diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 3999f3e3..c955498b 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -16,6 +16,9 @@ use de::MapAccess; use de::from_primitive::FromPrimitive; +#[cfg(any(feature = "std", feature = "collections"))] +use private::de::size_hint; + //////////////////////////////////////////////////////////////////////////////// struct UnitVisitor; @@ -344,7 +347,7 @@ impl<'de> Visitor<'de> for CStringVisitor { where A: SeqAccess<'de>, { - let len = cmp::min(seq.size_hint().0, 4096); + let len = size_hint::cautious(seq.size_hint()); let mut values = Vec::with_capacity(len); while let Some(value) = try!(seq.next_element()) { @@ -557,16 +560,16 @@ macro_rules! seq_impl { seq_impl!( BinaryHeap, BinaryHeapVisitor, - visitor, + seq, BinaryHeap::new(), - BinaryHeap::with_capacity(cmp::min(visitor.size_hint().0, 4096)), + BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::push); #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( BTreeSet, BTreeSetVisitor, - visitor, + seq, BTreeSet::new(), BTreeSet::new(), BTreeSet::insert); @@ -575,7 +578,7 @@ seq_impl!( seq_impl!( LinkedList, LinkedListVisitor, - visitor, + seq, LinkedList::new(), LinkedList::new(), LinkedList::push_back); @@ -585,27 +588,27 @@ seq_impl!( HashSet, HashSetVisitor, - visitor, + seq, HashSet::with_hasher(S::default()), - HashSet::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default()), + HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::insert); #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( Vec, VecVisitor, - visitor, + seq, Vec::new(), - Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)), + Vec::with_capacity(size_hint::cautious(seq.size_hint())), Vec::push); #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( VecDeque, VecDequeVisitor, - visitor, + seq, VecDeque::new(), - VecDeque::with_capacity(cmp::min(visitor.size_hint().0, 4096)), + VecDeque::with_capacity(size_hint::cautious(seq.size_hint())), VecDeque::push_back); //////////////////////////////////////////////////////////////////////////////// @@ -865,7 +868,7 @@ macro_rules! map_impl { map_impl!( BTreeMap, BTreeMapVisitor, - visitor, + map, BTreeMap::new(), BTreeMap::new()); @@ -874,9 +877,9 @@ map_impl!( HashMap, HashMapVisitor, - visitor, + map, HashMap::with_hasher(S::default()), - HashMap::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default())); + HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default())); //////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index dc67021b..af45dbb3 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1376,10 +1376,10 @@ pub trait SeqAccess<'de> { self.next_element_seed(PhantomData) } - /// Return the lower and upper bound of items remaining in the sequence. + /// Returns the number of elements remaining in the sequence, if known. #[inline] - fn size_hint(&self) -> (usize, Option) { - (0, None) + fn size_hint(&self) -> Option { + None } } @@ -1406,7 +1406,7 @@ where } #[inline] - fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> Option { (**self).size_hint() } } @@ -1504,10 +1504,10 @@ pub trait MapAccess<'de> { self.next_entry_seed(PhantomData, PhantomData) } - /// Return the lower and upper bound of items remaining in the sequence. + /// Returns the number of entries remaining in the map, if known. #[inline] - fn size_hint(&self) -> (usize, Option) { - (0, None) + fn size_hint(&self) -> Option { + None } } @@ -1572,7 +1572,7 @@ where } #[inline] - fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> Option { (**self).size_hint() } } diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index a521c9a6..921a4ac5 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -11,6 +11,7 @@ use lib::*; use de::{self, IntoDeserializer, Expected, SeqAccess}; +use private::de::size_hint; use self::private::{First, Second}; //////////////////////////////////////////////////////////////////////////////// @@ -545,8 +546,8 @@ where } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } @@ -799,8 +800,8 @@ where } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } @@ -827,8 +828,8 @@ where } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } @@ -910,7 +911,7 @@ where if pair_visitor.1.is_none() { Ok(pair) } else { - let remaining = pair_visitor.size_hint().0; + let remaining = pair_visitor.size_hint().unwrap(); // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length(2, &ExpectedInSeq(2 - remaining))) @@ -954,15 +955,14 @@ where } } - fn size_hint(&self) -> (usize, Option) { - let len = if self.0.is_some() { - 2 + fn size_hint(&self) -> Option { + if self.0.is_some() { + Some(2) } else if self.1.is_some() { - 1 + Some(1) } else { - 0 - }; - (len, Some(len)) + Some(0) + } } } diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 7ad86def..957052a3 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -187,6 +187,29 @@ where deserializer.deserialize_str(CowBytesVisitor) } +pub mod size_hint { + use lib::*; + + pub fn from_bounds(iter: &I) -> Option + where I: Iterator + { + helper(iter.size_hint()) + } + + pub fn cautious(hint: Option) -> usize { + cmp::min(hint.unwrap_or(0), 4096) + } + + fn helper(bounds: (usize, Option)) -> Option { + match bounds { + (lower, Some(upper)) if lower == upper => { + Some(upper) + } + _ => None, + } + } +} + #[cfg(any(feature = "std", feature = "collections"))] mod content { // This module is private and nothing here should be used outside of @@ -203,6 +226,7 @@ mod content { use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, MapAccess, EnumAccess, Unexpected}; + use super::size_hint; /// Used from generated code to buffer the contents of the Deserializer when /// deserializing untagged enums and internally tagged enums. @@ -428,7 +452,7 @@ mod content { where V: SeqAccess<'de>, { - let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)); + let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); while let Some(e) = try!(visitor.next_element()) { vec.push(e); } @@ -439,7 +463,7 @@ mod content { where V: MapAccess<'de>, { - let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)); + let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); while let Some(kv) = try!(visitor.next_entry()) { vec.push(kv); } @@ -764,7 +788,7 @@ mod content { V: MapAccess<'de>, { let mut tag = None; - let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)); + let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); while let Some(k) = try!(visitor.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { match k { @@ -1153,8 +1177,8 @@ mod content { } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } @@ -1209,8 +1233,8 @@ mod content { } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } @@ -1546,8 +1570,8 @@ mod content { } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } @@ -1603,8 +1627,8 @@ mod content { } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs index cef4bcae..c826ee86 100644 --- a/serde_test/src/de.rs +++ b/serde_test/src/de.rs @@ -404,9 +404,8 @@ impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> { seed.deserialize(&mut *self.de).map(Some) } - fn size_hint(&self) -> (usize, Option) { - let len = self.len.unwrap_or(0); - (len, self.len) + fn size_hint(&self) -> Option { + self.len } } @@ -439,9 +438,8 @@ impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> { seed.deserialize(&mut *self.de) } - fn size_hint(&self) -> (usize, Option) { - let len = self.len.unwrap_or(0); - (len, self.len) + fn size_hint(&self) -> Option { + self.len } }