mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
xso: refine handling of multiple #[xml(text)]
fields
Previously, we only enforced the existence of at most one `#[xml(text)]` field only at code generation time for `FromXml`. This change enforces it at parsing time, which is more consistent and allows for a clearer error message.
This commit is contained in:
parent
ae30221e3c
commit
46584f05f9
3 changed files with 34 additions and 7 deletions
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::*;
|
use syn::{spanned::Spanned, *};
|
||||||
|
|
||||||
use crate::error_message::ParentRef;
|
use crate::error_message::ParentRef;
|
||||||
use crate::field::{FieldBuilderPart, FieldDef, FieldIteratorPart, FieldTempInit};
|
use crate::field::{FieldBuilderPart, FieldDef, FieldIteratorPart, FieldTempInit};
|
||||||
|
@ -26,6 +26,7 @@ impl Compound {
|
||||||
/// Construct a compound from fields.
|
/// Construct a compound from fields.
|
||||||
pub(crate) fn from_fields(compound_fields: &Fields) -> Result<Self> {
|
pub(crate) fn from_fields(compound_fields: &Fields) -> Result<Self> {
|
||||||
let mut fields = Vec::with_capacity(compound_fields.len());
|
let mut fields = Vec::with_capacity(compound_fields.len());
|
||||||
|
let mut text_field = None;
|
||||||
for (i, field) in compound_fields.iter().enumerate() {
|
for (i, field) in compound_fields.iter().enumerate() {
|
||||||
let index = match i.try_into() {
|
let index = match i.try_into() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
|
@ -38,7 +39,24 @@ impl Compound {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fields.push(FieldDef::from_field(field, index)?);
|
let field = FieldDef::from_field(field, index)?;
|
||||||
|
|
||||||
|
if field.is_text_field() {
|
||||||
|
if let Some(other_field) = text_field.as_ref() {
|
||||||
|
let mut err = Error::new_spanned(
|
||||||
|
field.member(),
|
||||||
|
"only one `#[xml(text)]` field allowed per compound",
|
||||||
|
);
|
||||||
|
err.combine(Error::new(
|
||||||
|
*other_field,
|
||||||
|
"the other `#[xml(text)]` field is here",
|
||||||
|
));
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
text_field = Some(field.member().span())
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.push(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self { fields })
|
Ok(Self { fields })
|
||||||
|
@ -104,10 +122,9 @@ impl Compound {
|
||||||
finalize,
|
finalize,
|
||||||
} => {
|
} => {
|
||||||
if text_handler.is_some() {
|
if text_handler.is_some() {
|
||||||
return Err(Error::new_spanned(
|
// the existence of only one text handler is enforced
|
||||||
field.member(),
|
// by Compound's constructor(s).
|
||||||
"more than one field attempts to collect text data",
|
panic!("more than one field attempts to collect text data");
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
builder_data_def.extend(quote! {
|
builder_data_def.extend(quote! {
|
||||||
|
|
|
@ -329,4 +329,12 @@ impl FieldDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if this field's parsing consumes text data.
|
||||||
|
pub(crate) fn is_text_field(&self) -> bool {
|
||||||
|
match self.kind {
|
||||||
|
FieldKind::Text { .. } => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,9 @@ The `text` meta causes the field to be mapped to the text content of the
|
||||||
element. For `FromXml`, the field's type must implement [`FromXmlText`] and
|
element. For `FromXml`, the field's type must implement [`FromXmlText`] and
|
||||||
for `IntoXml`, the field's type must implement [`IntoXmlText`].
|
for `IntoXml`, the field's type must implement [`IntoXmlText`].
|
||||||
|
|
||||||
The `text` meta supports no options or value.
|
The `text` meta supports no options or value. Only a single field per struct
|
||||||
|
may be annotated with `#[xml(text)]` at a time, to avoid parsing ambiguities.
|
||||||
|
This is also true if only `IntoXml` is derived on a field, for consistency.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue