From 4b2cc22031d56a4846bc0ad4e65e19892db734c4 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Fri, 30 Aug 2013 19:59:49 +0200 Subject: std::iterator: Introduce trait ExactSizeHint The trait `ExactSizeHint` is introduced to solve a few small niggles: * We can't reverse (`.invert()`) an enumeration iterator * for a vector, we have `v.iter().position(f)` but `v.rposition(f)`. * We can't reverse `Zip` even if both iterators are from vectors `ExactSizeHint` is an empty trait that is intended to indicate that an iterator, for example `VecIterator`, knows its exact finite size and reports it correctly using `.size_hint()`. Only adaptors that preserve this at all times, can expose this trait further. (Where here we say finite for fitting in uint). --- src/libstd/iterator.rs | 35 +++++++++++++++++++++++++++++++++++ src/libstd/vec.rs | 3 +++ 2 files changed, 38 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 4af7b3e2425..19596421cb2 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -616,6 +616,26 @@ pub trait RandomAccessIterator: Iterator { fn idx(&self, index: uint) -> Option; } +/// An iterator that knows its exact length +/// +/// This trait is a helper for iterators like the vector iterator, so that +/// it can support double-ended enumeration. +/// +/// `Iterator::size_hint` *must* return the exact size of the iterator. +/// Note that the size must fit in `uint`. +pub trait ExactSizeHint {} + +// All adaptors that preserve the size of the wrapped iterator are fine +// Adaptors that may overflow in `size_hint` are not, i.e. `Chain`. +impl ExactSizeHint for Enumerate {} +impl<'self, A, T: ExactSizeHint> ExactSizeHint for Inspect<'self, A, T> {} +impl ExactSizeHint for Invert {} +impl<'self, A, B, T: ExactSizeHint> ExactSizeHint for Map<'self, A, B, T> {} +impl ExactSizeHint for Peekable {} +impl ExactSizeHint for Skip {} +impl ExactSizeHint for Take {} +impl ExactSizeHint for Zip {} + /// An double-ended iterator with the direction inverted #[deriving(Clone)] pub struct Invert { @@ -1094,6 +1114,21 @@ impl> Iterator<(uint, A)> for Enumerate { } } +impl + ExactSizeHint> DoubleEndedIterator<(uint, A)> +for Enumerate { + #[inline] + fn next_back(&mut self) -> Option<(uint, A)> { + match self.iter.next_back() { + Some(a) => { + let (len, _) = self.iter.size_hint(); + let ret = Some((self.count + len, a)); + ret + } + _ => None + } + } +} + impl> RandomAccessIterator<(uint, A)> for Enumerate { #[inline] fn indexable(&self) -> uint { diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 12aebe20161..6ddb2a72286 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2319,6 +2319,9 @@ iterator!{impl VecIterator -> &'self T} double_ended_iterator!{impl VecIterator -> &'self T} pub type RevIterator<'self, T> = Invert>; +impl<'self, T> ExactSizeHint for VecIterator<'self, T> {} +impl<'self, T> ExactSizeHint for VecMutIterator<'self, T> {} + impl<'self, T> Clone for VecIterator<'self, T> { fn clone(&self) -> VecIterator<'self, T> { *self } } -- cgit 1.4.1-3-g733a5