diff --git a/src/de.rs b/src/de.rs index c76eeef0..5c4006f0 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, BTreeMap}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::hash::Hash; use std::marker::PhantomData; use std::num::FromPrimitive; @@ -644,6 +644,111 @@ impl Deserialize for Option where T: Deserialize { /////////////////////////////////////////////////////////////////////////////// +pub struct BTreeSetVisitor { + marker: PhantomData, +} + +impl BTreeSetVisitor { + pub fn new() -> Self { + BTreeSetVisitor { + marker: PhantomData, + } + } +} + +impl Visitor for BTreeSetVisitor + where T: Deserialize + Eq + Ord, +{ + type Value = BTreeSet; + + #[inline] + fn visit_unit(&mut self) -> Result, E> + where E: Error, + { + Ok(BTreeSet::new()) + } + + #[inline] + fn visit_seq(&mut self, mut visitor: V) -> Result, V::Error> + where V: SeqVisitor, + { + let mut values = BTreeSet::new(); + + while let Some(value) = try!(visitor.visit()) { + values.insert(value); + } + + try!(visitor.end()); + + Ok(values) + } +} + +impl Deserialize for BTreeSet + where T: Deserialize + Eq + Ord, +{ + fn deserialize(deserializer: &mut D) -> Result, D::Error> + where D: Deserializer, + { + deserializer.visit(BTreeSetVisitor::new()) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +pub struct HashSetVisitor { + marker: PhantomData, +} + +impl HashSetVisitor { + pub fn new() -> Self { + HashSetVisitor { + marker: PhantomData, + } + } +} + +impl Visitor for HashSetVisitor + where T: Deserialize + Eq + Hash, +{ + type Value = HashSet; + + #[inline] + fn visit_unit(&mut self) -> Result, E> + where E: Error, + { + Ok(HashSet::new()) + } + + #[inline] + fn visit_seq(&mut self, mut visitor: V) -> Result, V::Error> + where V: SeqVisitor, + { + let (len, _) = visitor.size_hint(); + let mut values = HashSet::with_capacity(len); + + while let Some(value) = try!(visitor.visit()) { + values.insert(value); + } + + try!(visitor.end()); + + Ok(values) + } +} + +impl Deserialize for HashSet + where T: Deserialize + Eq + Hash, +{ + fn deserialize(deserializer: &mut D) -> Result, D::Error> + where D: Deserializer, + { + deserializer.visit(HashSetVisitor::new()) + } +} + +/////////////////////////////////////////////////////////////////////////////// + pub struct VecVisitor { marker: PhantomData, } @@ -663,7 +768,7 @@ impl Visitor for VecVisitor where T: Deserialize { fn visit_unit(&mut self) -> Result, E> where E: Error, { - Ok(vec![]) + Ok(Vec::new()) } #[inline] @@ -683,7 +788,9 @@ impl Visitor for VecVisitor where T: Deserialize { } } -impl Deserialize for Vec { +impl Deserialize for Vec + where T: Deserialize, +{ fn deserialize(deserializer: &mut D) -> Result, D::Error> where D: Deserializer, { @@ -755,6 +862,61 @@ tuple_impls! { /////////////////////////////////////////////////////////////////////////////// +pub struct BTreeMapVisitor { + marker: PhantomData>, +} + +impl BTreeMapVisitor { + #[inline] + pub fn new() -> Self { + BTreeMapVisitor { + marker: PhantomData, + } + } +} + +impl Visitor for BTreeMapVisitor + where K: Deserialize + Ord, + V: Deserialize +{ + type Value = BTreeMap; + + #[inline] + fn visit_unit(&mut self) -> Result, E> + where E: Error, + { + Ok(BTreeMap::new()) + } + + #[inline] + fn visit_map(&mut self, mut visitor: Visitor) -> Result, Visitor::Error> + where Visitor: MapVisitor, + { + let mut values = BTreeMap::new(); + + while let Some((key, value)) = try!(visitor.visit()) { + values.insert(key, value); + } + + try!(visitor.end()); + + Ok(values) + } +} + +impl Deserialize for BTreeMap + where K: Deserialize + Eq + Ord, + V: Deserialize, +{ + fn deserialize(deserializer: &mut D) -> Result, D::Error> + where D: Deserializer, + { + deserializer.visit(BTreeMapVisitor::new()) + } +} + +/////////////////////////////////////////////////////////////////////////////// + pub struct HashMapVisitor { marker: PhantomData>, } @@ -811,61 +973,6 @@ impl Deserialize for HashMap /////////////////////////////////////////////////////////////////////////////// -pub struct BTreeMapVisitor { - marker: PhantomData>, -} - -impl BTreeMapVisitor { - #[inline] - pub fn new() -> Self { - BTreeMapVisitor { - marker: PhantomData, - } - } -} - -impl Visitor for BTreeMapVisitor - where K: Deserialize + Ord, - V: Deserialize -{ - type Value = BTreeMap; - - #[inline] - fn visit_unit(&mut self) -> Result, E> - where E: Error, - { - Ok(BTreeMap::new()) - } - - #[inline] - fn visit_map(&mut self, mut visitor: Visitor) -> Result, Visitor::Error> - where Visitor: MapVisitor, - { - let mut values = BTreeMap::new(); - - while let Some((key, value)) = try!(visitor.visit()) { - values.insert(key, value); - } - - try!(visitor.end()); - - Ok(values) - } -} - -impl< - K: Deserialize + Eq + Ord, - V: Deserialize, -> Deserialize for BTreeMap { - fn deserialize(deserializer: &mut D) -> Result, D::Error> - where D: Deserializer, - { - deserializer.visit(BTreeMapVisitor::new()) - } -} - -/////////////////////////////////////////////////////////////////////////////// - struct PathBufVisitor; impl Visitor for PathBufVisitor { diff --git a/tests/test_de.rs b/tests/test_de.rs index c0a69f2f..53473956 100644 --- a/tests/test_de.rs +++ b/tests/test_de.rs @@ -4,7 +4,7 @@ extern crate test; extern crate serde; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::iter; use std::vec; @@ -36,11 +36,11 @@ enum Token { Unit, SeqStart(usize), - SeqSep(bool), + SeqSep, SeqEnd, MapStart(usize), - MapSep(bool), + MapSep, MapEnd, EnumStart(&'static str), @@ -107,14 +107,12 @@ impl Deserializer for TokenDeserializer { visitor.visit_seq(TokenDeserializerSeqVisitor { de: self, len: len, - first: true, }) } Some(Token::MapStart(len)) => { visitor.visit_map(TokenDeserializerMapVisitor { de: self, len: len, - first: true, }) } Some(Token::Name(_)) => self.visit(visitor), @@ -221,7 +219,6 @@ impl Deserializer for TokenDeserializer { struct TokenDeserializerSeqVisitor<'a> { de: &'a mut TokenDeserializer, len: usize, - first: bool, } impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> { @@ -230,11 +227,8 @@ impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> { fn visit(&mut self) -> Result, Error> where T: Deserialize, { - let first = self.first; - self.first = false; - match self.de.tokens.peek() { - Some(&Token::SeqSep(first_)) if first_ == first => { + Some(&Token::SeqSep) => { self.len -= 1; self.de.tokens.next(); Ok(Some(try!(Deserialize::deserialize(self.de)))) @@ -266,7 +260,6 @@ impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> { struct TokenDeserializerMapVisitor<'a> { de: &'a mut TokenDeserializer, len: usize, - first: bool, } impl<'a> de::MapVisitor for TokenDeserializerMapVisitor<'a> { @@ -275,11 +268,8 @@ impl<'a> de::MapVisitor for TokenDeserializerMapVisitor<'a> { fn visit_key(&mut self) -> Result, Error> where K: Deserialize, { - let first = self.first; - self.first = false; - match self.de.tokens.peek() { - Some(&Token::MapSep(first_)) if first_ == first => { + Some(&Token::MapSep) => { self.de.tokens.next(); self.len -= 1; Ok(Some(try!(Deserialize::deserialize(self.de)))) @@ -356,6 +346,19 @@ enum Enum { ////////////////////////////////////////////////////////////////////////// +macro_rules! btreeset { + () => { + BTreeSet::new() + }; + ($($value:expr),+) => { + { + let mut set = BTreeSet::new(); + $(set.insert($value);)+ + set + } + } +} + macro_rules! btreemap { () => { BTreeMap::new() @@ -369,6 +372,32 @@ macro_rules! btreemap { } } +macro_rules! hashset { + () => { + HashSet::new() + }; + ($($value:expr),+) => { + { + let mut set = HashSet::new(); + $(set.insert($value);)+ + set + } + } +} + +macro_rules! hashmap { + () => { + HashMap::new() + }; + ($($key:expr => $value:expr),+) => { + { + let mut map = HashMap::new(); + $(map.insert($key, $value);)+ + map + } + } +} + macro_rules! declare_test { ($name:ident { $($value:expr => $tokens:expr,)+ }) => { #[test] @@ -474,30 +503,100 @@ declare_tests! { test_named_seq { NamedSeq(1, 2, 3) => vec![ Token::SeqStart(3), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, ], NamedSeq(1, 2, 3) => vec![ Token::Name("NamedSeq"), Token::SeqStart(3), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, ], } + test_btreeset { + BTreeSet::::new() => vec![ + Token::Unit, + ], + BTreeSet::::new() => vec![ + Token::SeqStart(0), + Token::SeqEnd, + ], + btreeset![btreeset![], btreeset![1], btreeset![2, 3]] => vec![ + Token::SeqStart(3), + Token::SeqSep, + Token::SeqStart(0), + Token::SeqEnd, + + Token::SeqSep, + Token::SeqStart(1), + Token::SeqSep, + Token::I32(1), + Token::SeqEnd, + + Token::SeqSep, + Token::SeqStart(2), + Token::SeqSep, + Token::I32(2), + + Token::SeqSep, + Token::I32(3), + Token::SeqEnd, + Token::SeqEnd, + ], + BTreeSet::::new() => vec![ + Token::Name("Anything"), + Token::Unit, + ], + BTreeSet::::new() => vec![ + Token::Name("Anything"), + Token::SeqStart(0), + Token::SeqEnd, + ], + } + test_hashset { + HashSet::::new() => vec![ + Token::Unit, + ], + HashSet::::new() => vec![ + Token::SeqStart(0), + Token::SeqEnd, + ], + hashset![1, 2, 3] => vec![ + Token::SeqStart(3), + Token::SeqSep, + Token::I32(1), + + Token::SeqSep, + Token::I32(2), + + Token::SeqSep, + Token::I32(3), + Token::SeqEnd, + ], + HashSet::::new() => vec![ + Token::Name("Anything"), + Token::Unit, + ], + HashSet::::new() => vec![ + Token::Name("Anything"), + Token::SeqStart(0), + Token::SeqEnd, + ], + } test_vec { Vec::::new() => vec![ Token::Unit, @@ -508,22 +607,22 @@ declare_tests! { ], vec![vec![], vec![1], vec![2, 3]] => vec![ Token::SeqStart(3), - Token::SeqSep(true), + Token::SeqSep, Token::SeqStart(0), Token::SeqEnd, - Token::SeqSep(false), + Token::SeqSep, Token::SeqStart(1), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), Token::SeqEnd, - Token::SeqSep(false), + Token::SeqSep, Token::SeqStart(2), - Token::SeqSep(true), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, Token::SeqEnd, @@ -541,19 +640,19 @@ declare_tests! { test_tuple { (1,) => vec![ Token::SeqStart(1), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), Token::SeqEnd, ], (1, 2, 3) => vec![ Token::SeqStart(3), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, ], @@ -568,37 +667,37 @@ declare_tests! { ], btreemap![1 => 2] => vec![ Token::MapStart(1), - Token::MapSep(true), + Token::MapSep, Token::I32(1), Token::I32(2), Token::MapEnd, ], btreemap![1 => 2, 3 => 4] => vec![ Token::MapStart(2), - Token::MapSep(true), + Token::MapSep, Token::I32(1), Token::I32(2), - Token::MapSep(false), + Token::MapSep, Token::I32(3), Token::I32(4), Token::MapEnd, ], btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![ Token::MapStart(2), - Token::MapSep(true), + Token::MapSep, Token::I32(1), Token::MapStart(0), Token::MapEnd, - Token::MapSep(false), + Token::MapSep, Token::I32(2), Token::MapStart(2), - Token::MapSep(true), + Token::MapSep, Token::I32(3), Token::I32(4), - Token::MapSep(false), + Token::MapSep, Token::I32(5), Token::I32(6), Token::MapEnd, @@ -614,18 +713,74 @@ declare_tests! { Token::MapEnd, ], } + test_hashmap { + HashMap::::new() => vec![ + Token::Unit, + ], + HashMap::::new() => vec![ + Token::MapStart(0), + Token::MapEnd, + ], + hashmap![1 => 2] => vec![ + Token::MapStart(1), + Token::MapSep, + Token::I32(1), + Token::I32(2), + Token::MapEnd, + ], + hashmap![1 => 2, 3 => 4] => vec![ + Token::MapStart(2), + Token::MapSep, + Token::I32(1), + Token::I32(2), + + Token::MapSep, + Token::I32(3), + Token::I32(4), + Token::MapEnd, + ], + hashmap![1 => hashmap![], 2 => hashmap![3 => 4, 5 => 6]] => vec![ + Token::MapStart(2), + Token::MapSep, + Token::I32(1), + Token::MapStart(0), + Token::MapEnd, + + Token::MapSep, + Token::I32(2), + Token::MapStart(2), + Token::MapSep, + Token::I32(3), + Token::I32(4), + + Token::MapSep, + Token::I32(5), + Token::I32(6), + Token::MapEnd, + Token::MapEnd, + ], + HashMap::::new() => vec![ + Token::Name("Anything"), + Token::Unit, + ], + HashMap::::new() => vec![ + Token::Name("Anything"), + Token::MapStart(0), + Token::MapEnd, + ], + } test_named_map { NamedMap { a: 1, b: 2, c: 3 } => vec![ Token::MapStart(3), - Token::MapSep(true), + Token::MapSep, Token::Str("a"), Token::I32(1), - Token::MapSep(false), + Token::MapSep, Token::Str("b"), Token::I32(2), - Token::MapSep(false), + Token::MapSep, Token::Str("c"), Token::I32(3), Token::MapEnd, @@ -633,15 +788,15 @@ declare_tests! { NamedMap { a: 1, b: 2, c: 3 } => vec![ Token::Name("NamedMap"), Token::MapStart(3), - Token::MapSep(true), + Token::MapSep, Token::Str("a"), Token::I32(1), - Token::MapSep(false), + Token::MapSep, Token::Str("b"), Token::I32(2), - Token::MapSep(false), + Token::MapSep, Token::Str("c"), Token::I32(3), Token::MapEnd, @@ -660,13 +815,13 @@ declare_tests! { Token::EnumStart("Enum"), Token::Str("Seq"), Token::SeqStart(3), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, Token::EnumEnd, @@ -677,15 +832,15 @@ declare_tests! { Token::EnumStart("Enum"), Token::Str("Map"), Token::MapStart(3), - Token::MapSep(true), + Token::MapSep, Token::Str("a"), Token::I32(1), - Token::MapSep(false), + Token::MapSep, Token::Str("b"), Token::I32(2), - Token::MapSep(false), + Token::MapSep, Token::Str("c"), Token::I32(3), Token::MapEnd,