Simplify FromXml::KIND const

This commit is contained in:
Dirkjan Ochtman 2022-11-29 16:31:26 +01:00
parent 4eafa193bd
commit 0a323ba302
6 changed files with 45 additions and 73 deletions

View File

@ -84,7 +84,7 @@ fn deserialize_scalar_enum(
Ok(()) Ok(())
} }
const KIND: ::instant_xml::Kind<'static> = ::instant_xml::Kind::Scalar; const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Scalar;
} }
) )
} }
@ -142,7 +142,7 @@ fn deserialize_wrapped_enum(
} }
let name = meta.tag(); let name = meta.tag();
let default_namespace = meta.default_namespace(); let default_ns = meta.default_namespace();
let generics = meta.xml_generics(borrowed); let generics = meta.xml_generics(borrowed);
let (xml_impl_generics, _, _) = generics.split_for_impl(); let (xml_impl_generics, _, _) = generics.split_for_impl();
let (_, ty_generics, where_clause) = input.generics.split_for_impl(); let (_, ty_generics, where_clause) = input.generics.split_for_impl();
@ -150,10 +150,7 @@ fn deserialize_wrapped_enum(
impl #xml_impl_generics FromXml<'xml> for #ident #ty_generics #where_clause { impl #xml_impl_generics FromXml<'xml> for #ident #ty_generics #where_clause {
#[inline] #[inline]
fn matches(id: ::instant_xml::Id<'_>, field: Option<::instant_xml::Id<'_>>) -> bool { fn matches(id: ::instant_xml::Id<'_>, field: Option<::instant_xml::Id<'_>>) -> bool {
match field { id == ::instant_xml::Id { name: #name, ns: #default_ns }
Some(field) => id == field,
None => false,
}
} }
fn deserialize<'cx>( fn deserialize<'cx>(
@ -165,7 +162,7 @@ fn deserialize_wrapped_enum(
let node = match deserializer.next() { let node = match deserializer.next() {
Some(result) => result?, Some(result) => result?,
None => return Err(Error::MissingValue(&<Self as FromXml>::KIND)), None => return Err(Error::MissingValue(Self::KIND)),
}; };
let data = match node { let data = match node {
@ -185,10 +182,7 @@ fn deserialize_wrapped_enum(
Ok(()) Ok(())
} }
const KIND: ::instant_xml::Kind<'static> = ::instant_xml::Kind::Element(::instant_xml::Id { const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
ns: #default_namespace,
name: #name,
});
} }
) )
} }
@ -336,10 +330,7 @@ fn deserialize_struct(
Ok(()) Ok(())
} }
const KIND: ::instant_xml::Kind<'static> = ::instant_xml::Kind::Element(::instant_xml::Id { const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
ns: #default_namespace,
name: #name,
});
} }
) )
} }
@ -441,8 +432,8 @@ fn named_field(
)); ));
} else { } else {
tokens.r#match.extend(quote!( tokens.r#match.extend(quote!(
__Elements::#enum_name => match <#no_lifetime_type as FromXml>::KIND { __Elements::#enum_name => match <#no_lifetime_type>::KIND {
Kind::Element(_) => { Kind::Element => {
let mut nested = deserializer.nested(data); let mut nested = deserializer.nested(data);
FromXml::deserialize(&mut nested, &mut #enum_name)?; FromXml::deserialize(&mut nested, &mut #enum_name)?;
} }
@ -552,10 +543,7 @@ fn deserialize_tuple_struct(
Ok(()) Ok(())
} }
const KIND: ::instant_xml::Kind<'static> = ::instant_xml::Kind::Element(::instant_xml::Id { const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
ns: #default_namespace,
name: #name,
});
} }
) )
} }
@ -574,7 +562,7 @@ fn unnamed_field(
let name = Ident::new(&format!("v{index}"), Span::call_site()); let name = Ident::new(&format!("v{index}"), Span::call_site());
declare_values.extend(quote!( declare_values.extend(quote!(
let #name = match <#no_lifetime_type as FromXml>::KIND { let #name = match <#no_lifetime_type as FromXml>::KIND {
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: Option<#no_lifetime_type> = None;
@ -584,7 +572,7 @@ fn unnamed_field(
} }
Some(Ok(node)) => return Err(Error::UnexpectedNode(format!("{:?}", node))), Some(Ok(node)) => return Err(Error::UnexpectedNode(format!("{:?}", node))),
Some(Err(e)) => return Err(e), Some(Err(e)) => return Err(e),
None => return Err(Error::MissingValue(&<#no_lifetime_type as FromXml>::KIND)), None => return Err(Error::MissingValue(<#no_lifetime_type as FromXml>::KIND)),
} }
Kind::Scalar => { Kind::Scalar => {
let mut value: Option<#no_lifetime_type> = None; let mut value: Option<#no_lifetime_type> = None;
@ -627,10 +615,7 @@ fn deserialize_unit_struct(input: &syn::DeriveInput, meta: &ContainerMeta) -> To
Ok(()) Ok(())
} }
const KIND: ::instant_xml::Kind<'static> = ::instant_xml::Kind::Element(::instant_xml::Id { const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element;
ns: #default_namespace,
name: #name,
});
} }
) )
} }

