Provide field context to Deserializer implementations

Also reorders deserialize() arguments.
This commit is contained in:
Dirkjan Ochtman 2023-02-22 16:04:58 +01:00
parent 7a2e6ac735
commit c983e10a88
5 changed files with 71 additions and 46 deletions

View File

@ -67,8 +67,9 @@ fn deserialize_scalar_enum(
}
fn deserialize<'cx>(
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
) -> Result<(), ::instant_xml::Error> {
use ::instant_xml::Error;
@ -104,6 +105,7 @@ fn deserialize_forward_enum(
}
let ident = &input.ident;
let field_str = format!("{ident}::0");
let mut matches = TokenStream::new();
let mut variants = TokenStream::new();
let mut borrowed = BTreeSet::new();
@ -145,7 +147,7 @@ fn deserialize_forward_enum(
variants.extend(
quote!(if <#no_lifetime_type as FromXml>::matches(id, None) {
let mut value = None;
<#no_lifetime_type as FromXml>::deserialize(deserializer, &mut value)?;
<#no_lifetime_type as FromXml>::deserialize(&mut value, #field_str, deserializer)?;
*into = value.map(#ident::#v_ident);
}),
);
@ -163,8 +165,9 @@ fn deserialize_forward_enum(
}
fn deserialize<'cx>(
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
) -> Result<(), ::instant_xml::Error> {
use ::instant_xml::de::Node;
use ::instant_xml::{Accumulate, Error, FromXml};
@ -284,8 +287,9 @@ fn deserialize_struct(
}
fn deserialize<'cx>(
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
) -> Result<(), ::instant_xml::Error> {
use ::instant_xml::de::Node;
use ::instant_xml::{Accumulate, Error, FromXml, Id, Kind};
@ -418,6 +422,7 @@ fn named_field(
})
.transpose()?;
let field_str = format!("{type_name}::{field_name}");
if !field_meta.attribute {
if let Some(with) = deserialize_with {
if field_meta.direct {
@ -430,14 +435,14 @@ fn named_field(
tokens.r#match.extend(quote!(
__Elements::#enum_name => {
let mut nested = deserializer.nested(data);
#with(&mut nested, &mut #enum_name)?;
#with(&mut #enum_name, #field_str, &mut nested)?;
},
));
} else if field_meta.direct {
direct.extend(quote!(
Node::Text(text) => {
let mut nested = deserializer.for_node(Node::Text(text));
<#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?;
<#no_lifetime_type>::deserialize(&mut #enum_name, #field_str, &mut nested)?;
}
));
} else {
@ -445,11 +450,11 @@ fn named_field(
__Elements::#enum_name => match <#no_lifetime_type as FromXml>::KIND {
Kind::Element => {
let mut nested = deserializer.nested(data);
<#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?;
<#no_lifetime_type>::deserialize(&mut #enum_name, #field_str, &mut nested)?;
}
Kind::Scalar => {
let mut nested = deserializer.nested(data);
<#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?;
<#no_lifetime_type>::deserialize(&mut #enum_name, #field_str, &mut nested)?;
nested.ignore()?;
}
},
@ -467,20 +472,19 @@ fn named_field(
tokens.r#match.extend(quote!(
__Attributes::#enum_name => {
let mut nested = deserializer.nested(data);
#with(&mut nested, &mut #enum_name)?;
#with(&mut #enum_name, #field_str, &mut nested)?;
},
));
} else {
tokens.r#match.extend(quote!(
__Attributes::#enum_name => {
let mut nested = deserializer.for_node(Node::AttributeValue(attr.value));
let new = <#no_lifetime_type as FromXml>::deserialize(&mut nested, &mut #enum_name)?;
let new = <#no_lifetime_type as FromXml>::deserialize(&mut #enum_name, #field_str, &mut nested)?;
},
));
}
}
let field_str = format!("{type_name}::{field_name}");
return_val.extend(quote!(
#field_name: #enum_name.try_done(#field_str)?,
));
@ -539,8 +543,9 @@ fn deserialize_tuple_struct(
}
fn deserialize<'cx>(
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
) -> Result<(), ::instant_xml::Error> {
use ::instant_xml::de::Node;
use ::instant_xml::{Accumulate, Error, FromXml, Id, Kind};
@ -578,7 +583,7 @@ fn unnamed_field(
Some(Ok(Node::Open(data))) => {
let mut nested = deserializer.nested(data);
let mut value = <#no_lifetime_type as FromXml>::Accumulator::default();
<#no_lifetime_type as FromXml>::deserialize(&mut nested, &mut value)?;
<#no_lifetime_type as FromXml>::deserialize(&mut value, #field_str, &mut nested)?;
nested.ignore()?;
value
}
@ -588,13 +593,12 @@ fn unnamed_field(
}
Kind::Scalar => {
let mut value = <#no_lifetime_type as FromXml>::Accumulator::default();
<#no_lifetime_type as FromXml>::deserialize(deserializer, &mut value)?;
<#no_lifetime_type as FromXml>::deserialize(&mut value, #field_str, deserializer)?;
value
}
};
));
let field_str = format!("{type_name}::{index}");
return_val.extend(quote!(
#name.try_done(#field_str)?,
));
@ -617,8 +621,9 @@ fn deserialize_unit_struct(input: &syn::DeriveInput, meta: &ContainerMeta) -> To
}
fn deserialize<'cx>(
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
) -> Result<(), ::instant_xml::Error> {
deserializer.ignore()?;
*into = Some(Self);

View File

@ -333,8 +333,9 @@ impl<'xml> Iterator for Context<'xml> {
}
pub fn borrow_cow_str<'xml>(
deserializer: &mut Deserializer<'_, 'xml>,
into: &mut Option<Cow<'xml, str>>,
_: &'static str,
deserializer: &mut Deserializer<'_, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
@ -349,8 +350,9 @@ pub fn borrow_cow_str<'xml>(
}
pub fn borrow_cow_slice_u8<'xml>(
deserializer: &mut Deserializer<'_, 'xml>,
into: &mut Option<Cow<'xml, [u8]>>,
_: &'static str,
deserializer: &mut Deserializer<'_, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);

View File

@ -48,8 +48,9 @@ impl<'xml, T: FromStr> FromXml<'xml> for FromXmlStr<T> {
}
fn deserialize(
deserializer: &mut Deserializer<'_, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'_, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
@ -66,7 +67,7 @@ impl<'xml, T: FromStr> FromXml<'xml> for FromXmlStr<T> {
Ok(())
}
Err(_) => Err(Error::UnexpectedValue(format!(
"unable to parse {} from `{value}`",
"unable to parse {} from `{value}` for {field}",
type_name::<T>()
))),
}
@ -86,8 +87,9 @@ impl<'xml> FromXml<'xml> for bool {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
@ -103,7 +105,7 @@ impl<'xml> FromXml<'xml> for bool {
"false" | "0" => false,
val => {
return Err(Error::UnexpectedValue(format!(
"unable to parse bool from '{val}'"
"unable to parse bool from '{val}' for {field}"
)))
}
};
@ -181,15 +183,16 @@ macro_rules! from_xml_for_number {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
}
let mut value = None;
FromXmlStr::<Self>::deserialize(deserializer, &mut value)?;
FromXmlStr::<Self>::deserialize(&mut value, field, deserializer)?;
if let Some(value) = value {
*into = Some(value.0);
}
@ -226,15 +229,16 @@ impl<'xml> FromXml<'xml> for char {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
}
let mut value = None;
FromXmlStr::<Self>::deserialize(deserializer, &mut value)?;
FromXmlStr::<Self>::deserialize(&mut value, field, deserializer)?;
if let Some(value) = value {
*into = Some(value.0);
}
@ -256,8 +260,9 @@ impl<'xml> FromXml<'xml> for String {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
_: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
@ -285,8 +290,9 @@ impl<'xml> FromXml<'xml> for &'xml str {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
@ -301,7 +307,7 @@ impl<'xml> FromXml<'xml> for &'xml str {
Cow::Borrowed(str) => *into = Some(str),
Cow::Owned(_) => {
return Err(Error::UnexpectedValue(format!(
"string with escape characters cannot be deserialized as &str: '{value}'",
"string with escape characters cannot be deserialized as &str for {field}: '{value}'",
)))
}
}
@ -327,16 +333,17 @@ where
}
fn deserialize(
deserializer: &mut Deserializer<'_, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'_, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
}
let mut value = <T::Owned as FromXml<'xml>>::Accumulator::default();
T::Owned::deserialize(deserializer, &mut value)?;
*into = Some(Cow::Owned(value.try_done("Cow<T>")?));
T::Owned::deserialize(&mut value, field, deserializer)?;
*into = Some(Cow::Owned(value.try_done(field)?));
Ok(())
}
@ -351,10 +358,11 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Option<T> {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
<T>::deserialize(deserializer, &mut into.value)?;
<T>::deserialize(&mut into.value, field, deserializer)?;
Ok(())
}
@ -567,12 +575,13 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Vec<T> {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
let mut value = T::Accumulator::default();
T::deserialize(deserializer, &mut value)?;
into.push(value.try_done("Vec<T>")?);
T::deserialize(&mut value, field, deserializer)?;
into.push(value.try_done(field)?);
Ok(())
}
@ -640,8 +649,9 @@ impl<'xml> FromXml<'xml> for DateTime<Utc> {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
_: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
@ -701,8 +711,9 @@ impl<'xml> FromXml<'xml> for NaiveDate {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
_: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
@ -736,8 +747,9 @@ impl<'xml> FromXml<'xml> for () {
}
fn deserialize<'cx>(
_: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
_: &'static str,
_: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
*into = Some(());
Ok(())
@ -767,15 +779,16 @@ impl<'xml> FromXml<'xml> for IpAddr {
}
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue);
}
let mut value = None;
FromXmlStr::<Self>::deserialize(deserializer, &mut value)?;
FromXmlStr::<Self>::deserialize(&mut value, field, deserializer)?;
if let Some(value) = value {
*into = Some(value.0);
}

View File

@ -40,8 +40,9 @@ pub trait FromXml<'xml>: Sized {
fn matches(id: Id<'_>, field: Option<Id<'_>>) -> bool;
fn deserialize<'cx>(
deserializer: &mut Deserializer<'cx, 'xml>,
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error>;
type Accumulator: Accumulate<Self>;
@ -86,8 +87,12 @@ pub fn from_str<'xml, T: FromXml<'xml>>(input: &'xml str) -> Result<T, Error> {
}
let mut value = T::Accumulator::default();
T::deserialize(&mut Deserializer::new(root, &mut context), &mut value)?;
value.try_done("root element")
T::deserialize(
&mut value,
"<root element>",
&mut Deserializer::new(root, &mut context),
)?;
value.try_done("<root element>")
}
pub fn to_string(value: &(impl ToXml + ?Sized)) -> Result<String, Error> {

View File

@ -31,7 +31,7 @@ fn escape_back() {
from_str(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str&amp;</str></StructSpecialEntities>"
),
Err::<StructSpecialEntities, _>(Error::UnexpectedValue("string with escape characters cannot be deserialized as &str: 'str&amp;'".to_owned()))
Err::<StructSpecialEntities, _>(Error::UnexpectedValue("string with escape characters cannot be deserialized as &str for StructSpecialEntities::str: 'str&amp;'".to_owned()))
);
// Borrowed