mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-15 13:11:01 +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};
|
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[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.
|
/// Used to check that serde(getter) attributes return the expected type.
|
||||||
/// Not public API.
|
/// Not public API.
|
||||||
@@ -461,7 +466,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Content {
|
pub enum Content {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
|
|
||||||
U8(u8),
|
U8(u8),
|
||||||
@@ -586,12 +591,12 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContentSerializer<E> {
|
pub struct ContentSerializer<E> {
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> ContentSerializer<E> {
|
impl<E> ContentSerializer<E> {
|
||||||
fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ContentSerializer { error: PhantomData }
|
ContentSerializer { error: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -806,7 +811,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeSeq<E> {
|
pub struct SerializeSeq<E> {
|
||||||
elements: Vec<Content>,
|
elements: Vec<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
@@ -832,7 +837,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeTuple<E> {
|
pub struct SerializeTuple<E> {
|
||||||
elements: Vec<Content>,
|
elements: Vec<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
@@ -858,7 +863,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeTupleStruct<E> {
|
pub struct SerializeTupleStruct<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
fields: Vec<Content>,
|
fields: Vec<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
@@ -885,7 +890,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeTupleVariant<E> {
|
pub struct SerializeTupleVariant<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
@@ -919,7 +924,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeMap<E> {
|
pub struct SerializeMap<E> {
|
||||||
entries: Vec<(Content, Content)>,
|
entries: Vec<(Content, Content)>,
|
||||||
key: Option<Content>,
|
key: Option<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
@@ -969,7 +974,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeStruct<E> {
|
pub struct SerializeStruct<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
fields: Vec<(&'static str, Content)>,
|
fields: Vec<(&'static str, Content)>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
@@ -996,7 +1001,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeStructVariant<E> {
|
pub struct SerializeStructVariant<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
@@ -1059,7 +1064,7 @@ impl<'a, M> Serializer for FlatMapSerializer<'a, M>
|
|||||||
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
||||||
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
||||||
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
|
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> {
|
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||||
Err(self.bad_type(Unsupported::Boolean))
|
Err(self.bad_type(Unsupported::Boolean))
|
||||||
@@ -1212,10 +1217,11 @@ impl<'a, M> Serializer for FlatMapSerializer<'a, M>
|
|||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
_: u32,
|
_: u32,
|
||||||
_: &'static str,
|
inner_variant: &'static str,
|
||||||
_: usize,
|
_: usize,
|
||||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
) -> 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(())
|
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)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(repr="map")]
|
#[serde(repr = "map")]
|
||||||
struct CollectOther {
|
struct CollectOther {
|
||||||
a: u32,
|
a: u32,
|
||||||
b: u32,
|
b: u32,
|
||||||
@@ -104,6 +104,27 @@ struct CollectOther {
|
|||||||
extra: HashMap<String, u32>,
|
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]
|
#[test]
|
||||||
fn test_default_struct() {
|
fn test_default_struct() {
|
||||||
assert_de_tokens(
|
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