Skip to content

Commit 626bb5a

Browse files
committed
add a RandomAccessIterator trait
1 parent 3ee4238 commit 626bb5a

File tree

2 files changed

+117
-2
lines changed

2 files changed

+117
-2
lines changed

src/libstd/iterator.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ pub trait DoubleEndedIterator<A>: Iterator<A> {
5353
fn next_back(&mut self) -> Option<A>;
5454
}
5555

56+
/// An object implementing random access indexing by `uint`
57+
pub trait RandomAccessIterator<A> {
58+
/// Return the number of indexable elements. At most `std::uint::max_value`
59+
/// elements are indexable, even if the iterator represents a longer range.
60+
fn indexable(&self) -> uint;
61+
62+
/// Return an element at an index
63+
fn idx(&self, index: uint) -> Option<A>;
64+
}
65+
5666
/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
5767
///
5868
/// In the future these will be default methods instead of a utility trait.
@@ -836,6 +846,30 @@ for ChainIterator<A, T, U> {
836846
}
837847
}
838848

849+
impl<A, T: RandomAccessIterator<A>, U: RandomAccessIterator<A>> RandomAccessIterator<A>
850+
for ChainIterator<A, T, U> {
851+
#[inline]
852+
fn indexable(&self) -> uint {
853+
let (a, b) = (self.a.indexable(), self.b.indexable());
854+
let total = a + b;
855+
if total < a || total < b {
856+
uint::max_value
857+
} else {
858+
total
859+
}
860+
}
861+
862+
#[inline]
863+
fn idx(&self, index: uint) -> Option<A> {
864+
let len = self.a.indexable();
865+
if index < len {
866+
self.a.idx(index)
867+
} else {
868+
self.b.idx(index - len)
869+
}
870+
}
871+
}
872+
839873
/// An iterator which iterates two other iterators simultaneously
840874
// FIXME #6967: Dummy A & B parameters to get around type inference bug
841875
#[deriving(Clone)]
@@ -1718,4 +1752,23 @@ mod tests {
17181752
assert_eq!(it.next_back().unwrap(), &7)
17191753
assert_eq!(it.next_back(), None)
17201754
}
1755+
1756+
#[test]
1757+
fn test_random_access_chain() {
1758+
let xs = [1, 2, 3, 4, 5];
1759+
let ys = ~[7, 9, 11];
1760+
let mut it = xs.iter().chain_(ys.iter());
1761+
assert_eq!(it.idx(0).unwrap(), &1);
1762+
assert_eq!(it.idx(5).unwrap(), &7);
1763+
assert_eq!(it.idx(7).unwrap(), &11);
1764+
assert!(it.idx(8).is_none());
1765+
1766+
it.next();
1767+
it.next();
1768+
it.next_back();
1769+
1770+
assert_eq!(it.idx(0).unwrap(), &3);
1771+
assert_eq!(it.idx(4).unwrap(), &9);
1772+
assert!(it.idx(6).is_none());
1773+
}
17211774
}

src/libstd/vec.rs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,8 +2116,7 @@ macro_rules! iterator {
21162116

21172117
#[inline]
21182118
fn size_hint(&self) -> (uint, Option<uint>) {
2119-
let diff = (self.end as uint) - (self.ptr as uint);
2120-
let exact = diff / sys::nonzero_size_of::<$elem>();
2119+
let exact = self.indexable();
21212120
(exact, Some(exact))
21222121
}
21232122
}
@@ -2145,6 +2144,28 @@ macro_rules! double_ended_iterator {
21452144
}
21462145
}
21472146

2147+
macro_rules! random_access_iterator {
2148+
(impl $name:ident -> $elem:ty) => {
2149+
impl<'self, T> RandomAccessIterator<$elem> for $name<'self, T> {
2150+
#[inline]
2151+
fn indexable(&self) -> uint {
2152+
let diff = (self.end as uint) - (self.ptr as uint);
2153+
diff / sys::nonzero_size_of::<T>()
2154+
}
2155+
2156+
fn idx(&self, index: uint) -> Option<$elem> {
2157+
unsafe {
2158+
if index < self.indexable() {
2159+
cast::transmute(self.ptr.offset(index))
2160+
} else {
2161+
None
2162+
}
2163+
}
2164+
}
2165+
}
2166+
}
2167+
}
2168+
21482169
//iterator!{struct VecIterator -> *T, &'self T}
21492170
/// An iterator for iterating over a vector.
21502171
pub struct VecIterator<'self, T> {
@@ -2154,6 +2175,7 @@ pub struct VecIterator<'self, T> {
21542175
}
21552176
iterator!{impl VecIterator -> &'self T}
21562177
double_ended_iterator!{impl VecIterator -> &'self T}
2178+
random_access_iterator!{impl VecIterator -> &'self T}
21572179
pub type VecRevIterator<'self, T> = InvertIterator<&'self T, VecIterator<'self, T>>;
21582180

21592181
impl<'self, T> Clone for VecIterator<'self, T> {
@@ -2169,6 +2191,7 @@ pub struct VecMutIterator<'self, T> {
21692191
}
21702192
iterator!{impl VecMutIterator -> &'self mut T}
21712193
double_ended_iterator!{impl VecMutIterator -> &'self mut T}
2194+
random_access_iterator!{impl VecMutIterator -> &'self mut T}
21722195
pub type VecMutRevIterator<'self, T> = InvertIterator<&'self mut T, VecMutIterator<'self, T>>;
21732196

21742197
/// An iterator that moves out of a vector.
@@ -3108,6 +3131,45 @@ mod tests {
31083131
assert!(it.next().is_none());
31093132
}
31103133

3134+
#[test]
3135+
fn test_random_access_iterator() {
3136+
use iterator::*;
3137+
let xs = [1, 2, 5, 10, 11];
3138+
let mut it = xs.iter();
3139+
3140+
assert_eq!(it.indexable(), 5);
3141+
assert_eq!(it.idx(0).unwrap(), &1);
3142+
assert_eq!(it.idx(2).unwrap(), &5);
3143+
assert_eq!(it.idx(4).unwrap(), &11);
3144+
assert!(it.idx(5).is_none());
3145+
3146+
assert_eq!(it.next().unwrap(), &1);
3147+
assert_eq!(it.indexable(), 4);
3148+
assert_eq!(it.idx(0).unwrap(), &2);
3149+
assert_eq!(it.idx(3).unwrap(), &11);
3150+
assert!(it.idx(4).is_none());
3151+
3152+
assert_eq!(it.next().unwrap(), &2);
3153+
assert_eq!(it.indexable(), 3);
3154+
assert_eq!(it.idx(1).unwrap(), &10);
3155+
assert!(it.idx(3).is_none());
3156+
3157+
assert_eq!(it.next().unwrap(), &5);
3158+
assert_eq!(it.indexable(), 2);
3159+
assert_eq!(it.idx(1).unwrap(), &11);
3160+
3161+
assert_eq!(it.next().unwrap(), &10);
3162+
assert_eq!(it.indexable(), 1);
3163+
assert_eq!(it.idx(0).unwrap(), &11);
3164+
assert!(it.idx(1).is_none());
3165+
3166+
assert_eq!(it.next().unwrap(), &11);
3167+
assert_eq!(it.indexable(), 0);
3168+
assert!(it.idx(0).is_none());
3169+
3170+
assert!(it.next().is_none());
3171+
}
3172+
31113173
#[test]
31123174
fn test_iter_size_hints() {
31133175
use iterator::*;

0 commit comments

Comments
 (0)