MEDIUM: stream: Make the `unique_id` member of `struct stream` a `struct ist`

The `unique_id` member of `struct stream` now is a `struct ist`.
diff --git a/include/proto/stream.h b/include/proto/stream.h
index e54ac60..69153df 100644
--- a/include/proto/stream.h
+++ b/include/proto/stream.h
@@ -66,7 +66,7 @@
 void stream_dump(struct buffer *buf, const struct stream *s, const char *pfx, char eol);
 void stream_dump_and_crash(enum obj_type *obj, int rate);
 
-int stream_generate_unique_id(struct stream *strm, struct list *format);
+struct ist stream_generate_unique_id(struct stream *strm, struct list *format);
 
 void stream_process_counters(struct stream *s);
 void sess_change_server(struct stream *sess, struct server *newsrv);
diff --git a/include/types/stream.h b/include/types/stream.h
index 90819e6..39a6855 100644
--- a/include/types/stream.h
+++ b/include/types/stream.h
@@ -177,7 +177,7 @@
 	int pcli_next_pid;                      /* next target PID to use for the CLI proxy */
 	int pcli_flags;                         /* flags for CLI proxy */
 
-	char *unique_id;                        /* custom unique ID */
+	struct ist unique_id;                   /* custom unique ID */
 
 	/* These two pointers are used to resume the execution of the rule lists. */
 	struct list *current_rule_list;         /* this is used to store the current executed rule list. */
diff --git a/src/http_ana.c b/src/http_ana.c
index 010b170..b9067dd 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -793,9 +793,9 @@
 	 * fetches only available in the HTTP request processing stage.
 	 */
 	if (!LIST_ISEMPTY(&sess->fe->format_unique_id)) {
-		int length;
+		struct ist unique_id = stream_generate_unique_id(s, &sess->fe->format_unique_id);
 
-		if ((length = stream_generate_unique_id(s, &sess->fe->format_unique_id)) < 0) {
+		if (!isttest(unique_id)) {
 			if (!(s->flags & SF_ERR_MASK))
 				s->flags |= SF_ERR_RESOURCE;
 			goto return_int_err;
@@ -803,7 +803,7 @@
 
 		/* send unique ID if a "unique-id-header" is defined */
 		if (isttest(sess->fe->header_unique_id) &&
-		    !http_add_header(htx, sess->fe->header_unique_id, ist2(s->unique_id, length)))
+		    unlikely(!http_add_header(htx, sess->fe->header_unique_id, s->unique_id)))
 				goto return_int_err;
 	}
 
@@ -5078,9 +5078,9 @@
 	pool_free(pool_head_requri, txn->uri);
 	pool_free(pool_head_capture, txn->cli_cookie);
 	pool_free(pool_head_capture, txn->srv_cookie);
-	pool_free(pool_head_uniqueid, s->unique_id);
+	pool_free(pool_head_uniqueid, s->unique_id.ptr);
 
-	s->unique_id = NULL;
+	s->unique_id = IST_NULL;
 	txn->uri = NULL;
 	txn->srv_cookie = NULL;
 	txn->cli_cookie = NULL;
diff --git a/src/http_fetch.c b/src/http_fetch.c
index 9113b5e..9cfcee2 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -409,17 +409,17 @@
 
 static int smp_fetch_uniqueid(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int length;
+	struct ist unique_id;
 
 	if (LIST_ISEMPTY(&smp->sess->fe->format_unique_id))
 		return 0;
 
-	length = stream_generate_unique_id(smp->strm, &smp->sess->fe->format_unique_id);
-	if (length < 0)
+	unique_id = stream_generate_unique_id(smp->strm, &smp->sess->fe->format_unique_id);
+	if (!isttest(unique_id))
 		return 0;
 
-	smp->data.u.str.area = smp->strm->unique_id;
-	smp->data.u.str.data = length;
+	smp->data.u.str.area = smp->strm->unique_id.ptr;
+	smp->data.u.str.data = smp->strm->unique_id.len;
 	smp->data.type = SMP_T_STR;
 	smp->flags = SMP_F_CONST;
 	return 1;
diff --git a/src/log.c b/src/log.c
index b46605b..8f502ac 100644
--- a/src/log.c
+++ b/src/log.c
@@ -2927,8 +2927,10 @@
 
 			case LOG_FMT_UNIQUEID: // %ID
 				ret = NULL;
-				src = s ? s->unique_id : NULL;
-				ret = lf_text(tmplog, src, maxsize - (tmplog - dst), tmp);
+				if (s)
+					ret = lf_text_len(tmplog, s->unique_id.ptr, s->unique_id.len, maxsize - (tmplog - dst), tmp);
+				else
+					ret = lf_text_len(tmplog, NULL, 0, maxsize - (tmplog - dst), tmp);
 				if (ret == NULL)
 					goto out;
 				tmplog = ret;
@@ -2982,7 +2984,7 @@
 	}
 
 	/* if unique-id was not generated */
-	if (!s->unique_id && !LIST_ISEMPTY(&sess->fe->format_unique_id)) {
+	if (!isttest(s->unique_id) && !LIST_ISEMPTY(&sess->fe->format_unique_id)) {
 		stream_generate_unique_id(s, &sess->fe->format_unique_id);
 	}
 
diff --git a/src/stream.c b/src/stream.c
index 331f24b..7b63f1d 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -170,8 +170,10 @@
 	/* General info about the stream (htx/tcp, id...) */
 	chunk_appendf(&trace_buf, " : [%u,%s]",
 		      s->uniq_id, ((s->flags & SF_HTX) ? "HTX" : "TCP"));
-	if (s->unique_id)
-		chunk_appendf(&trace_buf, " id=%s", s->unique_id);
+	if (isttest(s->unique_id)) {
+		chunk_appendf(&trace_buf, " id=");
+		b_putist(&trace_buf, s->unique_id);
+	}
 
 	/* Front and back stream-int state */
 	chunk_appendf(&trace_buf, " SI=(%s,%s)",
@@ -399,7 +401,7 @@
 	s->call_rate.curr_sec = s->call_rate.curr_ctr = s->call_rate.prev_ctr = 0;
 	s->pcli_next_pid = 0;
 	s->pcli_flags = 0;
-	s->unique_id = NULL;
+	s->unique_id = IST_NULL;
 
 	if ((t = task_new(tid_bit)) == NULL)
 		goto out_fail_alloc;
@@ -605,8 +607,8 @@
 		offer_buffers(NULL, tasks_run_queue);
 	}
 
-	pool_free(pool_head_uniqueid, s->unique_id);
-	s->unique_id = NULL;
+	pool_free(pool_head_uniqueid, s->unique_id.ptr);
+	s->unique_id = IST_NULL;
 
 	hlua_ctx_destroy(s->hlua);
 	s->hlua = NULL;
@@ -2663,25 +2665,28 @@
 }
 
 /* Generates a unique ID based on the given <format>, stores it in the given <strm> and
- * returns the length of the ID. -1 is returned on memory allocation failure.
+ * returns the unique ID.
+
+ * If this function fails to allocate memory IST_NULL is returned.
  *
- * If an ID is already stored within the stream nothing happens and length of the stored
- * ID is returned.
+ * If an ID is already stored within the stream nothing happens existing unique ID is
+ * returned.
  */
-int stream_generate_unique_id(struct stream *strm, struct list *format)
+struct ist stream_generate_unique_id(struct stream *strm, struct list *format)
 {
-	if (strm->unique_id != NULL) {
-		return strlen(strm->unique_id);
+	if (isttest(strm->unique_id)) {
+		return strm->unique_id;
 	}
 	else {
 		char *unique_id;
+		int length;
 		if ((unique_id = pool_alloc(pool_head_uniqueid)) == NULL)
-			return -1;
+			return IST_NULL;
 
-		strm->unique_id = unique_id;
-		strm->unique_id[0] = 0;
+		length = build_logline(strm, unique_id, UNIQUEID_LEN, format);
+		strm->unique_id = ist2(unique_id, length);
 
-		return build_logline(strm, strm->unique_id, UNIQUEID_LEN, format);
+		return strm->unique_id;
 	}
 }