From c0a1b3a242b2339e6cbfd1b0ea035240c93a1129 Mon Sep 17 00:00:00 2001 From: Aymeric Beringer Date: Mon, 14 Oct 2019 17:13:26 +0200 Subject: [PATCH] Refactor tuple variant serialization, support tuple variant in externally tagged enum --- src/ser.rs | 118 ++++++++++++++++++++++----------------------- tests/serialize.rs | 6 +-- 2 files changed, 61 insertions(+), 63 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 58838ed..ad8dad0 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -86,9 +86,9 @@ fn serialize_unit(variant_name: &str, tag_type: &TagType) -> Result 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, + field_ident: &[Ident], variant_name: &str, tag_type: &TagType, ) -> Result { @@ -210,74 +210,72 @@ fn serialize_unnamed( .iter() .map(|field| &field.ty) .collect::>(); + 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, &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, })) } }) diff --git a/tests/serialize.rs b/tests/serialize.rs index 4375448..504d2ad 100644 --- a/tests/serialize.rs +++ b/tests/serialize.rs @@ -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); }