Merge pull request #2448 from Mingun/ser-flatten-enums
Implement serialization of tuple variants of flatten enums
This commit is contained in:
commit
427c839b3d
@ -207,6 +207,7 @@ mod content {
|
|||||||
|
|
||||||
use __private::size_hint;
|
use __private::size_hint;
|
||||||
use actually_private;
|
use actually_private;
|
||||||
|
use de::value::{MapDeserializer, SeqDeserializer};
|
||||||
use de::{
|
use de::{
|
||||||
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
||||||
MapAccess, SeqAccess, Unexpected, Visitor,
|
MapAccess, SeqAccess, Unexpected, Visitor,
|
||||||
@ -299,6 +300,17 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, E> de::IntoDeserializer<'de, E> for Content<'de>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = ContentDeserializer<'de, E>;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self::Deserializer {
|
||||||
|
ContentDeserializer::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ContentVisitor<'de> {
|
struct ContentVisitor<'de> {
|
||||||
value: PhantomData<Content<'de>>,
|
value: PhantomData<Content<'de>>,
|
||||||
}
|
}
|
||||||
@ -1074,7 +1086,7 @@ mod content {
|
|||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
let seq = content.into_iter().map(ContentDeserializer::new);
|
let seq = content.into_iter().map(ContentDeserializer::new);
|
||||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
let mut seq_visitor = SeqDeserializer::new(seq);
|
||||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||||
try!(seq_visitor.end());
|
try!(seq_visitor.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
@ -1091,7 +1103,7 @@ mod content {
|
|||||||
let map = content
|
let map = content
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
let mut map_visitor = MapDeserializer::new(map);
|
||||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||||
try!(map_visitor.end());
|
try!(map_visitor.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
@ -1569,7 +1581,7 @@ mod content {
|
|||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Some(Content::Seq(v)) => {
|
Some(Content::Seq(v)) => {
|
||||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
|
||||||
}
|
}
|
||||||
Some(other) => Err(de::Error::invalid_type(
|
Some(other) => Err(de::Error::invalid_type(
|
||||||
other.unexpected(),
|
other.unexpected(),
|
||||||
@ -1592,10 +1604,10 @@ mod content {
|
|||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Some(Content::Map(v)) => {
|
Some(Content::Map(v)) => {
|
||||||
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
|
de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor)
|
||||||
}
|
}
|
||||||
Some(Content::Seq(v)) => {
|
Some(Content::Seq(v)) => {
|
||||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
|
||||||
}
|
}
|
||||||
Some(other) => Err(de::Error::invalid_type(
|
Some(other) => Err(de::Error::invalid_type(
|
||||||
other.unexpected(),
|
other.unexpected(),
|
||||||
@ -1609,156 +1621,6 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SeqDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
|
|
||||||
err: PhantomData<E>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E> SeqDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
fn new(vec: Vec<Content<'de>>) -> Self {
|
|
||||||
SeqDeserializer {
|
|
||||||
iter: vec.into_iter(),
|
|
||||||
err: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
type Error = E;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
|
||||||
where
|
|
||||||
V: de::Visitor<'de>,
|
|
||||||
{
|
|
||||||
let len = self.iter.len();
|
|
||||||
if len == 0 {
|
|
||||||
visitor.visit_unit()
|
|
||||||
} else {
|
|
||||||
let ret = try!(visitor.visit_seq(&mut self));
|
|
||||||
let remaining = self.iter.len();
|
|
||||||
if remaining == 0 {
|
|
||||||
Ok(ret)
|
|
||||||
} else {
|
|
||||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
|
||||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
||||||
bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
||||||
tuple_struct map struct enum identifier ignored_any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
type Error = E;
|
|
||||||
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
|
||||||
where
|
|
||||||
T: de::DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.iter.next() {
|
|
||||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
size_hint::from_bounds(&self.iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MapDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
|
|
||||||
value: Option<Content<'de>>,
|
|
||||||
err: PhantomData<E>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E> MapDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self {
|
|
||||||
MapDeserializer {
|
|
||||||
iter: map.into_iter(),
|
|
||||||
value: None,
|
|
||||||
err: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
type Error = E;
|
|
||||||
|
|
||||||
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
|
||||||
where
|
|
||||||
T: de::DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.iter.next() {
|
|
||||||
Some((key, value)) => {
|
|
||||||
self.value = Some(value);
|
|
||||||
seed.deserialize(ContentDeserializer::new(key)).map(Some)
|
|
||||||
}
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
|
||||||
where
|
|
||||||
T: de::DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.value.take() {
|
|
||||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
|
|
||||||
None => Err(de::Error::custom("value is missing")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
size_hint::from_bounds(&self.iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
type Error = E;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
|
||||||
where
|
|
||||||
V: de::Visitor<'de>,
|
|
||||||
{
|
|
||||||
visitor.visit_map(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
|
||||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
||||||
bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
||||||
tuple_struct map struct enum identifier ignored_any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Not public API.
|
/// Not public API.
|
||||||
pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
|
pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
|
||||||
content: &'a Content<'de>,
|
content: &'a Content<'de>,
|
||||||
@ -1820,7 +1682,7 @@ mod content {
|
|||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
let seq = content.iter().map(ContentRefDeserializer::new);
|
let seq = content.iter().map(ContentRefDeserializer::new);
|
||||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
let mut seq_visitor = SeqDeserializer::new(seq);
|
||||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||||
try!(seq_visitor.end());
|
try!(seq_visitor.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
@ -1840,7 +1702,7 @@ mod content {
|
|||||||
ContentRefDeserializer::new(v),
|
ContentRefDeserializer::new(v),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
let mut map_visitor = MapDeserializer::new(map);
|
||||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||||
try!(map_visitor.end());
|
try!(map_visitor.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
@ -1025,7 +1025,7 @@ where
|
|||||||
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
|
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
|
||||||
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 = FlatMapSerializeTupleVariantAsMapValue<'a, M>;
|
||||||
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
|
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> {
|
||||||
@ -1157,10 +1157,11 @@ where
|
|||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
_: u32,
|
_: u32,
|
||||||
_: &'static str,
|
variant: &'static str,
|
||||||
_: usize,
|
_: usize,
|
||||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||||
Err(Self::bad_type(Unsupported::Enum))
|
try!(self.0.serialize_key(variant));
|
||||||
|
Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||||
@ -1259,6 +1260,52 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> {
|
||||||
|
map: &'a mut M,
|
||||||
|
fields: Vec<Content>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<'a, M> FlatMapSerializeTupleVariantAsMapValue<'a, M>
|
||||||
|
where
|
||||||
|
M: SerializeMap + 'a,
|
||||||
|
{
|
||||||
|
fn new(map: &'a mut M) -> Self {
|
||||||
|
FlatMapSerializeTupleVariantAsMapValue {
|
||||||
|
map: map,
|
||||||
|
fields: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<'a, M> ser::SerializeTupleVariant for FlatMapSerializeTupleVariantAsMapValue<'a, M>
|
||||||
|
where
|
||||||
|
M: SerializeMap + 'a,
|
||||||
|
{
|
||||||
|
type Ok = ();
|
||||||
|
type Error = M::Error;
|
||||||
|
|
||||||
|
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
{
|
||||||
|
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||||
|
self.fields.push(value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<(), Self::Error> {
|
||||||
|
try!(self.map.serialize_value(&Content::Seq(self.fields)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
|
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
|
||||||
map: &'a mut M,
|
map: &'a mut M,
|
||||||
|
@ -114,42 +114,6 @@ struct CollectOther {
|
|||||||
extra: HashMap<String, u32>,
|
extra: HashMap<String, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
struct FlattenStructEnumWrapper {
|
|
||||||
#[serde(flatten)]
|
|
||||||
data: FlattenStructEnum,
|
|
||||||
#[serde(flatten)]
|
|
||||||
extra: HashMap<String, String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
enum FlattenStructEnum {
|
|
||||||
InsertInteger { index: u32, value: u32 },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
struct FlattenStructTagContentEnumWrapper {
|
|
||||||
outer: u32,
|
|
||||||
#[serde(flatten)]
|
|
||||||
data: FlattenStructTagContentEnumNewtype,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum);
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
|
|
||||||
enum FlattenStructTagContentEnum {
|
|
||||||
InsertInteger { index: u32, value: u32 },
|
|
||||||
NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
struct FlattenStructTagContentEnumNewtypeVariant {
|
|
||||||
value: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default_struct() {
|
fn test_default_struct() {
|
||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
@ -1643,149 +1607,6 @@ 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 = FlattenStructEnumWrapper {
|
|
||||||
data: FlattenStructEnum::InsertInteger {
|
|
||||||
index: 0,
|
|
||||||
value: 42,
|
|
||||||
},
|
|
||||||
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::Str("extra value"),
|
|
||||||
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::Str("extra value"),
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flatten_struct_tag_content_enum() {
|
|
||||||
let change_request = FlattenStructTagContentEnumWrapper {
|
|
||||||
outer: 42,
|
|
||||||
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger {
|
|
||||||
index: 0,
|
|
||||||
value: 42,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
assert_de_tokens(
|
|
||||||
&change_request,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("outer"),
|
|
||||||
Token::U32(42),
|
|
||||||
Token::Str("type"),
|
|
||||||
Token::Str("insert_integer"),
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("index"),
|
|
||||||
Token::U32(0),
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::U32(42),
|
|
||||||
Token::MapEnd,
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
assert_ser_tokens(
|
|
||||||
&change_request,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("outer"),
|
|
||||||
Token::U32(42),
|
|
||||||
Token::Str("type"),
|
|
||||||
Token::Str("insert_integer"),
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::Struct {
|
|
||||||
len: 2,
|
|
||||||
name: "insert_integer",
|
|
||||||
},
|
|
||||||
Token::Str("index"),
|
|
||||||
Token::U32(0),
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::U32(42),
|
|
||||||
Token::StructEnd,
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flatten_struct_tag_content_enum_newtype() {
|
|
||||||
let change_request = FlattenStructTagContentEnumWrapper {
|
|
||||||
outer: 42,
|
|
||||||
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant(
|
|
||||||
FlattenStructTagContentEnumNewtypeVariant { value: 23 },
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
assert_de_tokens(
|
|
||||||
&change_request,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("outer"),
|
|
||||||
Token::U32(42),
|
|
||||||
Token::Str("type"),
|
|
||||||
Token::Str("newtype_variant"),
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::U32(23),
|
|
||||||
Token::MapEnd,
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
assert_ser_tokens(
|
|
||||||
&change_request,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("outer"),
|
|
||||||
Token::U32(42),
|
|
||||||
Token::Str("type"),
|
|
||||||
Token::Str("newtype_variant"),
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::Struct {
|
|
||||||
len: 1,
|
|
||||||
name: "FlattenStructTagContentEnumNewtypeVariant",
|
|
||||||
},
|
|
||||||
Token::Str("value"),
|
|
||||||
Token::U32(23),
|
|
||||||
Token::StructEnd,
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unknown_field_in_flatten() {
|
fn test_unknown_field_in_flatten() {
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -2142,86 +1963,6 @@ fn test_lifetime_propagation_for_flatten() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flatten_enum_newtype() {
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
struct S {
|
|
||||||
#[serde(flatten)]
|
|
||||||
flat: E,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
enum E {
|
|
||||||
Q(HashMap<String, String>),
|
|
||||||
}
|
|
||||||
|
|
||||||
let e = E::Q({
|
|
||||||
let mut map = HashMap::new();
|
|
||||||
map.insert("k".to_owned(), "v".to_owned());
|
|
||||||
map
|
|
||||||
});
|
|
||||||
let s = S { flat: e };
|
|
||||||
|
|
||||||
assert_tokens(
|
|
||||||
&s,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("Q"),
|
|
||||||
Token::Map { len: Some(1) },
|
|
||||||
Token::Str("k"),
|
|
||||||
Token::Str("v"),
|
|
||||||
Token::MapEnd,
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flatten_internally_tagged() {
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
struct S {
|
|
||||||
#[serde(flatten)]
|
|
||||||
x: X,
|
|
||||||
#[serde(flatten)]
|
|
||||||
y: Y,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
#[serde(tag = "typeX")]
|
|
||||||
enum X {
|
|
||||||
A { a: i32 },
|
|
||||||
B { b: i32 },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
#[serde(tag = "typeY")]
|
|
||||||
enum Y {
|
|
||||||
C { c: i32 },
|
|
||||||
D { d: i32 },
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = S {
|
|
||||||
x: X::B { b: 1 },
|
|
||||||
y: Y::D { d: 2 },
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_tokens(
|
|
||||||
&s,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("typeX"),
|
|
||||||
Token::Str("B"),
|
|
||||||
Token::Str("b"),
|
|
||||||
Token::I32(1),
|
|
||||||
Token::Str("typeY"),
|
|
||||||
Token::Str("D"),
|
|
||||||
Token::Str("d"),
|
|
||||||
Token::I32(2),
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_externally_tagged_enum_containing_flatten() {
|
fn test_externally_tagged_enum_containing_flatten() {
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
@ -2630,35 +2371,6 @@ fn test_partially_untagged_enum_desugared() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flatten_untagged_enum() {
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
struct Outer {
|
|
||||||
#[serde(flatten)]
|
|
||||||
inner: Inner,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
enum Inner {
|
|
||||||
Variant { a: i32 },
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = Outer {
|
|
||||||
inner: Inner::Variant { a: 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_tokens(
|
|
||||||
&data,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("a"),
|
|
||||||
Token::I32(0),
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flatten_option() {
|
fn test_flatten_option() {
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
@ -2815,48 +2527,6 @@ fn test_internally_tagged_unit_enum_with_unknown_fields() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() {
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
|
||||||
struct S {
|
|
||||||
#[serde(flatten)]
|
|
||||||
x: X,
|
|
||||||
#[serde(flatten)]
|
|
||||||
y: Y,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
|
||||||
#[serde(tag = "typeX")]
|
|
||||||
enum X {
|
|
||||||
A,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
|
||||||
#[serde(tag = "typeY")]
|
|
||||||
enum Y {
|
|
||||||
B { c: u32 },
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = S {
|
|
||||||
x: X::A,
|
|
||||||
y: Y::B { c: 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_de_tokens(
|
|
||||||
&s,
|
|
||||||
&[
|
|
||||||
Token::Map { len: None },
|
|
||||||
Token::Str("typeX"),
|
|
||||||
Token::Str("A"),
|
|
||||||
Token::Str("typeY"),
|
|
||||||
Token::Str("B"),
|
|
||||||
Token::Str("c"),
|
|
||||||
Token::I32(0),
|
|
||||||
Token::MapEnd,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flatten_any_after_flatten_struct() {
|
fn test_flatten_any_after_flatten_struct() {
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
@ -3149,3 +2819,339 @@ fn test_expecting_message_identifier_enum() {
|
|||||||
r#"invalid type: map, expected something strange..."#,
|
r#"invalid type: map, expected something strange..."#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod flatten {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
mod enum_ {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
mod externally_tagged {
|
||||||
|
use super::*;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct Flatten {
|
||||||
|
#[serde(flatten)]
|
||||||
|
data: Enum,
|
||||||
|
|
||||||
|
#[serde(flatten)]
|
||||||
|
extra: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
enum Enum {
|
||||||
|
Newtype(HashMap<String, String>),
|
||||||
|
Tuple(u32, u32),
|
||||||
|
Struct { index: u32, value: u32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn newtype() {
|
||||||
|
assert_tokens(
|
||||||
|
&Flatten {
|
||||||
|
data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])),
|
||||||
|
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("Newtype"), // variant
|
||||||
|
Token::Map { len: Some(1) },
|
||||||
|
Token::Str("key"),
|
||||||
|
Token::Str("value"),
|
||||||
|
Token::MapEnd,
|
||||||
|
Token::Str("extra_key"),
|
||||||
|
Token::Str("extra value"),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
|
||||||
|
/// Content::Seq case
|
||||||
|
/// via FlatMapDeserializer::deserialize_enum
|
||||||
|
#[test]
|
||||||
|
fn tuple() {
|
||||||
|
assert_tokens(
|
||||||
|
&Flatten {
|
||||||
|
data: Enum::Tuple(0, 42),
|
||||||
|
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("Tuple"), // variant
|
||||||
|
Token::Seq { len: Some(2) },
|
||||||
|
Token::U32(0),
|
||||||
|
Token::U32(42),
|
||||||
|
Token::SeqEnd,
|
||||||
|
Token::Str("extra_key"),
|
||||||
|
Token::Str("extra value"),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reaches crate::private::de::content::VariantDeserializer::struct_variant
|
||||||
|
/// Content::Seq case
|
||||||
|
/// via FlatMapDeserializer::deserialize_enum
|
||||||
|
#[test]
|
||||||
|
fn struct_from_seq() {
|
||||||
|
assert_de_tokens(
|
||||||
|
&Flatten {
|
||||||
|
data: Enum::Struct {
|
||||||
|
index: 0,
|
||||||
|
value: 42,
|
||||||
|
},
|
||||||
|
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("Struct"), // variant
|
||||||
|
Token::Seq { len: Some(2) },
|
||||||
|
Token::U32(0), // index
|
||||||
|
Token::U32(42), // value
|
||||||
|
Token::SeqEnd,
|
||||||
|
Token::Str("extra_key"),
|
||||||
|
Token::Str("extra value"),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reaches crate::private::de::content::VariantDeserializer::struct_variant
|
||||||
|
/// Content::Map case
|
||||||
|
/// via FlatMapDeserializer::deserialize_enum
|
||||||
|
#[test]
|
||||||
|
fn struct_from_map() {
|
||||||
|
assert_tokens(
|
||||||
|
&Flatten {
|
||||||
|
data: Enum::Struct {
|
||||||
|
index: 0,
|
||||||
|
value: 42,
|
||||||
|
},
|
||||||
|
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("Struct"), // variant
|
||||||
|
Token::Struct {
|
||||||
|
len: 2,
|
||||||
|
name: "Struct",
|
||||||
|
},
|
||||||
|
Token::Str("index"),
|
||||||
|
Token::U32(0),
|
||||||
|
Token::Str("value"),
|
||||||
|
Token::U32(42),
|
||||||
|
Token::StructEnd,
|
||||||
|
Token::Str("extra_key"),
|
||||||
|
Token::Str("extra value"),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod adjacently_tagged {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct Flatten {
|
||||||
|
outer: u32,
|
||||||
|
|
||||||
|
#[serde(flatten)]
|
||||||
|
data: NewtypeWrapper,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct NewtypeWrapper(pub Enum);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "tag", content = "content")]
|
||||||
|
enum Enum {
|
||||||
|
Newtype(NewtypeVariant),
|
||||||
|
Struct { index: u32, value: u32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct NewtypeVariant {
|
||||||
|
value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_() {
|
||||||
|
assert_tokens(
|
||||||
|
&Flatten {
|
||||||
|
outer: 42,
|
||||||
|
data: NewtypeWrapper(Enum::Struct {
|
||||||
|
index: 0,
|
||||||
|
value: 42,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("outer"),
|
||||||
|
Token::U32(42),
|
||||||
|
Token::Str("tag"),
|
||||||
|
Token::Str("Struct"),
|
||||||
|
Token::Str("content"),
|
||||||
|
Token::Struct {
|
||||||
|
len: 2,
|
||||||
|
name: "Struct",
|
||||||
|
},
|
||||||
|
Token::Str("index"),
|
||||||
|
Token::U32(0),
|
||||||
|
Token::Str("value"),
|
||||||
|
Token::U32(42),
|
||||||
|
Token::StructEnd,
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn newtype() {
|
||||||
|
assert_tokens(
|
||||||
|
&Flatten {
|
||||||
|
outer: 42,
|
||||||
|
data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })),
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("outer"),
|
||||||
|
Token::U32(42),
|
||||||
|
Token::Str("tag"),
|
||||||
|
Token::Str("Newtype"),
|
||||||
|
Token::Str("content"),
|
||||||
|
Token::Struct {
|
||||||
|
len: 1,
|
||||||
|
name: "NewtypeVariant",
|
||||||
|
},
|
||||||
|
Token::Str("value"),
|
||||||
|
Token::U32(23),
|
||||||
|
Token::StructEnd,
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod internally_tagged {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn structs() {
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct Flatten {
|
||||||
|
#[serde(flatten)]
|
||||||
|
x: X,
|
||||||
|
#[serde(flatten)]
|
||||||
|
y: Y,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "typeX")]
|
||||||
|
enum X {
|
||||||
|
A { a: i32 },
|
||||||
|
B { b: i32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "typeY")]
|
||||||
|
enum Y {
|
||||||
|
C { c: i32 },
|
||||||
|
D { d: i32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_tokens(
|
||||||
|
&Flatten {
|
||||||
|
x: X::B { b: 1 },
|
||||||
|
y: Y::D { d: 2 },
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("typeX"),
|
||||||
|
Token::Str("B"),
|
||||||
|
Token::Str("b"),
|
||||||
|
Token::I32(1),
|
||||||
|
Token::Str("typeY"),
|
||||||
|
Token::Str("D"),
|
||||||
|
Token::Str("d"),
|
||||||
|
Token::I32(2),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unit_enum_with_unknown_fields() {
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
struct Flatten {
|
||||||
|
#[serde(flatten)]
|
||||||
|
x: X,
|
||||||
|
#[serde(flatten)]
|
||||||
|
y: Y,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
#[serde(tag = "typeX")]
|
||||||
|
enum X {
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
#[serde(tag = "typeY")]
|
||||||
|
enum Y {
|
||||||
|
B { c: u32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Flatten {
|
||||||
|
x: X::A,
|
||||||
|
y: Y::B { c: 0 },
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("typeX"),
|
||||||
|
Token::Str("A"),
|
||||||
|
Token::Str("typeY"),
|
||||||
|
Token::Str("B"),
|
||||||
|
Token::Str("c"),
|
||||||
|
Token::I32(0),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod untagged {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct Flatten {
|
||||||
|
#[serde(flatten)]
|
||||||
|
data: Enum,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum Enum {
|
||||||
|
Struct { a: i32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_() {
|
||||||
|
assert_tokens(
|
||||||
|
&Flatten {
|
||||||
|
data: Enum::Struct { a: 0 },
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("a"),
|
||||||
|
Token::I32(0),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1429,6 +1429,9 @@ fn test_enum_in_internally_tagged_enum() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
|
||||||
|
// Content::Seq case
|
||||||
|
// via ContentDeserializer::deserialize_enum
|
||||||
assert_tokens(
|
assert_tokens(
|
||||||
&Outer::Inner(Inner::Tuple(1, 1)),
|
&Outer::Inner(Inner::Tuple(1, 1)),
|
||||||
&[
|
&[
|
||||||
@ -1447,6 +1450,9 @@ fn test_enum_in_internally_tagged_enum() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
|
||||||
|
// Content::Map case
|
||||||
|
// via ContentDeserializer::deserialize_enum
|
||||||
assert_tokens(
|
assert_tokens(
|
||||||
&Outer::Inner(Inner::Struct { f: 1 }),
|
&Outer::Inner(Inner::Struct { f: 1 }),
|
||||||
&[
|
&[
|
||||||
@ -1464,6 +1470,23 @@ fn test_enum_in_internally_tagged_enum() {
|
|||||||
Token::MapEnd,
|
Token::MapEnd,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
|
||||||
|
// Content::Seq case
|
||||||
|
// via ContentDeserializer::deserialize_enum
|
||||||
|
assert_de_tokens(
|
||||||
|
&Outer::Inner(Inner::Struct { f: 1 }),
|
||||||
|
&[
|
||||||
|
Token::Map { len: Some(2) },
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("Inner"),
|
||||||
|
Token::Str("Struct"),
|
||||||
|
Token::Seq { len: Some(1) },
|
||||||
|
Token::U8(1), // f
|
||||||
|
Token::SeqEnd,
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user