Skip to content

Commit dbe640a

Browse files
committed
Added support for struct variant enum serialization
1 parent 713c2c1 commit dbe640a

File tree

2 files changed

+128
-15
lines changed

2 files changed

+128
-15
lines changed

serde/src/private/ser.rs

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ use lib::*;
1111
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
1212

1313
#[cfg(any(feature = "std", feature = "alloc"))]
14-
use self::content::{SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue};
14+
use self::content::{
15+
SerializeStructVariantAsMapValue,
16+
SerializeTupleVariantAsMapValue,
17+
ContentSerializer,
18+
Content,
19+
};
1520

1621
/// Used to check that serde(getter) attributes return the expected type.
1722
/// Not public API.
@@ -461,7 +466,7 @@ mod content {
461466
}
462467

463468
#[derive(Debug)]
464-
enum Content {
469+
pub enum Content {
465470
Bool(bool),
466471

467472
U8(u8),
@@ -586,12 +591,12 @@ mod content {
586591
}
587592
}
588593

589-
struct ContentSerializer<E> {
594+
pub struct ContentSerializer<E> {
590595
error: PhantomData<E>,
591596
}
592597

593598
impl<E> ContentSerializer<E> {
594-
fn new() -> Self {
599+
pub fn new() -> Self {
595600
ContentSerializer { error: PhantomData }
596601
}
597602
}
@@ -806,7 +811,7 @@ mod content {
806811
}
807812
}
808813

809-
struct SerializeSeq<E> {
814+
pub struct SerializeSeq<E> {
810815
elements: Vec<Content>,
811816
error: PhantomData<E>,
812817
}
@@ -832,7 +837,7 @@ mod content {
832837
}
833838
}
834839

835-
struct SerializeTuple<E> {
840+
pub struct SerializeTuple<E> {
836841
elements: Vec<Content>,
837842
error: PhantomData<E>,
838843
}
@@ -858,7 +863,7 @@ mod content {
858863
}
859864
}
860865

861-
struct SerializeTupleStruct<E> {
866+
pub struct SerializeTupleStruct<E> {
862867
name: &'static str,
863868
fields: Vec<Content>,
864869
error: PhantomData<E>,
@@ -885,7 +890,7 @@ mod content {
885890
}
886891
}
887892

888-
struct SerializeTupleVariant<E> {
893+
pub struct SerializeTupleVariant<E> {
889894
name: &'static str,
890895
variant_index: u32,
891896
variant: &'static str,
@@ -919,7 +924,7 @@ mod content {
919924
}
920925
}
921926

922-
struct SerializeMap<E> {
927+
pub struct SerializeMap<E> {
923928
entries: Vec<(Content, Content)>,
924929
key: Option<Content>,
925930
error: PhantomData<E>,
@@ -969,7 +974,7 @@ mod content {
969974
}
970975
}
971976

972-
struct SerializeStruct<E> {
977+
pub struct SerializeStruct<E> {
973978
name: &'static str,
974979
fields: Vec<(&'static str, Content)>,
975980
error: PhantomData<E>,
@@ -996,7 +1001,7 @@ mod content {
9961001
}
9971002
}
9981003

999-
struct SerializeStructVariant<E> {
1004+
pub struct SerializeStructVariant<E> {
10001005
name: &'static str,
10011006
variant_index: u32,
10021007
variant: &'static str,
@@ -1059,7 +1064,7 @@ impl<'a, M> Serializer for FlatMapSerializer<'a, M>
10591064
type SerializeMap = FlatMapSerializeMap<'a, M>;
10601065
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
10611066
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
1062-
type SerializeStructVariant = Impossible<Self::Ok, M::Error>;
1067+
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
10631068

10641069
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
10651070
Err(self.bad_type(Unsupported::Boolean))
@@ -1212,10 +1217,11 @@ impl<'a, M> Serializer for FlatMapSerializer<'a, M>
12121217
self,
12131218
_: &'static str,
12141219
_: u32,
1215-
_: &'static str,
1220+
inner_variant: &'static str,
12161221
_: usize,
12171222
) -> Result<Self::SerializeStructVariant, Self::Error> {
1218-
Err(self.bad_type(Unsupported::Enum))
1223+
try!(self.0.serialize_key(inner_variant));
1224+
Ok(FlatMapSerializeStructVariantAsMapValue::new(self.0, inner_variant))
12191225
}
12201226
}
12211227

@@ -1269,3 +1275,44 @@ impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M>
12691275
Ok(())
12701276
}
12711277
}
1278+
1279+
#[cfg(any(feature = "std", feature = "alloc"))]
1280+
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
1281+
map: &'a mut M,
1282+
name: &'static str,
1283+
fields: Vec<(&'static str, Content)>,
1284+
}
1285+
1286+
impl<'a, M> FlatMapSerializeStructVariantAsMapValue<'a, M>
1287+
where M: SerializeMap + 'a
1288+
{
1289+
fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
1290+
FlatMapSerializeStructVariantAsMapValue {
1291+
map: map,
1292+
name: name,
1293+
fields: Vec::new(),
1294+
}
1295+
}
1296+
}
1297+
1298+
#[cfg(any(feature = "std", feature = "alloc"))]
1299+
impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M>
1300+
where M: SerializeMap + 'a
1301+
{
1302+
type Ok = ();
1303+
type Error = M::Error;
1304+
1305+
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
1306+
where
1307+
T: Serialize,
1308+
{
1309+
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
1310+
self.fields.push((key, value));
1311+
Ok(())
1312+
}
1313+
1314+
fn end(self) -> Result<(), Self::Error> {
1315+
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
1316+
Ok(())
1317+
}
1318+
}

test_suite/tests/test_annotations.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,35 @@ where
9696
}
9797

9898
#[derive(Debug, PartialEq, Serialize, Deserialize)]
99-
#[serde(repr="map")]
99+
#[serde(repr = "map")]
100100
struct CollectOther {
101101
a: u32,
102102
b: u32,
103103
#[serde(flatten)]
104104
extra: HashMap<String, u32>,
105105
}
106106

107+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
108+
#[serde(repr = "map")]
109+
struct ChangeRequest {
110+
#[serde(flatten)]
111+
data: ChangeAction,
112+
#[serde(flatten)]
113+
extra: HashMap<String, String>,
114+
}
115+
116+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
117+
#[serde(rename_all = "snake_case")]
118+
enum ChangeAction {
119+
AppendInteger {
120+
value: u32
121+
},
122+
InsertInteger {
123+
index: u32,
124+
value: u32
125+
},
126+
}
127+
107128
#[test]
108129
fn test_default_struct() {
109130
assert_de_tokens(
@@ -1309,3 +1330,48 @@ fn test_collect_other() {
13091330
],
13101331
);
13111332
}
1333+
1334+
#[test]
1335+
fn test_flatten_struct_enum() {
1336+
let mut extra = HashMap::new();
1337+
extra.insert("extra_key".into(), "extra value".into());
1338+
let change_request = ChangeRequest {
1339+
data: ChangeAction::InsertInteger {
1340+
index: 0,
1341+
value: 42
1342+
},
1343+
extra: extra,
1344+
};
1345+
assert_de_tokens(
1346+
&change_request,
1347+
&[
1348+
Token::Map { len: None },
1349+
Token::Str("insert_integer"),
1350+
Token::Map { len: None },
1351+
Token::Str("index"),
1352+
Token::U32(0),
1353+
Token::Str("value"),
1354+
Token::U32(42),
1355+
Token::MapEnd,
1356+
Token::Str("extra_key"),
1357+
Token::String("extra value".into()),
1358+
Token::MapEnd
1359+
],
1360+
);
1361+
assert_ser_tokens(
1362+
&change_request,
1363+
&[
1364+
Token::Map { len: None },
1365+
Token::Str("insert_integer"),
1366+
Token::Struct { len: 2, name: "insert_integer" },
1367+
Token::Str("index"),
1368+
Token::U32(0),
1369+
Token::Str("value"),
1370+
Token::U32(42),
1371+
Token::StructEnd,
1372+
Token::Str("extra_key"),
1373+
Token::String("extra value".into()),
1374+
Token::MapEnd
1375+
],
1376+
);
1377+
}

0 commit comments

Comments
 (0)