Add enum integration test and fix ser/de logic
This commit is contained in:
parent
6455801950
commit
4a61982792
|
@ -1,4 +1,4 @@
|
|||
//! Originally from https://raw.githubusercontent.com/serde-rs/serde/master/serde_derive/src/internals/case.rs
|
||||
//! Originally from <https://raw.githubusercontent.com/serde-rs/serde/master/serde_derive/src/internals/case.rs>
|
||||
//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the
|
||||
//! case of the source (e.g. `my-field`, `MY_FIELD`).
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{spanned::Spanned, ImplGenerics};
|
||||
|
||||
use super::{discard_lifetimes, ContainerMeta, FieldMeta, Namespace, VariantMeta};
|
||||
|
||||
|
@ -11,22 +11,37 @@ pub(crate) fn from_xml(input: &syn::DeriveInput) -> TokenStream {
|
|||
Err(e) => return e.to_compile_error(),
|
||||
};
|
||||
|
||||
let mut xml_generics = input.generics.clone();
|
||||
let mut xml = syn::LifetimeDef::new(syn::Lifetime::new("'xml", Span::call_site()));
|
||||
xml.bounds
|
||||
.extend(xml_generics.lifetimes().map(|lt| lt.lifetime.clone()));
|
||||
xml_generics.params.push(xml.into());
|
||||
|
||||
let (xml_impl_generics, _, _) = xml_generics.split_for_impl();
|
||||
|
||||
match &input.data {
|
||||
syn::Data::Struct(_) if meta.scalar => {
|
||||
syn::Error::new(input.span(), "scalar structs are unsupported!").to_compile_error()
|
||||
}
|
||||
syn::Data::Struct(ref data) => deserialize_struct(input, data, meta, ident),
|
||||
syn::Data::Struct(ref data) => {
|
||||
deserialize_struct(input, data, meta, ident, xml_impl_generics)
|
||||
}
|
||||
syn::Data::Enum(_) if !meta.scalar => {
|
||||
syn::Error::new(input.span(), "non-scalar enums are currently unsupported!")
|
||||
.to_compile_error()
|
||||
}
|
||||
syn::Data::Enum(ref data) => deserialize_enum(input, data, meta),
|
||||
syn::Data::Enum(ref data) => deserialize_enum(input, data, meta, xml_impl_generics),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn deserialize_enum(input: &syn::DeriveInput, data: &syn::DataEnum, meta: ContainerMeta) -> TokenStream {
|
||||
fn deserialize_enum(
|
||||
input: &syn::DeriveInput,
|
||||
data: &syn::DataEnum,
|
||||
meta: ContainerMeta,
|
||||
xml_impl_generics: ImplGenerics
|
||||
) -> TokenStream {
|
||||
let ident = &input.ident;
|
||||
let mut variants = TokenStream::new();
|
||||
|
||||
|
@ -38,19 +53,21 @@ fn deserialize_enum(input: &syn::DeriveInput, data: &syn::DataEnum, meta: Contai
|
|||
};
|
||||
|
||||
let serialize_as = meta.serialize_as;
|
||||
variants.extend(quote!(Ok(#serialize_as) => #ident::#v_ident,));
|
||||
variants.extend(quote!(Ok(#serialize_as) => Ok(#ident::#v_ident),));
|
||||
}
|
||||
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
let (_, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote!(
|
||||
impl #impl_generics FromXml<'xml> for #ident #ty_generics #where_clause {
|
||||
impl #xml_impl_generics FromXml<'xml> for #ident #ty_generics #where_clause {
|
||||
fn deserialize<'cx>(deserializer: &'cx mut ::instant_xml::Deserializer<'cx, 'xml>) -> Result<Self, ::instant_xml::Error> {
|
||||
match deserializer.take_str() {
|
||||
#variants
|
||||
_ => Err(::instant_xml::Error::UnexpectedValue)
|
||||
}
|
||||
}
|
||||
|
||||
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Scalar;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -60,20 +77,14 @@ fn deserialize_struct(
|
|||
data: &syn::DataStruct,
|
||||
container_meta: ContainerMeta,
|
||||
ident: &Ident,
|
||||
xml_impl_generics: ImplGenerics,
|
||||
) -> TokenStream {
|
||||
let default_namespace = match &container_meta.ns.uri {
|
||||
Some(ns) => quote!(#ns),
|
||||
None => quote!(""),
|
||||
};
|
||||
|
||||
let mut xml_generics = input.generics.clone();
|
||||
let mut xml = syn::LifetimeDef::new(syn::Lifetime::new("'xml", Span::call_site()));
|
||||
xml.bounds
|
||||
.extend(xml_generics.lifetimes().map(|lt| lt.lifetime.clone()));
|
||||
xml_generics.params.push(xml.into());
|
||||
|
||||
let (_, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
let (xml_impl_generics, _, _) = xml_generics.split_for_impl();
|
||||
|
||||
let mut namespaces_map = quote!(let mut namespaces_map = std::collections::HashMap::new(););
|
||||
for (k, v) in container_meta.ns.prefixes.iter() {
|
||||
|
|
|
@ -684,7 +684,7 @@ mod tests {
|
|||
};
|
||||
|
||||
assert_eq!(super::ser::to_xml(&input).to_string(),
|
||||
"impl ToXml for TestEnum { fn serialize < W : :: core :: fmt :: Write + ? :: core :: marker :: Sized > (& self , serializer : & mut instant_xml :: Serializer < W > ,) -> Result < () , instant_xml :: Error > { serializer . write_str (match self { TestEnum :: Foo => \"Foo\" , TestEnum :: Bar => \"Bar\" , TestEnum :: Baz => \"1\" , }) } }"
|
||||
"impl ToXml for TestEnum { fn serialize < W : :: core :: fmt :: Write + ? :: core :: marker :: Sized > (& self , serializer : & mut instant_xml :: Serializer < W > ,) -> Result < () , instant_xml :: Error > { serializer . write_str (match self { TestEnum :: Foo => \"Foo\" , TestEnum :: Bar => \"Bar\" , TestEnum :: Baz => \"1\" , }) } const KIND : :: instant_xml :: Kind = :: instant_xml :: Kind :: Scalar ; }"
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -701,7 +701,7 @@ mod tests {
|
|||
};
|
||||
|
||||
assert_eq!(super::de::from_xml(&input).to_string(),
|
||||
"impl FromXml < 'xml > for TestEnum { fn deserialize < 'cx > (deserializer : & 'cx mut :: instant_xml :: Deserializer < 'cx , 'xml >) -> Result < Self , :: instant_xml :: Error > { match deserializer . take_str () { Ok (\"Foo\") => TestEnum :: Foo , Ok (\"Bar\") => TestEnum :: Bar , Ok (\"1\") => TestEnum :: Baz , _ => Err (:: instant_xml :: Error :: UnexpectedValue) } } }"
|
||||
"impl < 'xml > FromXml < 'xml > for TestEnum { fn deserialize < 'cx > (deserializer : & 'cx mut :: instant_xml :: Deserializer < 'cx , 'xml >) -> Result < Self , :: instant_xml :: Error > { match deserializer . take_str () { Ok (\"Foo\") => Ok (TestEnum :: Foo) , Ok (\"Bar\") => Ok (TestEnum :: Bar) , Ok (\"1\") => Ok (TestEnum :: Baz) , _ => Err (:: instant_xml :: Error :: UnexpectedValue) } } const KIND : :: instant_xml :: Kind = :: instant_xml :: Kind :: Scalar ; }"
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -789,7 +789,7 @@ mod tests {
|
|||
Bar,
|
||||
Baz
|
||||
}
|
||||
}).to_string(), "impl ToXml for TestEnum { fn serialize < W : :: core :: fmt :: Write + ? :: core :: marker :: Sized > (& self , serializer : & mut instant_xml :: Serializer < W > ,) -> Result < () , instant_xml :: Error > { serializer . write_str (match self { TestEnum :: Foo => \"1\" , TestEnum :: Bar => \"BAR\" , TestEnum :: Baz => \"BAZ\" , }) } }");
|
||||
}).to_string(), "impl ToXml for TestEnum { fn serialize < W : :: core :: fmt :: Write + ? :: core :: marker :: Sized > (& self , serializer : & mut instant_xml :: Serializer < W > ,) -> Result < () , instant_xml :: Error > { serializer . write_str (match self { TestEnum :: Foo => \"1\" , TestEnum :: Bar => \"BAR\" , TestEnum :: Baz => \"BAZ\" , }) } const KIND : :: instant_xml :: Kind = :: instant_xml :: Kind :: Scalar ; }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -56,6 +56,8 @@ fn serialize_enum(
|
|||
) -> Result<(), instant_xml::Error> {
|
||||
serializer.write_str(match self { #variants })
|
||||
}
|
||||
|
||||
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Scalar;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -41,3 +41,31 @@ fn rename_all_struct() {
|
|||
assert_eq!(to_string(&instance).unwrap(), serialized);
|
||||
assert_eq!(from_str::<TestStruct>(serialized), Ok(instance));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rename_all_enum_variant() {
|
||||
#[derive(Debug, PartialEq, Eq, ToXml, FromXml)]
|
||||
#[xml(scalar, rename_all = "snake_case")]
|
||||
pub enum TestEnum {
|
||||
SnakeCased,
|
||||
ThisToo,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, ToXml, FromXml)]
|
||||
#[xml(rename_all = "UPPERCASE")]
|
||||
pub struct TestStruct {
|
||||
field_1: TestEnum,
|
||||
#[xml(attribute)]
|
||||
field_2: TestEnum,
|
||||
}
|
||||
|
||||
let serialized =
|
||||
r#"<TestStruct FIELD_2="this_too"><FIELD_1>snake_cased</FIELD_1></TestStruct>"#;
|
||||
let instance = TestStruct {
|
||||
field_1: TestEnum::SnakeCased,
|
||||
field_2: TestEnum::ThisToo,
|
||||
};
|
||||
|
||||
assert_eq!(to_string(&instance).unwrap(), serialized);
|
||||
assert_eq!(from_str::<TestStruct>(serialized), Ok(instance));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue