Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Merge pull request #312 from dtolnay/empty
Browse files Browse the repository at this point in the history
Deserialize empty plain scalar to an empty map or seq
  • Loading branch information
dtolnay committed Aug 13, 2022
2 parents 804d127 + 749bf0a commit 4c9065e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 23 deletions.
69 changes: 53 additions & 16 deletions src/de.rs
Expand Up @@ -536,7 +536,11 @@ impl<'de, 'document> DeserializerFromEvents<'de, 'document> {
V: Visitor<'de>,
{
let (value, len) = self.recursion_check(mark, |de| {
let mut seq = SeqAccess { de, len: 0 };
let mut seq = SeqAccess {
empty: false,
de,
len: 0,
};
let value = visitor.visit_seq(&mut seq)?;
Ok((value, seq.len))
})?;
Expand All @@ -550,6 +554,7 @@ impl<'de, 'document> DeserializerFromEvents<'de, 'document> {
{
let (value, len) = self.recursion_check(mark, |de| {
let mut map = MapAccess {
empty: false,
de,
len: 0,
key: None,
Expand All @@ -563,7 +568,11 @@ impl<'de, 'document> DeserializerFromEvents<'de, 'document> {

fn end_sequence(&mut self, len: usize) -> Result<()> {
let total = {
let mut seq = SeqAccess { de: self, len };
let mut seq = SeqAccess {
empty: false,
de: self,
len,
};
while de::SeqAccess::next_element::<IgnoredAny>(&mut seq)?.is_some() {}
seq.len
};
Expand Down Expand Up @@ -591,6 +600,7 @@ impl<'de, 'document> DeserializerFromEvents<'de, 'document> {
fn end_mapping(&mut self, len: usize) -> Result<()> {
let total = {
let mut map = MapAccess {
empty: false,
de: self,
len,
key: None,
Expand Down Expand Up @@ -636,6 +646,7 @@ impl<'de, 'document> DeserializerFromEvents<'de, 'document> {
}

struct SeqAccess<'de, 'document, 'seq> {
empty: bool,
de: &'seq mut DeserializerFromEvents<'de, 'document>,
len: usize,
}
Expand All @@ -647,6 +658,9 @@ impl<'de, 'document, 'seq> de::SeqAccess<'de> for SeqAccess<'de, 'document, 'seq
where
T: DeserializeSeed<'de>,
{
if self.empty {
return Ok(None);
}
match self.de.peek_event()? {
Event::SequenceEnd | Event::Void => Ok(None),
_ => {
Expand All @@ -669,6 +683,7 @@ impl<'de, 'document, 'seq> de::SeqAccess<'de> for SeqAccess<'de, 'document, 'seq
}

struct MapAccess<'de, 'document, 'map> {
empty: bool,
de: &'map mut DeserializerFromEvents<'de, 'document>,
len: usize,
key: Option<&'document [u8]>,
Expand All @@ -681,6 +696,9 @@ impl<'de, 'document, 'map> de::MapAccess<'de> for MapAccess<'de, 'document, 'map
where
K: DeserializeSeed<'de>,
{
if self.empty {
return Ok(None);
}
match self.de.peek_event()? {
Event::MappingEnd | Event::Void => Ok(None),
Event::Scalar(scalar) => {
Expand Down Expand Up @@ -1564,12 +1582,23 @@ impl<'de, 'document> de::Deserializer<'de> for &mut DeserializerFromEvents<'de,
match next {
Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_seq(visitor),
Event::SequenceStart(_) => self.visit_sequence(visitor, mark),
Event::Void => {
*self.pos -= 1;
let mut seq = SeqAccess { de: self, len: 0 };
visitor.visit_seq(&mut seq)
other => {
if match other {
Event::Void => true,
Event::Scalar(scalar) => {
scalar.value.is_empty() && scalar.style == ScalarStyle::Plain
}
_ => false,
} {
visitor.visit_seq(SeqAccess {
empty: true,
de: self,
len: 0,
})
} else {
Err(invalid_type(other, &visitor))
}
}
other => Err(invalid_type(other, &visitor)),
}
.map_err(|err| error::fix_mark(err, mark, self.path))
}
Expand Down Expand Up @@ -1601,16 +1630,24 @@ impl<'de, 'document> de::Deserializer<'de> for &mut DeserializerFromEvents<'de,
match next {
Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_map(visitor),
Event::MappingStart(_) => self.visit_mapping(visitor, mark),
Event::Void => {
*self.pos -= 1;
let mut map = MapAccess {
de: self,
len: 0,
key: None,
};
visitor.visit_map(&mut map)
other => {
if match other {
Event::Void => true,
Event::Scalar(scalar) => {
scalar.value.is_empty() && scalar.style == ScalarStyle::Plain
}
_ => false,
} {
visitor.visit_map(MapAccess {
empty: true,
de: self,
len: 0,
key: None,
})
} else {
Err(invalid_type(other, &visitor))
}
}
other => Err(invalid_type(other, &visitor)),
}
.map_err(|err| error::fix_mark(err, mark, self.path))
}
Expand Down
18 changes: 13 additions & 5 deletions src/value/de.rs
Expand Up @@ -184,7 +184,7 @@ where
let len = mapping.len();
let mut deserializer = MapRefDeserializer::new(mapping);
let map = visitor.visit_map(&mut deserializer)?;
let remaining = deserializer.iter.len();
let remaining = deserializer.iter.unwrap().len();
if remaining == 0 {
Ok(map)
} else {
Expand Down Expand Up @@ -390,6 +390,7 @@ impl<'de> Deserializer<'de> for Value {
{
match self.untag() {
Value::Sequence(v) => visit_sequence(v, visitor),
Value::Null => visit_sequence(Sequence::new(), visitor),
other => Err(other.invalid_type(&visitor)),
}
}
Expand Down Expand Up @@ -419,6 +420,7 @@ impl<'de> Deserializer<'de> for Value {
{
match self.untag() {
Value::Mapping(v) => visit_mapping(v, visitor),
Value::Null => visit_mapping(Mapping::new(), visitor),
other => Err(other.invalid_type(&visitor)),
}
}
Expand Down Expand Up @@ -903,8 +905,10 @@ impl<'de> Deserializer<'de> for &'de Value {
where
V: Visitor<'de>,
{
static EMPTY: Sequence = Sequence::new();
match self.untag_ref() {
Value::Sequence(v) => visit_sequence_ref(v, visitor),
Value::Null => visit_sequence_ref(&EMPTY, visitor),
other => Err(other.invalid_type(&visitor)),
}
}
Expand Down Expand Up @@ -934,6 +938,10 @@ impl<'de> Deserializer<'de> for &'de Value {
{
match self.untag_ref() {
Value::Mapping(v) => visit_mapping_ref(v, visitor),
Value::Null => visitor.visit_map(&mut MapRefDeserializer {
iter: None,
value: None,
}),
other => Err(other.invalid_type(&visitor)),
}
}
Expand Down Expand Up @@ -1138,14 +1146,14 @@ impl<'de> SeqAccess<'de> for SeqRefDeserializer<'de> {
}

pub(crate) struct MapRefDeserializer<'de> {
iter: <&'de Mapping as IntoIterator>::IntoIter,
iter: Option<<&'de Mapping as IntoIterator>::IntoIter>,
value: Option<&'de Value>,
}

impl<'de> MapRefDeserializer<'de> {
pub(crate) fn new(map: &'de Mapping) -> Self {
MapRefDeserializer {
iter: map.iter(),
iter: Some(map.iter()),
value: None,
}
}
Expand All @@ -1158,7 +1166,7 @@ impl<'de> MapAccess<'de> for MapRefDeserializer<'de> {
where
T: DeserializeSeed<'de>,
{
match self.iter.next() {
match self.iter.as_mut().and_then(Iterator::next) {
Some((key, value)) => {
self.value = Some(value);
seed.deserialize(key).map(Some)
Expand All @@ -1178,7 +1186,7 @@ impl<'de> MapAccess<'de> for MapRefDeserializer<'de> {
}

fn size_hint(&self) -> Option<usize> {
match self.iter.size_hint() {
match self.iter.as_ref()?.size_hint() {
(lower, Some(upper)) if lower == upper => Some(upper),
_ => None,
}
Expand Down
19 changes: 19 additions & 0 deletions tests/test_de.rs
Expand Up @@ -550,3 +550,22 @@ fn test_no_required_fields() {
assert_eq!(expected, deserialized);
}
}

#[test]
fn test_empty_scalar() {
#[derive(Deserialize, PartialEq, Debug)]
struct Struct<T> {
thing: T,
}

let yaml = "thing:\n";
let expected = Struct {
thing: serde_yaml::Sequence::new(),
};
test_de(yaml, &expected);

let expected = Struct {
thing: serde_yaml::Mapping::new(),
};
test_de(yaml, &expected);
}
4 changes: 2 additions & 2 deletions tests/test_error.rs
Expand Up @@ -328,8 +328,8 @@ fn test_invalid_scalar_type() {
x: [i32; 1],
}

let yaml = "x:\n";
let expected = "x: invalid type: unit value, expected an array of length 1 at line 1 column 3";
let yaml = "x: ''\n";
let expected = "x: invalid type: string \"\", expected an array of length 1 at line 1 column 4";
test_error::<S>(yaml, expected);
}

Expand Down

0 comments on commit 4c9065e

Please sign in to comment.