diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index a4e0c29f..bdd547c7 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -381,29 +381,30 @@ impl Deserialize for PhantomData where T: Deserialize { macro_rules! seq_impl { ( $ty:ty, - < $($constraints:ident),* >, - $visitor_name:ident, + $visitor_ty:ident < $($typaram:ident : $bound1:ident $(+ $bound2:ident)*),* >, $visitor:ident, $ctor:expr, $with_capacity:expr, $insert:expr ) => { /// A visitor that produces a sequence. - pub struct $visitor_name { - marker: PhantomData, + pub struct $visitor_ty<$($typaram),*> { + marker: PhantomData<$ty>, } - impl $visitor_name { + impl<$($typaram),*> $visitor_ty<$($typaram),*> + where $($typaram: $bound1 $(+ $bound2)*),* + { /// Construct a new sequence visitor. pub fn new() -> Self { - $visitor_name { + $visitor_ty { marker: PhantomData, } } } - impl Visitor for $visitor_name - where T: $($constraints +)*, + impl<$($typaram),*> Visitor for $visitor_ty<$($typaram),*> + where $($typaram: $bound1 $(+ $bound2)*),* { type Value = $ty; @@ -430,13 +431,13 @@ macro_rules! seq_impl { } } - impl Deserialize for $ty - where T: $($constraints +)*, + impl<$($typaram),*> Deserialize for $ty + where $($typaram: $bound1 $(+ $bound2)*),* { fn deserialize(deserializer: &mut D) -> Result<$ty, D::Error> where D: Deserializer, { - deserializer.deserialize_seq($visitor_name::new()) + deserializer.deserialize_seq($visitor_ty::new()) } } } @@ -445,8 +446,7 @@ macro_rules! seq_impl { #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( BinaryHeap, - , - BinaryHeapVisitor, + BinaryHeapVisitor, visitor, BinaryHeap::new(), BinaryHeap::with_capacity(visitor.size_hint().0), @@ -455,8 +455,7 @@ seq_impl!( #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( BTreeSet, - , - BTreeSetVisitor, + BTreeSetVisitor, visitor, BTreeSet::new(), BTreeSet::new(), @@ -465,8 +464,7 @@ seq_impl!( #[cfg(all(feature = "nightly", feature = "collections"))] seq_impl!( EnumSet, - , - EnumSetVisitor, + EnumSetVisitor, visitor, EnumSet::new(), EnumSet::new(), @@ -475,8 +473,7 @@ seq_impl!( #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( LinkedList, - , - LinkedListVisitor, + LinkedListVisitor, visitor, LinkedList::new(), LinkedList::new(), @@ -484,19 +481,18 @@ seq_impl!( #[cfg(feature = "std")] seq_impl!( - HashSet, - , - HashSetVisitor, + HashSet, + HashSetVisitor, visitor, - HashSet::new(), - HashSet::with_capacity(visitor.size_hint().0), + HashSet::with_hasher(S::default()), + HashSet::with_capacity_and_hasher(visitor.size_hint().0, S::default()), HashSet::insert); #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( Vec, - , - VecVisitor, + VecVisitor, visitor, Vec::new(), Vec::with_capacity(visitor.size_hint().0), @@ -505,8 +501,7 @@ seq_impl!( #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( VecDeque, - , - VecDequeVisitor, + VecDequeVisitor, visitor, VecDeque::new(), VecDeque::with_capacity(visitor.size_hint().0), diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index a05ae862..dbc58cc3 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -330,8 +330,9 @@ impl Serialize for EnumSet } #[cfg(feature = "std")] -impl Serialize for HashSet +impl Serialize for HashSet where T: Serialize + Eq + Hash, + H: BuildHasher, { #[inline] fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> diff --git a/serde_tests/tests/macros.rs b/serde_tests/tests/macros.rs index c0b38b3d..2446150b 100644 --- a/serde_tests/tests/macros.rs +++ b/serde_tests/tests/macros.rs @@ -62,6 +62,14 @@ macro_rules! hashset { $(set.insert($value);)+ set } + }; + ($hasher:ident @ $($value:expr),+) => { + { + use std::hash::BuildHasherDefault; + let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default()); + $(set.insert($value);)+ + set + } } } diff --git a/serde_tests/tests/test_de.rs b/serde_tests/tests/test_de.rs index 8081b9ea..2b9d0035 100644 --- a/serde_tests/tests/test_de.rs +++ b/serde_tests/tests/test_de.rs @@ -287,6 +287,18 @@ declare_tests! { Token::TupleStructStart("Anything", Some(0)), Token::SeqEnd, ], + hashset![FnvHasher @ 1, 2, 3] => vec![ + Token::SeqStart(Some(3)), + Token::SeqSep, + Token::I32(1), + + Token::SeqSep, + Token::I32(2), + + Token::SeqSep, + Token::I32(3), + Token::SeqEnd, + ], } test_vec { Vec::::new() => vec![ diff --git a/serde_tests/tests/test_ser.rs b/serde_tests/tests/test_ser.rs index 2fa8cb9d..5b3f215b 100644 --- a/serde_tests/tests/test_ser.rs +++ b/serde_tests/tests/test_ser.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::net; use std::path::{Path, PathBuf}; use std::str; @@ -147,6 +147,24 @@ declare_ser_tests! { Token::SeqEnd, ], } + test_hashset { + HashSet::::new() => &[ + Token::SeqStart(Some(0)), + Token::SeqEnd, + ], + hashset![1] => &[ + Token::SeqStart(Some(1)), + Token::SeqSep, + Token::I32(1), + Token::SeqEnd, + ], + hashset![FnvHasher @ 1] => &[ + Token::SeqStart(Some(1)), + Token::SeqSep, + Token::I32(1), + Token::SeqEnd, + ], + } test_tuple { (1,) => &[ Token::TupleStart(1),