Use associated accumulator type to deserialize into
This commit is contained in:
parent
be7902925e
commit
7a2e6ac735
|
@ -68,7 +68,7 @@ fn deserialize_scalar_enum(
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), ::instant_xml::Error> {
|
) -> Result<(), ::instant_xml::Error> {
|
||||||
use ::instant_xml::Error;
|
use ::instant_xml::Error;
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ fn deserialize_scalar_enum(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Scalar;
|
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Scalar;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -163,10 +164,10 @@ fn deserialize_forward_enum(
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), ::instant_xml::Error> {
|
) -> Result<(), ::instant_xml::Error> {
|
||||||
use ::instant_xml::de::Node;
|
use ::instant_xml::de::Node;
|
||||||
use ::instant_xml::{Error, FromXml};
|
use ::instant_xml::{Accumulate, Error, FromXml};
|
||||||
|
|
||||||
let id = deserializer.parent();
|
let id = deserializer.parent();
|
||||||
#variants else {
|
#variants else {
|
||||||
|
@ -180,6 +181,7 @@ fn deserialize_forward_enum(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -283,10 +285,10 @@ fn deserialize_struct(
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), ::instant_xml::Error> {
|
) -> Result<(), ::instant_xml::Error> {
|
||||||
use ::instant_xml::de::Node;
|
use ::instant_xml::de::Node;
|
||||||
use ::instant_xml::{Error, FromXml, Id, Kind};
|
use ::instant_xml::{Accumulate, Error, FromXml, Id, Kind};
|
||||||
|
|
||||||
enum __Elements {
|
enum __Elements {
|
||||||
#elements_enum
|
#elements_enum
|
||||||
|
@ -336,6 +338,7 @@ fn deserialize_struct(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -399,7 +402,7 @@ fn named_field(
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_values.extend(quote!(
|
declare_values.extend(quote!(
|
||||||
let mut #enum_name: Option<#no_lifetime_type> = None;
|
let mut #enum_name = <#no_lifetime_type as FromXml>::Accumulator::default();
|
||||||
));
|
));
|
||||||
|
|
||||||
let deserialize_with = field_meta
|
let deserialize_with = field_meta
|
||||||
|
@ -434,7 +437,7 @@ fn named_field(
|
||||||
direct.extend(quote!(
|
direct.extend(quote!(
|
||||||
Node::Text(text) => {
|
Node::Text(text) => {
|
||||||
let mut nested = deserializer.for_node(Node::Text(text));
|
let mut nested = deserializer.for_node(Node::Text(text));
|
||||||
FromXml::deserialize(&mut nested, &mut #enum_name)?;
|
<#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?;
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
@ -442,11 +445,11 @@ fn named_field(
|
||||||
__Elements::#enum_name => match <#no_lifetime_type as FromXml>::KIND {
|
__Elements::#enum_name => match <#no_lifetime_type as FromXml>::KIND {
|
||||||
Kind::Element => {
|
Kind::Element => {
|
||||||
let mut nested = deserializer.nested(data);
|
let mut nested = deserializer.nested(data);
|
||||||
FromXml::deserialize(&mut nested, &mut #enum_name)?;
|
<#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?;
|
||||||
}
|
}
|
||||||
Kind::Scalar => {
|
Kind::Scalar => {
|
||||||
let mut nested = deserializer.nested(data);
|
let mut nested = deserializer.nested(data);
|
||||||
FromXml::deserialize(&mut nested, &mut #enum_name)?;
|
<#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?;
|
||||||
nested.ignore()?;
|
nested.ignore()?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -479,10 +482,7 @@ fn named_field(
|
||||||
|
|
||||||
let field_str = format!("{type_name}::{field_name}");
|
let field_str = format!("{type_name}::{field_name}");
|
||||||
return_val.extend(quote!(
|
return_val.extend(quote!(
|
||||||
#field_name: match #enum_name {
|
#field_name: #enum_name.try_done(#field_str)?,
|
||||||
Some(v) => v,
|
|
||||||
None => <#no_lifetime_type as FromXml>::missing(#field_str)?,
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -540,10 +540,10 @@ fn deserialize_tuple_struct(
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), ::instant_xml::Error> {
|
) -> Result<(), ::instant_xml::Error> {
|
||||||
use ::instant_xml::de::Node;
|
use ::instant_xml::de::Node;
|
||||||
use ::instant_xml::{Error, FromXml, Id, Kind};
|
use ::instant_xml::{Accumulate, Error, FromXml, Id, Kind};
|
||||||
|
|
||||||
#declare_values
|
#declare_values
|
||||||
deserializer.ignore()?;
|
deserializer.ignore()?;
|
||||||
|
@ -552,6 +552,7 @@ fn deserialize_tuple_struct(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -576,7 +577,7 @@ fn unnamed_field(
|
||||||
Kind::Element => match deserializer.next() {
|
Kind::Element => match deserializer.next() {
|
||||||
Some(Ok(Node::Open(data))) => {
|
Some(Ok(Node::Open(data))) => {
|
||||||
let mut nested = deserializer.nested(data);
|
let mut nested = deserializer.nested(data);
|
||||||
let mut value: Option<#no_lifetime_type> = None;
|
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 nested, &mut value)?;
|
||||||
nested.ignore()?;
|
nested.ignore()?;
|
||||||
value
|
value
|
||||||
|
@ -586,7 +587,7 @@ fn unnamed_field(
|
||||||
None => return Err(Error::MissingValue(#field_str)),
|
None => return Err(Error::MissingValue(#field_str)),
|
||||||
}
|
}
|
||||||
Kind::Scalar => {
|
Kind::Scalar => {
|
||||||
let mut value: Option<#no_lifetime_type> = None;
|
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(deserializer, &mut value)?;
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
@ -595,10 +596,7 @@ fn unnamed_field(
|
||||||
|
|
||||||
let field_str = format!("{type_name}::{index}");
|
let field_str = format!("{type_name}::{index}");
|
||||||
return_val.extend(quote!(
|
return_val.extend(quote!(
|
||||||
match #name {
|
#name.try_done(#field_str)?,
|
||||||
Some(v) => v,
|
|
||||||
None => <#no_lifetime_type as FromXml>::missing(#field_str)?,
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,13 +618,14 @@ fn deserialize_unit_struct(input: &syn::DeriveInput, meta: &ContainerMeta) -> To
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
deserializer: &mut ::instant_xml::Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), ::instant_xml::Error> {
|
) -> Result<(), ::instant_xml::Error> {
|
||||||
deserializer.ignore()?;
|
deserializer.ignore()?;
|
||||||
*into = Some(Self);
|
*into = Some(Self);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::any::type_name;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::{any::type_name, marker::PhantomData};
|
||||||
|
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
use chrono::{DateTime, NaiveDate, Utc};
|
use chrono::{DateTime, NaiveDate, Utc};
|
||||||
|
|
||||||
use crate::{Deserializer, Error, FromXml, Id, Kind, Serializer, ToXml};
|
use crate::{Accumulate, Deserializer, Error, FromXml, Id, Kind, Serializer, ToXml};
|
||||||
|
|
||||||
// Deserializer
|
// Deserializer
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ impl<'xml, T: FromStr> FromXml<'xml> for FromXmlStr<T> {
|
||||||
|
|
||||||
fn deserialize(
|
fn deserialize(
|
||||||
deserializer: &mut Deserializer<'_, 'xml>,
|
deserializer: &mut Deserializer<'_, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -72,6 +72,7 @@ impl<'xml, T: FromStr> FromXml<'xml> for FromXmlStr<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<FromXmlStr<T>>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ impl<'xml> FromXml<'xml> for bool {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -111,6 +112,7 @@ impl<'xml> FromXml<'xml> for bool {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<bool>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +182,7 @@ macro_rules! from_xml_for_number {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -195,6 +197,7 @@ macro_rules! from_xml_for_number {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -224,7 +227,7 @@ impl<'xml> FromXml<'xml> for char {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -239,6 +242,7 @@ impl<'xml> FromXml<'xml> for char {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +257,7 @@ impl<'xml> FromXml<'xml> for String {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -267,6 +271,7 @@ impl<'xml> FromXml<'xml> for String {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<String>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +286,7 @@ impl<'xml> FromXml<'xml> for &'xml str {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -304,6 +309,7 @@ impl<'xml> FromXml<'xml> for &'xml str {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<&'xml str>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,21 +328,19 @@ where
|
||||||
|
|
||||||
fn deserialize(
|
fn deserialize(
|
||||||
deserializer: &mut Deserializer<'_, 'xml>,
|
deserializer: &mut Deserializer<'_, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut value = None;
|
let mut value = <T::Owned as FromXml<'xml>>::Accumulator::default();
|
||||||
T::Owned::deserialize(deserializer, &mut value)?;
|
T::Owned::deserialize(deserializer, &mut value)?;
|
||||||
if let Some(value) = value {
|
*into = Some(Cow::Owned(value.try_done("Cow<T>")?));
|
||||||
*into = Some(Cow::Owned(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Cow<'a, T>>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,29 +352,37 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Option<T> {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match into.as_mut() {
|
<T>::deserialize(deserializer, &mut into.value)?;
|
||||||
Some(value) => {
|
|
||||||
<T>::deserialize(deserializer, value)?;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let mut value = None;
|
|
||||||
<T>::deserialize(deserializer, &mut value)?;
|
|
||||||
if let Some(value) = value {
|
|
||||||
*into = Some(Some(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing(_: &'static str) -> Result<Self, Error> {
|
type Accumulator = OptionAccumulator<T, T::Accumulator>;
|
||||||
Ok(None)
|
const KIND: Kind = <T>::KIND;
|
||||||
}
|
}
|
||||||
|
|
||||||
const KIND: Kind = <T>::KIND;
|
pub struct OptionAccumulator<T, A: Accumulate<T>> {
|
||||||
|
value: A,
|
||||||
|
marker: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, A: Accumulate<T>> Default for OptionAccumulator<T, A> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
value: A::default(),
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, A: Accumulate<T>> Accumulate<Option<T>> for OptionAccumulator<T, A> {
|
||||||
|
fn try_done(self, field: &'static str) -> Result<Option<T>, Error> {
|
||||||
|
match self.value.try_done(field) {
|
||||||
|
Ok(value) => Ok(Some(value)),
|
||||||
|
Err(_) => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
to_xml_for_number!(i8);
|
to_xml_for_number!(i8);
|
||||||
|
@ -556,22 +568,15 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Vec<T> {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut value = None;
|
let mut value = T::Accumulator::default();
|
||||||
T::deserialize(deserializer, &mut value)?;
|
T::deserialize(deserializer, &mut value)?;
|
||||||
let dst = into.get_or_insert(Vec::new());
|
into.push(value.try_done("Vec<T>")?);
|
||||||
if let Some(value) = value {
|
|
||||||
dst.push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing(_: &'static str) -> Result<Self, Error> {
|
type Accumulator = Vec<T>;
|
||||||
Ok(Vec::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
const KIND: Kind = T::KIND;
|
const KIND: Kind = T::KIND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,7 +641,7 @@ impl<'xml> FromXml<'xml> for DateTime<Utc> {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -656,6 +661,7 @@ impl<'xml> FromXml<'xml> for DateTime<Utc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,7 +702,7 @@ impl<'xml> FromXml<'xml> for NaiveDate {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -716,6 +722,7 @@ impl<'xml> FromXml<'xml> for NaiveDate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,12 +737,13 @@ impl<'xml> FromXml<'xml> for () {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
_: &mut Deserializer<'cx, 'xml>,
|
_: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
*into = Some(());
|
*into = Some(());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,7 +768,7 @@ impl<'xml> FromXml<'xml> for IpAddr {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if into.is_some() {
|
if into.is_some() {
|
||||||
return Err(Error::DuplicateValue);
|
return Err(Error::DuplicateValue);
|
||||||
|
@ -775,6 +783,7 @@ impl<'xml> FromXml<'xml> for IpAddr {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Accumulator = Option<Self>;
|
||||||
const KIND: Kind = Kind::Scalar;
|
const KIND: Kind = Kind::Scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,16 +41,34 @@ pub trait FromXml<'xml>: Sized {
|
||||||
|
|
||||||
fn deserialize<'cx>(
|
fn deserialize<'cx>(
|
||||||
deserializer: &mut Deserializer<'cx, 'xml>,
|
deserializer: &mut Deserializer<'cx, 'xml>,
|
||||||
into: &mut Option<Self>,
|
into: &mut Self::Accumulator,
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
// If the missing field is of type `Option<T>` then treat is as `None`,
|
type Accumulator: Accumulate<Self>;
|
||||||
// otherwise it is an error.
|
const KIND: Kind;
|
||||||
fn missing(field: &'static str) -> Result<Self, Error> {
|
|
||||||
Err(Error::MissingValue(field))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const KIND: Kind;
|
/// A type implementing `Accumulate<T>` is used to accumulate a value of type `T`.
|
||||||
|
pub trait Accumulate<T>: Default {
|
||||||
|
fn try_done(self, field: &'static str) -> Result<T, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Accumulate<T> for Option<T> {
|
||||||
|
fn try_done(self, field: &'static str) -> Result<T, Error> {
|
||||||
|
self.ok_or(Error::MissingValue(field))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Accumulate<Vec<T>> for Vec<T> {
|
||||||
|
fn try_done(self, _: &'static str) -> Result<Vec<T>, Error> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Accumulate<Option<T>> for Option<T> {
|
||||||
|
fn try_done(self, _: &'static str) -> Result<Option<T>, Error> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_str<'xml, T: FromXml<'xml>>(input: &'xml str) -> Result<T, Error> {
|
pub fn from_str<'xml, T: FromXml<'xml>>(input: &'xml str) -> Result<T, Error> {
|
||||||
|
@ -67,12 +85,9 @@ pub fn from_str<'xml, T: FromXml<'xml>>(input: &'xml str) -> Result<T, Error> {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut value = None;
|
let mut value = T::Accumulator::default();
|
||||||
T::deserialize(&mut Deserializer::new(root, &mut context), &mut value)?;
|
T::deserialize(&mut Deserializer::new(root, &mut context), &mut value)?;
|
||||||
match value {
|
value.try_done("root element")
|
||||||
Some(value) => Ok(value),
|
|
||||||
None => T::missing("<root>"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(value: &(impl ToXml + ?Sized)) -> Result<String, Error> {
|
pub fn to_string(value: &(impl ToXml + ?Sized)) -> Result<String, Error> {
|
||||||
|
|
Loading…
Reference in New Issue