diff options
author | est31 <est31@users.noreply.github.com> | 2019-10-28 15:01:23 +0100 |
---|---|---|
committer | Alex Crichton <alex@alexcrichton.com> | 2019-10-28 09:01:23 -0500 |
commit | ec21d604f892a06999a9d38d38c903e083ad1f08 (patch) | |
tree | 28d5e177d3a8eeb8e7e2195363a4c1b823c11ea2 /src | |
parent | e9f5290926dd7a5660f4f86bfc44591710079fe0 (diff) | |
download | milf-rs-ec21d604f892a06999a9d38d38c903e083ad1f08.tar.gz milf-rs-ec21d604f892a06999a9d38d38c903e083ad1f08.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/de.rs | 56 |
1 files changed, 50 insertions, 6 deletions
@@ -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<TablePair<'de>>, + values: iter::Peekable<vec::IntoIter<TablePair<'de>>>, next_value: Option<TablePair<'de>>, 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<V>( + mut self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + 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<T>. + 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<V>( 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; |