Full support for deserializing externally tagged enums
This commit is contained in:
45
src/de.rs
45
src/de.rs
@@ -171,7 +171,7 @@ pub fn unnamed_fields_as_struct(variant: &Variant, fields: &FieldsUnnamed, ident
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let as_struct = quote!{
|
let as_struct = quote!{
|
||||||
struct #ident {
|
struct #ident {
|
||||||
#(#field_idents: Option<#field_types>,)*
|
#(#field_idents: #field_types,)*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let de_impl = if fields.unnamed.len() == 1 {
|
let de_impl = if fields.unnamed.len() == 1 {
|
||||||
@@ -184,6 +184,7 @@ pub fn unnamed_fields_as_struct(variant: &Variant, fields: &FieldsUnnamed, ident
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
let index = 0usize..;
|
||||||
quote!{
|
quote!{
|
||||||
struct __Visitor {
|
struct __Visitor {
|
||||||
__out: miniserde::export::Option<#ident>,
|
__out: miniserde::export::Option<#ident>,
|
||||||
@@ -201,23 +202,49 @@ pub fn unnamed_fields_as_struct(variant: &Variant, fields: &FieldsUnnamed, ident
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl miniserde::de::Visitor for __Visitor {
|
impl miniserde::de::Visitor for __Visitor {
|
||||||
|
fn seq(&mut self) -> miniserde::Result<miniserde::export::Box<dyn miniserde::de::Seq + '_>> {
|
||||||
|
Ok(miniserde::export::Box::new(__State {
|
||||||
|
#(#field_idents: None,)*
|
||||||
|
__state: 0,
|
||||||
|
__out: &mut self.__out,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct __State<'a> {
|
||||||
|
#(#field_idents: miniserde::export::Option<#field_types>,)*
|
||||||
|
__state: usize,
|
||||||
|
__out: &'a mut miniserde::export::Option<#ident>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> miniserde::de::Seq for __State<'a> {
|
||||||
|
fn element(&mut self) -> miniserde::Result<&mut dyn miniserde::de::Visitor> {
|
||||||
|
let state = self.__state;
|
||||||
|
self.__state += 1;
|
||||||
|
match state {
|
||||||
|
#(#index => Ok(<#field_types as miniserde::Deserialize>::begin(&mut self.#field_idents)),)*
|
||||||
|
_ => Err(miniserde::Error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self) -> miniserde::Result<()> {
|
||||||
|
*self.__out = Some(#ident{
|
||||||
|
#(#field_idents: match self.#field_idents.take() {
|
||||||
|
Some(f) => f,
|
||||||
|
None => return Err(miniserde::Error),
|
||||||
|
},)*
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let as_enum = if fields.unnamed.len() == 1 {
|
|
||||||
quote!{
|
|
||||||
#enum_ident::#variant_ident(self.__f0.unwrap())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote!(unimplemented!())
|
|
||||||
};
|
|
||||||
Ok(quote!{
|
Ok(quote!{
|
||||||
#as_struct
|
#as_struct
|
||||||
|
|
||||||
impl #ident {
|
impl #ident {
|
||||||
fn as_enum(self) -> #enum_ident {
|
fn as_enum(self) -> #enum_ident {
|
||||||
#as_enum
|
#enum_ident::#variant_ident(#(self.#field_idents,)*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,18 +6,16 @@ fn test_external() {
|
|||||||
#[derive(Deserialize_enum, Debug, PartialEq)]
|
#[derive(Deserialize_enum, Debug, PartialEq)]
|
||||||
enum External {
|
enum External {
|
||||||
A(i32),
|
A(i32),
|
||||||
// #[serde(rename = "renamedB")]
|
#[serde(rename = "renamedB")]
|
||||||
// B(i32, String),
|
B(i32, String),
|
||||||
C {
|
C {
|
||||||
x: i32,
|
x: i32,
|
||||||
},
|
},
|
||||||
D,
|
D,
|
||||||
}
|
}
|
||||||
use External::*;
|
use External::*;
|
||||||
// let example = r#"[{"A":21},{"renamedB":[42,"everything"]},{"C":{"x":2}},"D"]"#;
|
let example = r#"[{"A":21},{"renamedB":[42,"everything"]},{"C":{"x":2}},"D"]"#;
|
||||||
let example = r#"[{"A":21},{"C":{"x":2}},"D"]"#;
|
|
||||||
let actual: Vec<External> = json::from_str(example).unwrap();
|
let actual: Vec<External> = json::from_str(example).unwrap();
|
||||||
// let expected = [A(21), B(42, "everything".to_string()), C { x: 2 }, D];
|
let expected = [A(21), B(42, "everything".to_string()), C { x: 2 }, D];
|
||||||
let expected = vec![A(21), C { x: 2 }, D];
|
|
||||||
assert_eq!(actual, expected);
|
assert_eq!(actual, expected);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user