fr_assert(0);
}
+ /*
+ * Apply a cast to the results if required.
+ */
+ if (tmpl_rules_cast(node->vpt) != FR_TYPE_NULL) {
+ fr_type_t cast = tmpl_rules_cast(node->vpt);
+ fr_value_box_t *vb;
+ bool tainted;
+
+ vb = fr_dlist_head(&result);
+
+ switch (cast) {
+ case FR_TYPE_STRING:
+ case FR_TYPE_OCTETS:
+ if (fr_value_box_list_concat_in_place(vb, vb, &result, cast,
+ FR_VALUE_BOX_LIST_FREE_BOX, true, SIZE_MAX) < 0) {
+ goto fail;
+ }
+ break;
+
+ default:
+ /*
+ * One box, we cast it as the destination type.
+ *
+ * Many boxes, turn them into strings, and try to parse it as the
+ * output type.
+ */
+ if (!fr_dlist_next(&result, vb)) {
+ if (fr_value_box_cast_in_place(vb, vb, cast, NULL) < 0) goto fail;
+
+ } else {
+ ssize_t slen, vlen;
+ fr_sbuff_t *agg;
+
+ FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 256, 256);
+
+ slen = fr_value_box_list_concat_as_string(&tainted, agg, &result, NULL, 0, NULL,
+ FR_VALUE_BOX_LIST_FREE_BOX, true);
+ if (slen < 0) goto fail;
+
+ MEM(vb = fr_value_box_alloc_null(ctx));
+ vlen = fr_value_box_from_str(vb, vb, cast, NULL,
+ fr_sbuff_start(agg), fr_sbuff_used(agg),
+ NULL, tainted);
+ if ((vlen < 0) || (slen != vlen)) goto fail;
+
+ fr_dlist_insert_tail(&result, vb);
+ }
+ break;
+
+ case FR_TYPE_STRUCTURAL:
+ fr_assert(0);
+ goto fail;
+ }
+ }
+
xlat_debug_log_list_result(request, &result);
fr_dlist_move(out->dlist, &result);
continue;