From ec21d604f892a06999a9d38d38c903e083ad1f08 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 28 Oct 2019 15:01:23 +0100 Subject: Support for dotted table spans (#340) * "Support" spans for maps In toml you can declare maps via {} and via [name]. We can't obtain spans for [] maps but at least we can emit fake spans to make SpannedValue work. We also add a regression test. * Don't regress the inline table case * Also support arrays --- src/de.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/de.rs b/src/de.rs index 9bb5204..0e1ae6a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -8,6 +8,7 @@ use std::borrow::Cow; use std::error; use std::f64; use std::fmt; +use std::iter; use std::marker::PhantomData; use std::mem::discriminant; use std::str; @@ -216,7 +217,7 @@ impl<'de, 'b> de::Deserializer<'de> for &'b mut Deserializer<'de> { let mut tables = self.tables()?; let res = visitor.visit_map(MapVisitor { - values: Vec::new().into_iter(), + values: Vec::new().into_iter().peekable(), next_value: None, depth: 0, cur: 0, @@ -333,7 +334,7 @@ struct Table<'a> { } struct MapVisitor<'de, 'b> { - values: vec::IntoIter>, + values: iter::Peekable>>, next_value: Option>, depth: usize, cur: usize, @@ -440,7 +441,8 @@ impl<'de, 'b> de::MapAccess<'de> for MapVisitor<'de, 'b> { .values .take() .expect("Unable to read table values") - .into_iter(); + .into_iter() + .peekable(); } } @@ -462,7 +464,7 @@ impl<'de, 'b> de::MapAccess<'de> for MapVisitor<'de, 'b> { self.tables[self.cur].array && self.depth == self.tables[self.cur].header.len() - 1; self.cur += 1; let res = seed.deserialize(MapVisitor { - values: Vec::new().into_iter(), + values: Vec::new().into_iter().peekable(), next_value: None, depth: self.depth + if array { 0 } else { 1 }, cur_parent: self.cur - 1, @@ -509,7 +511,8 @@ impl<'de, 'b> de::SeqAccess<'de> for MapVisitor<'de, 'b> { .values .take() .expect("Unable to read table values") - .into_iter(), + .into_iter() + .peekable(), next_value: None, depth: self.depth + 1, cur_parent: self.cur_parent, @@ -558,6 +561,39 @@ impl<'de, 'b> de::Deserializer<'de> for MapVisitor<'de, 'b> { visitor.visit_newtype_struct(self) } + fn deserialize_struct( + mut self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + if name == spanned::NAME + && fields == [spanned::START, spanned::END, spanned::VALUE] + && !(self.array && !self.values.peek().is_none()) + { + // TODO we can't actually emit spans here for the *entire* table/array + // due to the format that toml uses. Setting the start and end to 0 is + // *detectable* (and no reasonable span would look like that), + // it would be better to expose this in the API via proper + // ADTs like Option. + let start = 0; + let end = 0; + + let res = visitor.visit_map(SpannedDeserializer { + phantom_data: PhantomData, + start: Some(start), + value: Some(self), + end: Some(end), + }); + return res; + } + + self.deserialize_any(visitor) + } + fn deserialize_enum( self, _name: &'static str, @@ -591,7 +627,7 @@ impl<'de, 'b> de::Deserializer<'de> for MapVisitor<'de, 'b> { serde::forward_to_deserialize_any! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq - bytes byte_buf map struct unit identifier + bytes byte_buf map unit identifier ignored_any unit_struct tuple_struct tuple } } @@ -853,6 +889,14 @@ impl<'de> de::Deserializer<'de> for ValueDeserializer<'de> { } } +impl<'de, 'b> de::IntoDeserializer<'de, Error> for MapVisitor<'de, 'b> { + type Deserializer = MapVisitor<'de, 'b>; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + impl<'de, 'b> de::IntoDeserializer<'de, Error> for &'b mut Deserializer<'de> { type Deserializer = Self; -- cgit v1.2.3