Fix panic deserializing flattened any after flattened struct
This commit is contained in:
parent
108cca687c
commit
2a4b8ce42d
@ -2916,18 +2916,17 @@ where
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(item) => {
|
||||
while let Some(item) = self.iter.next() {
|
||||
if let Some((ref key, ref content)) = *item {
|
||||
// Do not take(), instead borrow this entry. The internally tagged
|
||||
// enum does its own buffering so we can't tell whether this entry
|
||||
// is going to be consumed. Borrowing here leaves the entry
|
||||
// available for later flattened fields.
|
||||
let (ref key, ref content) = *item.as_ref().unwrap();
|
||||
self.pending = Some(content);
|
||||
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
|
||||
return seed.deserialize(ContentRefDeserializer::new(key)).map(Some);
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
|
@ -12,9 +12,11 @@
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde;
|
||||
use self::serde::de::{self, Unexpected};
|
||||
use self::serde::de::{self, Visitor, MapAccess, Unexpected};
|
||||
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
extern crate serde_test;
|
||||
@ -2311,3 +2313,66 @@ fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_any_after_flatten_struct() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct Any;
|
||||
|
||||
impl<'de> Deserialize<'de> for Any {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct AnyVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for AnyVisitor {
|
||||
type Value = Any;
|
||||
|
||||
fn expecting(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
while let Some((Any, Any)) = map.next_entry()? {}
|
||||
Ok(Any)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(AnyVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Outer {
|
||||
#[serde(flatten)]
|
||||
inner: Inner,
|
||||
#[serde(flatten)]
|
||||
extra: Any,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
inner: i32,
|
||||
}
|
||||
|
||||
let s = Outer {
|
||||
inner: Inner {
|
||||
inner: 0,
|
||||
},
|
||||
extra: Any,
|
||||
};
|
||||
|
||||
assert_de_tokens(
|
||||
&s,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("inner"),
|
||||
Token::I32(0),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user