Refactor tuple variant serialization, support tuple variant in externally tagged enum

This commit is contained in:
Aymeric Beringer
2019-10-14 17:13:26 +02:00
parent 6ddeac2461
commit c0a1b3a242
2 changed files with 61 additions and 63 deletions

View File

@@ -86,9 +86,9 @@ fn serialize_unit(variant_name: &str, tag_type: &TagType) -> Result<TokenStream>
self.state = __state + 1;
match __state {
0 => miniserde::export::Some((
miniserde::export::Cow::Borrowed(#tag),
&#variant_name,
)),
miniserde::export::Cow::Borrowed(#tag),
&#variant_name,
)),
_ => miniserde::export::None,
}
}
@@ -129,8 +129,8 @@ fn serialize_named(
#(#field_ident: &'__b #field_type),*,
}
struct __SuperMap<'__b> {
data: __AsStruct<'__b>,
struct __SuperMap<'__a> {
data: __AsStruct<'__a>,
state: miniserde::export::usize,
}
@@ -159,9 +159,9 @@ fn serialize_named(
0usize,
quote!{
0 => miniserde::export::Some((
miniserde::export::Cow::Borrowed(#tag),
&#variant_name,
)),
miniserde::export::Cow::Borrowed(#tag),
&#variant_name,
)),
},
)
} else {
@@ -182,9 +182,9 @@ fn serialize_named(
#tag_arm
#(#index => {
miniserde::export::Some((
miniserde::export::Cow::Borrowed(#field_name),
self.#field_ident,
))
miniserde::export::Cow::Borrowed(#field_name),
self.#field_ident,
))
})*,
_ => miniserde::export::None,
}
@@ -201,7 +201,7 @@ fn serialize_named(
fn serialize_unnamed(
fields: &FieldsUnnamed,
field_ident: &Vec<Ident>,
field_ident: &[Ident],
variant_name: &str,
tag_type: &TagType,
) -> Result<TokenStream> {
@@ -210,74 +210,72 @@ fn serialize_unnamed(
.iter()
.map(|field| &field.ty)
.collect::<Vec<_>>();
let index = 0usize..;
let seq = quote!{
struct __Seq<'__a> {
#(#field_ident: &'__a #field_type),*,
state: miniserde::export::usize,
}
impl<'__a> miniserde::ser::Seq for __Seq<'__a> {
fn next(&mut self) -> miniserde::export::Option<&dyn miniserde::Serialize> {
let __state = self.state;
self.state = __state + 1;
match __state {
#(#index => {
miniserde::export::Some(self.#field_ident)
})*,
_ => miniserde::export::None,
}
}
}
};
Ok(if let TagType::External = tag_type {
quote!{
use miniserde::Serialize;
#[derive(Serialize)]
struct __AsStruct<'__b> (#(&'__b #field_type),*);
#seq
struct __SuperMap<'__b> {
data: __AsStruct<'__b>,
state: miniserde::export::usize,
struct __AsStruct<'__a> (#(&'__a #field_type),*);
impl<'__a> miniserde::Serialize for __AsStruct<'__a> {
fn begin(&self) -> miniserde::ser::Fragment {
let __AsStruct(#(#field_ident),*) = self;
miniserde::ser::Fragment::Seq(miniserde::export::Box::new(__Seq {
#(#field_ident),*,
state: 0,
}))
}
}
struct __SuperMap<'__a> {
data: __AsStruct<'__a>,
state: bool,
}
impl<'__a> miniserde::ser::Map for __SuperMap<'__a> {
fn next(&mut self) -> miniserde::export::Option<(miniserde::export::Cow<miniserde::export::str>, &dyn miniserde::Serialize)> {
let __state = self.state;
self.state = __state + 1;
match __state {
0 => miniserde::export::Some((
if self.state {
return miniserde::export::None;
}
self.state = true;
miniserde::export::Some((
miniserde::export::Cow::Borrowed(#variant_name),
&self.data,
)),
_ => miniserde::export::None,
}
))
}
}
miniserde::ser::Fragment::Map(miniserde::export::Box::new(__SuperMap {
data: __AsStruct { #(#field_ident),* },
state: 0,
data: __AsStruct ( #(#field_ident),* ),
state: false,
}))
}
} else {
let (start, tag_arm) = if let TagType::Internal(ref tag) = &tag_type {
(
0usize,
quote!{
0 => miniserde::export::Some((
miniserde::export::Cow::Borrowed(#tag),
&#variant_name,
)),
},
)
} else {
(1, quote!())
};
let index = 1usize..;
quote!{
struct __Seq<'__a> {
#(#field_ident: &'__a #field_type),*,
state: miniserde::export::usize,
}
impl<'__a> miniserde::ser::Seq for __Seq<'__a> {
fn next(&mut self) -> miniserde::export::Option<&dyn miniserde::Serialize> {
let __state = self.state;
self.state = __state + 1;
match __state {
#tag_arm
#(#index => {
miniserde::export::Some(self.#field_ident)
})*,
_ => miniserde::export::None,
}
}
}
#seq
miniserde::ser::Fragment::Seq(miniserde::export::Box::new(__Seq {
#(#field_ident),*,
state: #start,
state: 0,
}))
}
})

View File

@@ -26,15 +26,15 @@ fn test_external() {
enum External {
A,
#[serde(rename = "renamedB")]
B,
B(i32, String),
C {
x: i32,
},
}
use External::*;
let example = [A, B, C { x: 2 }];
let example = [A, B(42, "everything".to_string()), C { x: 2 }];
let actual = json::to_string(&example[..]);
let expected = r#"["A","renamedB",{"C":{"x":2}}]"#;
let expected = r#"["A",{"renamedB":[42,"everything"]},{"C":{"x":2}}]"#;
assert_eq!(actual, expected);
}