View File

@ -36,7 +36,7 @@ impl<'cx, 'xml> Deserializer<'cx, 'xml> {
Some(Ok(Node::Text(s))) => Ok(s), Some(Ok(Node::Text(s))) => Ok(s),
Some(Ok(node)) => Err(Error::ExpectedScalar(format!("{node:?}"))), Some(Ok(node)) => Err(Error::ExpectedScalar(format!("{node:?}"))),
Some(Err(e)) => Err(e), Some(Err(e)) => Err(e),
None => Err(Error::MissingValue(&Kind::Scalar)), None => Err(Error::MissingValue(Kind::Scalar)),
} }
} }

View File

@ -38,7 +38,7 @@ impl<'xml, T: FromStr> FromXml<'xml> for FromXmlStr<T> {
} }
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
impl<'xml> FromXml<'xml> for bool { impl<'xml> FromXml<'xml> for bool {
@ -65,11 +65,11 @@ impl<'xml> FromXml<'xml> for bool {
*into = Some(value.0); *into = Some(value.0);
Ok(()) Ok(())
} }
None => Err(Error::MissingValue(&Kind::Scalar)), None => Err(Error::MissingValue(Kind::Scalar)),
} }
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
// Serializer // Serializer
@ -142,11 +142,11 @@ macro_rules! from_xml_for_number {
*into = Some(value.0); *into = Some(value.0);
Ok(()) Ok(())
} }
None => Err(Error::MissingValue(&Kind::Scalar)), None => Err(Error::MissingValue(Kind::Scalar)),
} }
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
}; };
} }
@ -188,11 +188,11 @@ impl<'xml> FromXml<'xml> for char {
*into = Some(value.0); *into = Some(value.0);
Ok(()) Ok(())
} }
None => Err(Error::MissingValue(&Kind::Scalar)), None => Err(Error::MissingValue(Kind::Scalar)),
} }
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
impl<'xml> FromXml<'xml> for String { impl<'xml> FromXml<'xml> for String {
@ -217,7 +217,7 @@ impl<'xml> FromXml<'xml> for String {
Ok(()) Ok(())
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
impl<'xml> FromXml<'xml> for &'xml str { impl<'xml> FromXml<'xml> for &'xml str {
@ -250,7 +250,7 @@ impl<'xml> FromXml<'xml> for &'xml str {
Ok(()) Ok(())
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
impl<'xml, 'a, T: ?Sized> FromXml<'xml> for Cow<'a, T> impl<'xml, 'a, T: ?Sized> FromXml<'xml> for Cow<'a, T>
@ -281,11 +281,11 @@ where
*into = Some(Cow::Owned(value)); *into = Some(Cow::Owned(value));
Ok(()) Ok(())
} }
None => Err(Error::MissingValue(&Kind::Scalar)), None => Err(Error::MissingValue(Kind::Scalar)),
} }
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Option<T> { impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Option<T> {
@ -303,7 +303,7 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Option<T> {
<T>::deserialize(deserializer, value)?; <T>::deserialize(deserializer, value)?;
match value { match value {
Some(_) => Ok(()), Some(_) => Ok(()),
None => Err(Error::MissingValue(&<T as FromXml<'_>>::KIND)), None => Err(Error::MissingValue(<T as FromXml<'_>>::KIND)),
} }
} }
None => { None => {
@ -314,7 +314,7 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Option<T> {
*into = Some(Some(value)); *into = Some(Some(value));
Ok(()) Ok(())
} }
None => Err(Error::MissingValue(&<T as FromXml<'_>>::KIND)), None => Err(Error::MissingValue(<T as FromXml<'_>>::KIND)),
} }
} }
} }
@ -324,7 +324,7 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Option<T> {
Ok(None) Ok(None)
} }
const KIND: Kind<'static> = <T>::KIND; const KIND: Kind = <T>::KIND;
} }
to_xml_for_number!(i8); to_xml_for_number!(i8);
@ -514,7 +514,7 @@ impl<'xml, T: FromXml<'xml>> FromXml<'xml> for Vec<T> {
Ok(Vec::new()) Ok(Vec::new())
} }
const KIND: Kind<'static> = T::KIND; const KIND: Kind = T::KIND;
} }
impl<T: ToXml> ToXml for Vec<T> { impl<T: ToXml> ToXml for Vec<T> {
@ -584,7 +584,7 @@ impl<'xml> FromXml<'xml> for DateTime<Utc> {
} }
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
impl<'xml> FromXml<'xml> for () { impl<'xml> FromXml<'xml> for () {
@ -604,7 +604,7 @@ impl<'xml> FromXml<'xml> for () {
Ok(()) Ok(())
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }
impl ToXml for IpAddr { impl ToXml for IpAddr {
@ -641,9 +641,9 @@ impl<'xml> FromXml<'xml> for IpAddr {
*into = Some(value.0); *into = Some(value.0);
Ok(()) Ok(())
} }
None => Err(Error::MissingValue(&Kind::Scalar)), None => Err(Error::MissingValue(Kind::Scalar)),
} }
} }
const KIND: Kind<'static> = Kind::Scalar; const KIND: Kind = Kind::Scalar;
} }

