Add deserialization impls for {BTree,Hash}{Map,Set}

This commit is contained in:
Erick Tryzelaar
2015-03-20 20:35:01 -07:00
parent 9059b734aa
commit 1618faed63
2 changed files with 370 additions and 108 deletions
+165 -58
View File
@@ -1,4 +1,4 @@
use std::collections::{HashMap, BTreeMap}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::num::FromPrimitive; use std::num::FromPrimitive;
@@ -644,6 +644,111 @@ impl<T> Deserialize for Option<T> where T: Deserialize {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
pub struct BTreeSetVisitor<T> {
marker: PhantomData<T>,
}
impl<T> BTreeSetVisitor<T> {
pub fn new() -> Self {
BTreeSetVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for BTreeSetVisitor<T>
where T: Deserialize + Eq + Ord,
{
type Value = BTreeSet<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<BTreeSet<T>, E>
where E: Error,
{
Ok(BTreeSet::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<BTreeSet<T>, 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<T> Deserialize for BTreeSet<T>
where T: Deserialize + Eq + Ord,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeSet<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeSetVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct HashSetVisitor<T> {
marker: PhantomData<T>,
}
impl<T> HashSetVisitor<T> {
pub fn new() -> Self {
HashSetVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for HashSetVisitor<T>
where T: Deserialize + Eq + Hash,
{
type Value = HashSet<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<HashSet<T>, E>
where E: Error,
{
Ok(HashSet::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<HashSet<T>, 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<T> Deserialize for HashSet<T>
where T: Deserialize + Eq + Hash,
{
fn deserialize<D>(deserializer: &mut D) -> Result<HashSet<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(HashSetVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct VecVisitor<T> { pub struct VecVisitor<T> {
marker: PhantomData<T>, marker: PhantomData<T>,
} }
@@ -663,7 +768,7 @@ impl<T> Visitor for VecVisitor<T> where T: Deserialize {
fn visit_unit<E>(&mut self) -> Result<Vec<T>, E> fn visit_unit<E>(&mut self) -> Result<Vec<T>, E>
where E: Error, where E: Error,
{ {
Ok(vec![]) Ok(Vec::new())
} }
#[inline] #[inline]
@@ -683,7 +788,9 @@ impl<T> Visitor for VecVisitor<T> where T: Deserialize {
} }
} }
impl<T: Deserialize> Deserialize for Vec<T> { impl<T> Deserialize for Vec<T>
where T: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<Vec<T>, D::Error> fn deserialize<D>(deserializer: &mut D) -> Result<Vec<T>, D::Error>
where D: Deserializer, where D: Deserializer,
{ {
@@ -755,6 +862,61 @@ tuple_impls! {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
pub struct BTreeMapVisitor<K, V> {
marker: PhantomData<BTreeMap<K, V>>,
}
impl<K, V> BTreeMapVisitor<K, V> {
#[inline]
pub fn new() -> Self {
BTreeMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for BTreeMapVisitor<K, V>
where K: Deserialize + Ord,
V: Deserialize
{
type Value = BTreeMap<K, V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<BTreeMap<K, V>, E>
where E: Error,
{
Ok(BTreeMap::new())
}
#[inline]
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<BTreeMap<K, V>, 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, V> Deserialize for BTreeMap<K, V>
where K: Deserialize + Eq + Ord,
V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeMapVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct HashMapVisitor<K, V> { pub struct HashMapVisitor<K, V> {
marker: PhantomData<HashMap<K, V>>, marker: PhantomData<HashMap<K, V>>,
} }
@@ -811,61 +973,6 @@ impl<K, V> Deserialize for HashMap<K, V>
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
pub struct BTreeMapVisitor<K, V> {
marker: PhantomData<BTreeMap<K, V>>,
}
impl<K, V> BTreeMapVisitor<K, V> {
#[inline]
pub fn new() -> Self {
BTreeMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for BTreeMapVisitor<K, V>
where K: Deserialize + Ord,
V: Deserialize
{
type Value = BTreeMap<K, V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<BTreeMap<K, V>, E>
where E: Error,
{
Ok(BTreeMap::new())
}
#[inline]
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<BTreeMap<K, V>, 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<K, V> {
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeMapVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
struct PathBufVisitor; struct PathBufVisitor;
impl Visitor for PathBufVisitor { impl Visitor for PathBufVisitor {
+205 -50
View File
@@ -4,7 +4,7 @@
extern crate test; extern crate test;
extern crate serde; extern crate serde;
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::iter; use std::iter;
use std::vec; use std::vec;
@@ -36,11 +36,11 @@ enum Token {
Unit, Unit,
SeqStart(usize), SeqStart(usize),
SeqSep(bool), SeqSep,
SeqEnd, SeqEnd,
MapStart(usize), MapStart(usize),
MapSep(bool), MapSep,
MapEnd, MapEnd,
EnumStart(&'static str), EnumStart(&'static str),
@@ -107,14 +107,12 @@ impl Deserializer for TokenDeserializer {
visitor.visit_seq(TokenDeserializerSeqVisitor { visitor.visit_seq(TokenDeserializerSeqVisitor {
de: self, de: self,
len: len, len: len,
first: true,
}) })
} }
Some(Token::MapStart(len)) => { Some(Token::MapStart(len)) => {
visitor.visit_map(TokenDeserializerMapVisitor { visitor.visit_map(TokenDeserializerMapVisitor {
de: self, de: self,
len: len, len: len,
first: true,
}) })
} }
Some(Token::Name(_)) => self.visit(visitor), Some(Token::Name(_)) => self.visit(visitor),
@@ -221,7 +219,6 @@ impl Deserializer for TokenDeserializer {
struct TokenDeserializerSeqVisitor<'a> { struct TokenDeserializerSeqVisitor<'a> {
de: &'a mut TokenDeserializer, de: &'a mut TokenDeserializer,
len: usize, len: usize,
first: bool,
} }
impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> { impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> {
@@ -230,11 +227,8 @@ impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> {
fn visit<T>(&mut self) -> Result<Option<T>, Error> fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize, where T: Deserialize,
{ {
let first = self.first;
self.first = false;
match self.de.tokens.peek() { match self.de.tokens.peek() {
Some(&Token::SeqSep(first_)) if first_ == first => { Some(&Token::SeqSep) => {
self.len -= 1; self.len -= 1;
self.de.tokens.next(); self.de.tokens.next();
Ok(Some(try!(Deserialize::deserialize(self.de)))) Ok(Some(try!(Deserialize::deserialize(self.de))))
@@ -266,7 +260,6 @@ impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> {
struct TokenDeserializerMapVisitor<'a> { struct TokenDeserializerMapVisitor<'a> {
de: &'a mut TokenDeserializer, de: &'a mut TokenDeserializer,
len: usize, len: usize,
first: bool,
} }
impl<'a> de::MapVisitor for TokenDeserializerMapVisitor<'a> { impl<'a> de::MapVisitor for TokenDeserializerMapVisitor<'a> {
@@ -275,11 +268,8 @@ impl<'a> de::MapVisitor for TokenDeserializerMapVisitor<'a> {
fn visit_key<K>(&mut self) -> Result<Option<K>, Error> fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: Deserialize, where K: Deserialize,
{ {
let first = self.first;
self.first = false;
match self.de.tokens.peek() { match self.de.tokens.peek() {
Some(&Token::MapSep(first_)) if first_ == first => { Some(&Token::MapSep) => {
self.de.tokens.next(); self.de.tokens.next();
self.len -= 1; self.len -= 1;
Ok(Some(try!(Deserialize::deserialize(self.de)))) 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 { macro_rules! btreemap {
() => { () => {
BTreeMap::new() 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 { macro_rules! declare_test {
($name:ident { $($value:expr => $tokens:expr,)+ }) => { ($name:ident { $($value:expr => $tokens:expr,)+ }) => {
#[test] #[test]
@@ -474,30 +503,100 @@ declare_tests! {
test_named_seq { test_named_seq {
NamedSeq(1, 2, 3) => vec![ NamedSeq(1, 2, 3) => vec![
Token::SeqStart(3), Token::SeqStart(3),
Token::SeqSep(true), Token::SeqSep,
Token::I32(1), Token::I32(1),
Token::SeqSep(false), Token::SeqSep,
Token::I32(2), Token::I32(2),
Token::SeqSep(false), Token::SeqSep,
Token::I32(3), Token::I32(3),
Token::SeqEnd, Token::SeqEnd,
], ],
NamedSeq(1, 2, 3) => vec![ NamedSeq(1, 2, 3) => vec![
Token::Name("NamedSeq"), Token::Name("NamedSeq"),
Token::SeqStart(3), Token::SeqStart(3),
Token::SeqSep(true), Token::SeqSep,
Token::I32(1), Token::I32(1),
Token::SeqSep(false), Token::SeqSep,
Token::I32(2), Token::I32(2),
Token::SeqSep(false), Token::SeqSep,
Token::I32(3), Token::I32(3),
Token::SeqEnd, Token::SeqEnd,
], ],
} }
test_btreeset {
BTreeSet::<isize>::new() => vec![
Token::Unit,
],
BTreeSet::<isize>::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::<isize>::new() => vec![
Token::Name("Anything"),
Token::Unit,
],
BTreeSet::<isize>::new() => vec![
Token::Name("Anything"),
Token::SeqStart(0),
Token::SeqEnd,
],
}
test_hashset {
HashSet::<isize>::new() => vec![
Token::Unit,
],
HashSet::<isize>::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::<isize>::new() => vec![
Token::Name("Anything"),
Token::Unit,
],
HashSet::<isize>::new() => vec![
Token::Name("Anything"),
Token::SeqStart(0),
Token::SeqEnd,
],
}
test_vec { test_vec {
Vec::<isize>::new() => vec![ Vec::<isize>::new() => vec![
Token::Unit, Token::Unit,
@@ -508,22 +607,22 @@ declare_tests! {
], ],
vec![vec![], vec![1], vec![2, 3]] => vec![ vec![vec![], vec![1], vec![2, 3]] => vec![
Token::SeqStart(3), Token::SeqStart(3),
Token::SeqSep(true), Token::SeqSep,
Token::SeqStart(0), Token::SeqStart(0),
Token::SeqEnd, Token::SeqEnd,
Token::SeqSep(false), Token::SeqSep,
Token::SeqStart(1), Token::SeqStart(1),
Token::SeqSep(true), Token::SeqSep,
Token::I32(1), Token::I32(1),
Token::SeqEnd, Token::SeqEnd,
Token::SeqSep(false), Token::SeqSep,
Token::SeqStart(2), Token::SeqStart(2),
Token::SeqSep(true), Token::SeqSep,
Token::I32(2), Token::I32(2),
Token::SeqSep(false), Token::SeqSep,
Token::I32(3), Token::I32(3),
Token::SeqEnd, Token::SeqEnd,
Token::SeqEnd, Token::SeqEnd,
@@ -541,19 +640,19 @@ declare_tests! {
test_tuple { test_tuple {
(1,) => vec![ (1,) => vec![
Token::SeqStart(1), Token::SeqStart(1),
Token::SeqSep(true), Token::SeqSep,
Token::I32(1), Token::I32(1),
Token::SeqEnd, Token::SeqEnd,
], ],
(1, 2, 3) => vec![ (1, 2, 3) => vec![
Token::SeqStart(3), Token::SeqStart(3),
Token::SeqSep(true), Token::SeqSep,
Token::I32(1), Token::I32(1),
Token::SeqSep(false), Token::SeqSep,
Token::I32(2), Token::I32(2),
Token::SeqSep(false), Token::SeqSep,
Token::I32(3), Token::I32(3),
Token::SeqEnd, Token::SeqEnd,
], ],
@@ -568,37 +667,37 @@ declare_tests! {
], ],
btreemap![1 => 2] => vec![ btreemap![1 => 2] => vec![
Token::MapStart(1), Token::MapStart(1),
Token::MapSep(true), Token::MapSep,
Token::I32(1), Token::I32(1),
Token::I32(2), Token::I32(2),
Token::MapEnd, Token::MapEnd,
], ],
btreemap![1 => 2, 3 => 4] => vec![ btreemap![1 => 2, 3 => 4] => vec![
Token::MapStart(2), Token::MapStart(2),
Token::MapSep(true), Token::MapSep,
Token::I32(1), Token::I32(1),
Token::I32(2), Token::I32(2),
Token::MapSep(false), Token::MapSep,
Token::I32(3), Token::I32(3),
Token::I32(4), Token::I32(4),
Token::MapEnd, Token::MapEnd,
], ],
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![ btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![
Token::MapStart(2), Token::MapStart(2),
Token::MapSep(true), Token::MapSep,
Token::I32(1), Token::I32(1),
Token::MapStart(0), Token::MapStart(0),
Token::MapEnd, Token::MapEnd,
Token::MapSep(false), Token::MapSep,
Token::I32(2), Token::I32(2),
Token::MapStart(2), Token::MapStart(2),
Token::MapSep(true), Token::MapSep,
Token::I32(3), Token::I32(3),
Token::I32(4), Token::I32(4),
Token::MapSep(false), Token::MapSep,
Token::I32(5), Token::I32(5),
Token::I32(6), Token::I32(6),
Token::MapEnd, Token::MapEnd,
@@ -614,18 +713,74 @@ declare_tests! {
Token::MapEnd, Token::MapEnd,
], ],
} }
test_hashmap {
HashMap::<isize, isize>::new() => vec![
Token::Unit,
],
HashMap::<isize, isize>::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::<isize, isize>::new() => vec![
Token::Name("Anything"),
Token::Unit,
],
HashMap::<isize, isize>::new() => vec![
Token::Name("Anything"),
Token::MapStart(0),
Token::MapEnd,
],
}
test_named_map { test_named_map {
NamedMap { a: 1, b: 2, c: 3 } => vec![ NamedMap { a: 1, b: 2, c: 3 } => vec![
Token::MapStart(3), Token::MapStart(3),
Token::MapSep(true), Token::MapSep,
Token::Str("a"), Token::Str("a"),
Token::I32(1), Token::I32(1),
Token::MapSep(false), Token::MapSep,
Token::Str("b"), Token::Str("b"),
Token::I32(2), Token::I32(2),
Token::MapSep(false), Token::MapSep,
Token::Str("c"), Token::Str("c"),
Token::I32(3), Token::I32(3),
Token::MapEnd, Token::MapEnd,
@@ -633,15 +788,15 @@ declare_tests! {
NamedMap { a: 1, b: 2, c: 3 } => vec![ NamedMap { a: 1, b: 2, c: 3 } => vec![
Token::Name("NamedMap"), Token::Name("NamedMap"),
Token::MapStart(3), Token::MapStart(3),
Token::MapSep(true), Token::MapSep,
Token::Str("a"), Token::Str("a"),
Token::I32(1), Token::I32(1),
Token::MapSep(false), Token::MapSep,
Token::Str("b"), Token::Str("b"),
Token::I32(2), Token::I32(2),
Token::MapSep(false), Token::MapSep,
Token::Str("c"), Token::Str("c"),
Token::I32(3), Token::I32(3),
Token::MapEnd, Token::MapEnd,
@@ -660,13 +815,13 @@ declare_tests! {
Token::EnumStart("Enum"), Token::EnumStart("Enum"),
Token::Str("Seq"), Token::Str("Seq"),
Token::SeqStart(3), Token::SeqStart(3),
Token::SeqSep(true), Token::SeqSep,
Token::I32(1), Token::I32(1),
Token::SeqSep(false), Token::SeqSep,
Token::I32(2), Token::I32(2),
Token::SeqSep(false), Token::SeqSep,
Token::I32(3), Token::I32(3),
Token::SeqEnd, Token::SeqEnd,
Token::EnumEnd, Token::EnumEnd,
@@ -677,15 +832,15 @@ declare_tests! {
Token::EnumStart("Enum"), Token::EnumStart("Enum"),
Token::Str("Map"), Token::Str("Map"),
Token::MapStart(3), Token::MapStart(3),
Token::MapSep(true), Token::MapSep,
Token::Str("a"), Token::Str("a"),
Token::I32(1), Token::I32(1),
Token::MapSep(false), Token::MapSep,
Token::Str("b"), Token::Str("b"),
Token::I32(2), Token::I32(2),
Token::MapSep(false), Token::MapSep,
Token::Str("c"), Token::Str("c"),
Token::I32(3), Token::I32(3),
Token::MapEnd, Token::MapEnd,