{
fr_dict_attr_t const *to_free;
- /*
- * This only works for leaf nodes.
- */
- if (!fr_type_is_leaf(da->type)) return -1;
-
/*
* vp may be created from fr_pair_alloc_null(), in which case it has no da.
*/
- if (vp->da) {
+ if (vp->da && !vp->da->flags.is_raw) {
if (vp->da == da) return 0;
if (!fr_type_is_leaf(vp->vp_type)) return -1;
if ((da->type != vp->vp_type) && (fr_value_box_cast_in_place(vp, &vp->data, da->type, da) < 0)) return -1;
} else {
+ fr_assert(fr_type_is_leaf(vp->vp_type) || (fr_pair_list_num_elements(&vp->vp_group) == 0));
+
fr_value_box_init(&vp->data, da->type, da, false);
}
to_free = vp->da;
+ vp->da = da;
+
+ /*
+ * Only frees unknown fr_dict_attr_t's
+ */
+ fr_dict_unknown_free(&to_free);
/*
* Ensure we update the attribute index in the parent.
if (list) {
fr_pair_remove(list, vp);
- vp->da = da;
-
fr_pair_append(list, vp);
- } else {
- vp->da = da;
}
- /*
- * Only frees unknown fr_dict_attr_t's
- */
- fr_dict_unknown_free(&to_free);
-
return 0;
}
* If we force it to be raw, then only do that if it's not already unknown.
*/
if (is_raw && !da_unknown) {
- da_unknown = fr_dict_unknown_attr_afrom_da(ctx, da);
+ da_unknown = fr_dict_unknown_afrom_da(ctx, da);
if (!da_unknown) goto error;
da = da_unknown;
}
vp->op = op;
+ /*
+ * Peek ahead for structural elements which are raw. If the caller wants to parse them
+ * as a set of raw octets, then swap the data type to be octets.
+ */
+ if (is_raw && (p[0] == '0') && (p[1] == 'x') && (da->type != FR_TYPE_OCTETS)) {
+ fr_dict_unknown_free(&da_unknown);
+
+ da_unknown = fr_dict_unknown_attr_afrom_da(vp, vp->da);
+ if (!da_unknown) goto error;
+
+ fr_assert(da_unknown->type == FR_TYPE_OCTETS);
+
+ if (fr_pair_reinit_from_da(NULL, vp, da_unknown) < 0) goto error;
+
+ da = vp->da;
+ da_unknown = NULL; /* already parented from vp */
+ }
+
/*
* Allow grouping attributes.
*/