View File

@ -42,21 +42,17 @@ pub trait FromXml<'xml>: Sized {
// If the missing field is of type `Option<T>` then treat is as `None`, // If the missing field is of type `Option<T>` then treat is as `None`,
// otherwise it is an error. // otherwise it is an error.
fn missing_value() -> Result<Self, Error> { fn missing_value() -> Result<Self, Error> {
Err(Error::MissingValue(&Self::KIND)) Err(Error::MissingValue(Self::KIND))
} }
const KIND: Kind<'static>; const KIND: Kind;
} }
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> {
let (mut context, root) = Context::new(input)?; let (mut context, root) = Context::new(input)?;
let id = context.element_id(&root)?; let id = context.element_id(&root)?;
let expected = match T::KIND {
Kind::Scalar => return Err(Error::UnexpectedState("found scalar as root")),
Kind::Element(expected) => expected,
};
if id != expected { if !T::matches(id, None) {
return Err(Error::UnexpectedValue("unexpected root")); return Err(Error::UnexpectedValue("unexpected root"));
} }
@ -102,7 +98,7 @@ pub enum Error {
#[error("missing tag")] #[error("missing tag")]
MissingTag, MissingTag,
#[error("missing value")] #[error("missing value")]
MissingValue(&'static Kind<'static>), MissingValue(Kind),
#[error("unexpected token: {0}")] #[error("unexpected token: {0}")]
UnexpectedToken(String), UnexpectedToken(String),
#[error("unknown prefix: {0}")] #[error("unknown prefix: {0}")]
@ -117,19 +113,10 @@ pub enum Error {
DuplicateValue, DuplicateValue,
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Kind<'a> { pub enum Kind {
Scalar, Scalar,
Element(Id<'a>), Element,
}
impl<'a> Kind<'a> {
pub const fn element(&self) -> Id<'a> {
match self {
Kind::Element(id) => *id,
_ => panic!("expected element kind"),
}
}
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]

View File

@ -24,12 +24,12 @@ fn direct_namespaces() {
from_str( from_str(
"<StructDirectNamespace xmlns=\"URI\"><flag xmlns=\"WRONG\">true</flag></StructDirectNamespace>" "<StructDirectNamespace xmlns=\"URI\"><flag xmlns=\"WRONG\">true</flag></StructDirectNamespace>"
), ),
Err::<StructDirectNamespace, _>(Error::MissingValue(&Kind::Scalar)) Err::<StructDirectNamespace, _>(Error::MissingValue(Kind::Scalar))
); );
// Wrong direct namespace - missing namespace // Wrong direct namespace - missing namespace
assert_eq!( assert_eq!(
from_str("<StructDirectNamespace xmlns=\"URI\"><flag>true</flag></StructDirectNamespace>"), from_str("<StructDirectNamespace xmlns=\"URI\"><flag>true</flag></StructDirectNamespace>"),
Err::<StructDirectNamespace, _>(Error::MissingValue(&Kind::Scalar)) Err::<StructDirectNamespace, _>(Error::MissingValue(Kind::Scalar))
); );
} }

