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

Deserialize empty plain scalar to an empty map or seq #312

Merged
merged 1 commit into from Aug 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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