mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-26 01:37:55 +00:00
Added support for struct variant enum serialization
This commit is contained in:
+61
-14
@@ -11,7 +11,12 @@ use lib::*;
|
||||
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use self::content::{SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue};
|
||||
use self::content::{
|
||||
SerializeStructVariantAsMapValue,
|
||||
SerializeTupleVariantAsMapValue,
|
||||
ContentSerializer,
|
||||
Content,
|
||||
};
|
||||
|
||||
/// Used to check that serde(getter) attributes return the expected type.
|
||||
/// Not public API.
|
||||
@@ -461,7 +466,7 @@ mod content {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Content {
|
||||
pub enum Content {
|
||||
Bool(bool),
|
||||
|
||||
U8(u8),
|
||||
@@ -586,12 +591,12 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentSerializer<E> {
|
||||
pub struct ContentSerializer<E> {
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ContentSerializer<E> {
|
||||
fn new() -> Self {
|
||||
pub fn new() -> Self {
|
||||
ContentSerializer { error: PhantomData }
|
||||
}
|
||||
}
|
||||
@@ -806,7 +811,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeSeq<E> {
|
||||
pub struct SerializeSeq<E> {
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
@@ -832,7 +837,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTuple<E> {
|
||||
pub struct SerializeTuple<E> {
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
@@ -858,7 +863,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleStruct<E> {
|
||||
pub struct SerializeTupleStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
@@ -885,7 +890,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleVariant<E> {
|
||||
pub struct SerializeTupleVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
@@ -919,7 +924,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeMap<E> {
|
||||
pub struct SerializeMap<E> {
|
||||
entries: Vec<(Content, Content)>,
|
||||
key: Option<Content>,
|
||||
error: PhantomData<E>,
|
||||
@@ -969,7 +974,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStruct<E> {
|
||||
pub struct SerializeStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
error: PhantomData<E>,
|
||||
@@ -996,7 +1001,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStructVariant<E> {
|
||||
pub struct SerializeStructVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
@@ -1059,7 +1064,7 @@ impl<'a, M> Serializer for FlatMapSerializer<'a, M>
|
||||
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
||||
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
||||
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeStructVariant = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
|
||||
|
||||
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Boolean))
|
||||
@@ -1212,10 +1217,11 @@ impl<'a, M> Serializer for FlatMapSerializer<'a, M>
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
_: &'static str,
|
||||
inner_variant: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
try!(self.0.serialize_key(inner_variant));
|
||||
Ok(FlatMapSerializeStructVariantAsMapValue::new(self.0, inner_variant))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1269,3 +1275,44 @@ impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M>
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
|
||||
map: &'a mut M,
|
||||
name: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
}
|
||||
|
||||
impl<'a, M> FlatMapSerializeStructVariantAsMapValue<'a, M>
|
||||
where M: SerializeMap + 'a
|
||||
{
|
||||
fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
|
||||
FlatMapSerializeStructVariantAsMapValue {
|
||||
map: map,
|
||||
name: name,
|
||||
fields: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M>
|
||||
where M: SerializeMap + 'a
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ where
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(repr="map")]
|
||||
#[serde(repr = "map")]
|
||||
struct CollectOther {
|
||||
a: u32,
|
||||
b: u32,
|
||||
@@ -104,6 +104,27 @@ struct CollectOther {
|
||||
extra: HashMap<String, u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(repr = "map")]
|
||||
struct ChangeRequest {
|
||||
#[serde(flatten)]
|
||||
data: ChangeAction,
|
||||
#[serde(flatten)]
|
||||
extra: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
enum ChangeAction {
|
||||
AppendInteger {
|
||||
value: u32
|
||||
},
|
||||
InsertInteger {
|
||||
index: u32,
|
||||
value: u32
|
||||
},
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_struct() {
|
||||
assert_de_tokens(
|
||||
@@ -1309,3 +1330,48 @@ fn test_collect_other() {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_struct_enum() {
|
||||
let mut extra = HashMap::new();
|
||||
extra.insert("extra_key".into(), "extra value".into());
|
||||
let change_request = ChangeRequest {
|
||||
data: ChangeAction::InsertInteger {
|
||||
index: 0,
|
||||
value: 42
|
||||
},
|
||||
extra: extra,
|
||||
};
|
||||
assert_de_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("insert_integer"),
|
||||
Token::Map { len: None },
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
Token::Str("extra_key"),
|
||||
Token::String("extra value".into()),
|
||||
Token::MapEnd
|
||||
],
|
||||
);
|
||||
assert_ser_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("insert_integer"),
|
||||
Token::Struct { len: 2, name: "insert_integer" },
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
Token::Str("extra_key"),
|
||||
Token::String("extra value".into()),
|
||||
Token::MapEnd
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user