From 4a7a188dbad077e4d0e653ce5ddb2aca3cdde3df Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Sat, 31 Mar 2018 23:51:07 -0400 Subject: [PATCH 1/2] Add size_hints for btree iterators Continues work on adding size_hint implementations for iterators: issue #49205 --- src/liballoc/btree/map.rs | 35 +++++++++++++++++++++++++++++++++++ src/liballoc/btree/set.rs | 4 ++++ 2 files changed, 39 insertions(+) diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index c604df7049e0c..cabeaf3a73f30 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -1480,6 +1480,16 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { unsafe { Some(self.next_unchecked()) } } } + + fn size_hint(&self) -> (usize, Option) { + if self.front == self.back { + (0, Some(0)) + } else { + // There doesn't seem to be any way to get the size of the whole tree + // from a NodeRef. + (1, None) + } + } } #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1612,6 +1622,16 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { unsafe { Some(self.next_unchecked()) } } } + + fn size_hint(&self) -> (usize, Option) { + if self.front == self.back { + (0, Some(0)) + } else { + // We can get the root node by using into_root_mut; but there doesn't + // seem to be any way to get the size of the tree from the root node. + (1, None) + } + } } impl<'a, K, V> RangeMut<'a, K, V> { @@ -2549,4 +2569,19 @@ impl> Iterator for MergeIter { } } } + + // Currently unused. However, BTreeMap::from_sorted_iter may some day be + // rewritten to pre-allocate the correct amount of nodes, in which case + // having this will be helpful. + fn size_hint(&self) -> (usize, Option) { + let (left_lower, left_upper) = self.left.size_hint(); + let (right_lower, right_upper) = self.right.size_hint(); + let lower = left_lower + right_lower; + let upper = match (left_upper, right_upper) { + (Some(left), Some(right)) => left.checked_add(right), + (left, None) => left, + (None, right) => right + }; + (lower, upper) + } } diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index 2aad476d3153a..ff22b82a5c251 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -987,6 +987,10 @@ impl<'a, T> Iterator for Range<'a, T> { fn next(&mut self) -> Option<&'a T> { self.iter.next().map(|(k, _)| k) } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } } #[stable(feature = "btree_range", since = "1.17.0")] From 2e92759107d57910166fe1dd192b90f82482fe02 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Mon, 16 Apr 2018 17:50:53 -0400 Subject: [PATCH 2/2] Fix bug, add FIXME --- src/liballoc/btree/map.rs | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index cabeaf3a73f30..18694c06e7227 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -1481,15 +1481,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { } } - fn size_hint(&self) -> (usize, Option) { - if self.front == self.back { - (0, Some(0)) - } else { - // There doesn't seem to be any way to get the size of the whole tree - // from a NodeRef. - (1, None) - } - } + // FIXME(#49205): Add size_hint. } #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1623,15 +1615,7 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { } } - fn size_hint(&self) -> (usize, Option) { - if self.front == self.back { - (0, Some(0)) - } else { - // We can get the root node by using into_root_mut; but there doesn't - // seem to be any way to get the size of the tree from the root node. - (1, None) - } - } + // FIXME(#49205): Add size_hint. } impl<'a, K, V> RangeMut<'a, K, V> { @@ -2576,11 +2560,11 @@ impl> Iterator for MergeIter { fn size_hint(&self) -> (usize, Option) { let (left_lower, left_upper) = self.left.size_hint(); let (right_lower, right_upper) = self.right.size_hint(); - let lower = left_lower + right_lower; + let lower = left_lower.saturating_add(right_lower); let upper = match (left_upper, right_upper) { (Some(left), Some(right)) => left.checked_add(right), - (left, None) => left, - (None, right) => right + (_, None) => None, + (None, _) => None }; (lower, upper) }