Skip to content

Commit

Permalink
- Changed from flatten to rest.
Browse files Browse the repository at this point in the history
- Added error when using unknown_fields = deny
  • Loading branch information
NicholasLYang committed May 9, 2024
1 parent e250dd8 commit ae242f2
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 25 deletions.
51 changes: 30 additions & 21 deletions crates/biome_deserialize_macros/src/deserializable_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl DeriveInput {
}
Data::Struct(data) => {
if data.fields.iter().all(|field| field.ident.is_some()) {
let mut flatten_field = None;
let mut rest_field = None;
let fields = data
.fields
.into_iter()
Expand All @@ -85,14 +85,14 @@ impl DeriveInput {
.rename
.unwrap_or_else(|| Case::Camel.convert(&ident.to_string()));

if flatten_field.is_some() && attrs.flatten {
if rest_field.is_some() && attrs.rest {
abort!(
ident,
"Cannot have multiple fields with #[deserializable(flatten)]"
"Cannot have multiple fields with #[deserializable(rest)]"
)
}
if attrs.flatten {
flatten_field = Some(ident.clone());
if attrs.rest {
rest_field = Some(ident.clone());
}

DeserializableFieldData {
Expand All @@ -108,9 +108,18 @@ impl DeriveInput {
})
.collect();

if rest_field.is_some()
&& matches!(attrs.unknown_fields, Some(UnknownFields::Deny))
{
abort!(
rest_field.unwrap(),
"Cannot have a field with #[deserializable(rest)] and #[deserializable(unknown_fields = \"deny\")]"
)
}

DeserializableData::Struct(DeserializableStructData {
fields,
flatten_field,
rest_field,
with_validator: attrs.with_validator,
unknown_fields: attrs.unknown_fields.unwrap_or_default(),
})
Expand Down Expand Up @@ -163,7 +172,7 @@ pub struct DeserializableNewtypeData {
#[derive(Debug)]
pub struct DeserializableStructData {
fields: Vec<DeserializableFieldData>,
flatten_field: Option<Ident>,
rest_field: Option<Ident>,
with_validator: bool,
unknown_fields: UnknownFields,
}
Expand Down Expand Up @@ -428,7 +437,7 @@ fn generate_deserializable_struct(
} else {
validator
};
let unknown_key_handler = if data.flatten_field.is_some() {
let unknown_key_handler = if data.rest_field.is_some() {
quote! {
unknown_key => {
let key_text = Text::deserialize(&key, "", diagnostics)?;
Expand Down Expand Up @@ -459,19 +468,19 @@ fn generate_deserializable_struct(
}
};

let (unknown_fields_initializer, collect_unknown_fields) =
if let Some(field) = data.flatten_field {
(
quote! {
let mut unknown_fields = vec![];
},
quote! {
result.#field = unknown_fields.into_iter().collect();
},
)
} else {
(quote! {}, quote! {})
};
let (unknown_fields_initializer, collect_unknown_fields) = if let Some(field) = data.rest_field
{
(
quote! {
let mut unknown_fields = vec![];
},
quote! {
result.#field = unknown_fields.into_iter().collect();
},
)
} else {
(quote! {}, quote! {})
};

let tuple_type = generate_generics_tuple(&generics);
let trait_bounds = generate_trait_bounds(&generics);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub struct StructFieldAttrs {
/// Optional validation function to be called on the field value.
pub validate: Option<Path>,

/// Flattens the field into the parent object.
pub flatten: bool,
/// Uses the field as a catch-all for unknown entries in the map
pub rest: bool,
}

#[derive(Clone, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -65,8 +65,8 @@ impl TryFrom<&Vec<Attribute>> for StructFieldAttrs {
opts.passthrough_name = true;
} else if path.is_ident("bail_on_error") {
opts.bail_on_error = true;
} else if path.is_ident("flatten") {
opts.flatten = true;
} else if path.is_ident("rest") {
opts.rest = true;
} else {
let path_str = path.to_token_stream().to_string();
return Err(Error::new(
Expand Down

0 comments on commit ae242f2

Please sign in to comment.