View File

@ -1,6 +1,6 @@
use similar_asserts::assert_eq; use similar_asserts::assert_eq;
use instant_xml::{from_str, Error, FromXml, Id, Kind}; use instant_xml::{from_str, Error, FromXml, Kind};
#[derive(Debug, Eq, PartialEq, FromXml)] #[derive(Debug, Eq, PartialEq, FromXml)]
struct NestedWrongNamespace { struct NestedWrongNamespace {
@ -72,7 +72,7 @@ fn default_namespaces() {
assert_eq!( assert_eq!(
from_str("<StructWithWrongNestedNamespace xmlns=\"URI\" xmlns:dar=\"BAZ\"><NestedWrongNamespace><flag>true</flag></NestedWrongNamespace></StructWithWrongNestedNamespace>"), from_str("<StructWithWrongNestedNamespace xmlns=\"URI\" xmlns:dar=\"BAZ\"><NestedWrongNamespace><flag>true</flag></NestedWrongNamespace></StructWithWrongNestedNamespace>"),
Err::<StructWithWrongNestedNamespace, _>( Err::<StructWithWrongNestedNamespace, _>(
Error::MissingValue(&Kind::Element(Id { ns: "", name: "NestedWrongNamespace" })) Error::MissingValue(Kind::Element)
) )
); );
} }
@ -113,7 +113,7 @@ fn other_namespaces() {
from_str( from_str(
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"WRONG\"><bar:flag>true</bar:flag></NestedOtherNamespace>" "<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"WRONG\"><bar:flag>true</bar:flag></NestedOtherNamespace>"
), ),
Err::<NestedOtherNamespace, _>(Error::MissingValue(&Kind::Scalar)) Err::<NestedOtherNamespace, _>(Error::MissingValue(Kind::Scalar))
); );
// Other namespace not-nested - missing parser prefix // Other namespace not-nested - missing parser prefix
@ -121,7 +121,7 @@ fn other_namespaces() {
from_str( from_str(
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAR\"><flag>true</flag></NestedOtherNamespace>" "<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAR\"><flag>true</flag></NestedOtherNamespace>"
), ),
Err::<NestedOtherNamespace, _>(Error::MissingValue(&Kind::Scalar)) Err::<NestedOtherNamespace, _>(Error::MissingValue(Kind::Scalar))
); );
// Correct child other namespace // Correct child other namespace