// Copyright (c) 2016 multimap developers // // Licensed under the Apache License, Version 2.0 // or the MIT // license , at your // option. All files in the project carrying such notice may not be copied, // modified, or distributed except according to those terms. //! Serde trait implementations for MultiMap extern crate serde; use std::fmt; use std::hash::{BuildHasher, Hash}; use std::marker::PhantomData; use self::serde::de::{MapAccess, Visitor}; use self::serde::{Deserialize, Deserializer, Serialize, Serializer}; use MultiMap; impl Serialize for MultiMap where K: Serialize + Eq + Hash, V: Serialize, BS: BuildHasher, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.inner.serialize(serializer) } } impl MultiMapVisitor where K: Hash + Eq, { fn new() -> Self { MultiMapVisitor { marker: PhantomData, } } } struct MultiMapVisitor { marker: PhantomData>, } impl<'a, K, V, S> Visitor<'a> for MultiMapVisitor where K: Deserialize<'a> + Eq + Hash, V: Deserialize<'a>, S: BuildHasher + Default, { type Value = MultiMap; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("expected a map") } fn visit_map(self, mut visitor: M) -> Result where M: MapAccess<'a>, { let mut values = MultiMap::with_capacity_and_hasher(visitor.size_hint().unwrap_or(0), S::default()); while let Some((key, value)) = visitor.next_entry()? { values.inner.insert(key, value); } Ok(values) } } impl<'a, K, V, S> Deserialize<'a> for MultiMap where K: Deserialize<'a> + Eq + Hash, V: Deserialize<'a>, S: BuildHasher + Default, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'a>, { deserializer.deserialize_map(MultiMapVisitor::::new()) } } #[cfg(test)] mod tests { extern crate serde_test; use self::serde_test::{assert_tokens, Token}; use super::*; #[test] fn test_empty() { let map = MultiMap::::new(); assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); } #[test] fn test_single() { let mut map = MultiMap::::new(); map.insert('x', 1); assert_tokens( &map, &[ Token::Map { len: Some(1) }, Token::Char('x'), Token::Seq { len: Some(1) }, Token::U8(1), Token::SeqEnd, Token::MapEnd, ], ); } #[test] fn test_multiple() { let mut map = MultiMap::::new(); map.insert('x', 1); map.insert('x', 3); map.insert('x', 1); map.insert('x', 5); assert_tokens( &map, &[ Token::Map { len: Some(1) }, Token::Char('x'), Token::Seq { len: Some(4) }, Token::U8(1), Token::U8(3), Token::U8(1), Token::U8(5), Token::SeqEnd, Token::MapEnd, ], ); } }