xso-proc: Add the default flag to the element meta

This allows the payload to be absent, and requires the field type to be
Option<minidom::Element>.
This commit is contained in:
Emmanuel Gil Peyrot 2024-12-20 18:41:39 +01:00 committed by Jonas Schäfer
commit 1823afbc71
6 changed files with 107 additions and 6 deletions

View file

@ -14,7 +14,7 @@ use quote::quote;
use syn::*;
use crate::error_message::{self, ParentRef};
use crate::meta::AmountConstraint;
use crate::meta::{AmountConstraint, Flag};
use crate::scope::{AsItemsScope, FromEventsScope};
use crate::types::{
as_xml_iter_fn, default_fn, element_ty, from_events_fn, from_xml_builder_ty,
@ -25,6 +25,10 @@ use crate::types::{
use super::{Field, FieldBuilderPart, FieldIteratorPart, FieldTempInit, NestedMatcher};
pub(super) struct ElementField {
/// Flag indicating whether the value should be defaulted if the
/// child is absent.
pub(super) default_: Flag,
/// Number of child elements allowed.
pub(super) amount: AmountConstraint,
}
@ -58,8 +62,13 @@ impl Field for ElementField {
match self.amount {
AmountConstraint::FixedSingle(_) => {
let missing_msg = error_message::on_missing_child(container_name, member);
let on_absent = quote! {
return ::core::result::Result::Err(::xso::error::Error::Other(#missing_msg).into())
let on_absent = match self.default_ {
Flag::Absent => quote! {
return ::core::result::Result::Err(::xso::error::Error::Other(#missing_msg).into())
},
Flag::Present(_) => {
quote! { #default_fn() }
}
};
Ok(FieldBuilderPart::Nested {
extra_defs,

View file

@ -406,7 +406,12 @@ fn new_field(
}
#[cfg(feature = "minidom")]
XmlFieldMeta::Element { span, amount } => Ok(Box::new(ElementField {
XmlFieldMeta::Element {
span,
default_,
amount,
} => Ok(Box::new(ElementField {
default_,
amount: amount.unwrap_or(AmountConstraint::FixedSingle(span)),
})),

View file

@ -755,6 +755,9 @@ pub(crate) enum XmlFieldMeta {
/// This is useful for error messages.
span: Span,
/// The `default` flag.
default_: Flag,
/// The `n` flag.
amount: Option<AmountConstraint>,
},
@ -1035,9 +1038,16 @@ impl XmlFieldMeta {
/// Parse a `#[xml(element)]` meta.
fn element_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
let mut amount = None;
let mut default_ = Flag::Absent;
if meta.input.peek(syn::token::Paren) {
meta.parse_nested_meta(|meta| {
if meta.path.is_ident("n") {
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 if meta.path.is_ident("n") {
if amount.is_some() {
return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
}
@ -1050,6 +1060,7 @@ impl XmlFieldMeta {
}
Ok(Self::Element {
span: meta.path.span(),
default_,
amount,
})
}