xso-proc: add support for optional children
This commit is contained in:
parent
5d284bbd3a
commit
01336802b4
6 changed files with 133 additions and 11 deletions
|
|
@ -152,7 +152,11 @@ enum FieldKind {
|
|||
},
|
||||
|
||||
/// The field maps to a child
|
||||
Child,
|
||||
Child {
|
||||
// Flag indicating whether the value should be defaulted if the
|
||||
// child is absent.
|
||||
default_: Flag,
|
||||
},
|
||||
}
|
||||
|
||||
impl FieldKind {
|
||||
|
|
@ -199,7 +203,7 @@ impl FieldKind {
|
|||
|
||||
XmlFieldMeta::Text { codec } => Ok(Self::Text { codec }),
|
||||
|
||||
XmlFieldMeta::Child => Ok(Self::Child),
|
||||
XmlFieldMeta::Child { default_ } => Ok(Self::Child { default_ }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -341,7 +345,7 @@ impl FieldDef {
|
|||
})
|
||||
}
|
||||
|
||||
FieldKind::Child => {
|
||||
FieldKind::Child { ref default_ } => {
|
||||
let FromEventsScope {
|
||||
ref substate_result,
|
||||
..
|
||||
|
|
@ -353,6 +357,18 @@ impl FieldDef {
|
|||
let from_events = from_events_fn(self.ty.clone());
|
||||
let from_xml_builder = from_xml_builder_ty(self.ty.clone());
|
||||
|
||||
let on_absent = match default_ {
|
||||
Flag::Absent => quote! {
|
||||
return ::core::result::Result::Err(::xso::error::Error::Other(#missing_msg).into())
|
||||
},
|
||||
Flag::Present(_) => {
|
||||
let default_ = default_fn(self.ty.clone());
|
||||
quote! {
|
||||
#default_()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(FieldBuilderPart::Nested {
|
||||
value: FieldTempInit {
|
||||
init: quote! { ::std::option::Option::None },
|
||||
|
|
@ -368,7 +384,7 @@ impl FieldDef {
|
|||
finalize: quote! {
|
||||
match #field_access {
|
||||
::std::option::Option::Some(value) => value,
|
||||
::std::option::Option::None => return ::core::result::Result::Err(::xso::error::Error::Other(#missing_msg).into()),
|
||||
::std::option::Option::None => #on_absent,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
@ -426,7 +442,7 @@ impl FieldDef {
|
|||
Ok(FieldIteratorPart::Text { generator })
|
||||
}
|
||||
|
||||
FieldKind::Child => {
|
||||
FieldKind::Child { default_: _ } => {
|
||||
let AsItemsScope { ref lifetime, .. } = scope;
|
||||
|
||||
let as_xml_iter = as_xml_iter_fn(self.ty.clone());
|
||||
|
|
|
|||
|
|
@ -318,7 +318,10 @@ pub(crate) enum XmlFieldMeta {
|
|||
},
|
||||
|
||||
/// `#[xml(child)`
|
||||
Child,
|
||||
Child {
|
||||
/// The `default` flag.
|
||||
default_: Flag,
|
||||
},
|
||||
}
|
||||
|
||||
impl XmlFieldMeta {
|
||||
|
|
@ -424,8 +427,26 @@ impl XmlFieldMeta {
|
|||
}
|
||||
|
||||
/// Parse a `#[xml(child)]` meta.
|
||||
fn child_from_meta(_: ParseNestedMeta<'_>) -> Result<Self> {
|
||||
Ok(Self::Child)
|
||||
fn child_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
|
||||
if meta.input.peek(syn::token::Paren) {
|
||||
let mut default_ = Flag::Absent;
|
||||
meta.parse_nested_meta(|meta| {
|
||||
if meta.path.is_ident("default") {
|
||||
if default_.is_set() {
|
||||
return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
|
||||
}
|
||||
default_ = (&meta.path).into();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new_spanned(meta.path, "unsupported key"))
|
||||
}
|
||||
})?;
|
||||
Ok(Self::Child { default_ })
|
||||
} else {
|
||||
Ok(Self::Child {
|
||||
default_: Flag::Absent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse [`Self`] from a nestd meta, switching on the identifier
|
||||
|
|
|
|||
Loading…
Reference in a new issue