auto merge of #8265 : blake2-ppc/rust/std-iter, r=thestinger
Fix #8228 by replacing .iter() and .iter_err() in Result by external iterators. Implement random access for `iterator::Invert` and `vec::ChunkIter` (and bidirectionality). Implement Repeat iterator.
This commit is contained in:
commit
f8cf234b34
@ -13,7 +13,7 @@
|
||||
|
||||
use std::cmp;
|
||||
use std::iterator::RandomAccessIterator;
|
||||
use std::iterator::{Invert, Enumerate};
|
||||
use std::iterator::{Invert, Enumerate, Repeat, Map, Zip};
|
||||
use std::num;
|
||||
use std::ops;
|
||||
use std::uint;
|
||||
@ -206,14 +206,13 @@ impl BigBitv {
|
||||
#[inline]
|
||||
pub fn equals(&self, b: &BigBitv, nbits: uint) -> bool {
|
||||
let len = b.storage.len();
|
||||
do uint::iterate(0, len) |i| {
|
||||
for i in range(0, len) {
|
||||
let mask = big_mask(nbits, i);
|
||||
if mask & self.storage[i] != mask & b.storage[i] {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@ -864,13 +863,12 @@ impl BitvSet {
|
||||
/// w1, w2) where the bit location is the number of bits offset so far,
|
||||
/// and w1/w2 are the words coming from the two vectors self, other.
|
||||
fn common_iter<'a>(&'a self, other: &'a BitvSet)
|
||||
-> MapE<(uint,&uint),(uint,uint,uint), &'a ~[uint],Enumerate<vec::VecIterator<'a,uint>>> {
|
||||
let min = num::min(self.bitv.storage.len(),
|
||||
other.bitv.storage.len());
|
||||
MapE{iter: self.bitv.storage.slice(0, min).iter().enumerate(),
|
||||
env: &other.bitv.storage,
|
||||
f: |(i, &w): (uint, &uint), o_store| (i * uint::bits, w, o_store[i])
|
||||
}
|
||||
-> Map<'static, ((uint, &'a uint), &'a ~[uint]), (uint, uint, uint),
|
||||
Zip<Enumerate<vec::VecIterator<'a, uint>>, Repeat<&'a ~[uint]>>> {
|
||||
let min = num::min(self.bitv.storage.len(), other.bitv.storage.len());
|
||||
self.bitv.storage.slice(0, min).iter().enumerate()
|
||||
.zip(Repeat::new(&other.bitv.storage))
|
||||
.transform(|((i, &w), o_store)| (i * uint::bits, w, o_store[i]))
|
||||
}
|
||||
|
||||
/// Visits each word in self or other that extends beyond the other. This
|
||||
@ -881,47 +879,23 @@ impl BitvSet {
|
||||
/// is true if the word comes from 'self', and false if it comes from
|
||||
/// 'other'.
|
||||
fn outlier_iter<'a>(&'a self, other: &'a BitvSet)
|
||||
-> MapE<(uint, &uint),(bool, uint, uint), uint, Enumerate<vec::VecIterator<'a, uint>>> {
|
||||
let len1 = self.bitv.storage.len();
|
||||
let len2 = other.bitv.storage.len();
|
||||
let min = num::min(len1, len2);
|
||||
-> Map<'static, ((uint, &'a uint), uint), (bool, uint, uint),
|
||||
Zip<Enumerate<vec::VecIterator<'a, uint>>, Repeat<uint>>> {
|
||||
let slen = self.bitv.storage.len();
|
||||
let olen = other.bitv.storage.len();
|
||||
|
||||
if min < len1 {
|
||||
MapE{iter: self.bitv.storage.slice(min, len1).iter().enumerate(),
|
||||
env: min,
|
||||
f: |(i, &w): (uint, &uint), min| (true, (i + min) * uint::bits, w)
|
||||
}
|
||||
if olen < slen {
|
||||
self.bitv.storage.slice_from(olen).iter().enumerate()
|
||||
.zip(Repeat::new(olen))
|
||||
.transform(|((i, &w), min)| (true, (i + min) * uint::bits, w))
|
||||
} else {
|
||||
MapE{iter: other.bitv.storage.slice(min, len2).iter().enumerate(),
|
||||
env: min,
|
||||
f: |(i, &w): (uint, &uint), min| (false, (i + min) * uint::bits, w)
|
||||
}
|
||||
other.bitv.storage.slice_from(slen).iter().enumerate()
|
||||
.zip(Repeat::new(slen))
|
||||
.transform(|((i, &w), min)| (false, (i + min) * uint::bits, w))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Like iterator::Map with explicit env capture
|
||||
struct MapE<A, B, Env, I> {
|
||||
priv env: Env,
|
||||
priv f: &'static fn(A, Env) -> B,
|
||||
priv iter: I,
|
||||
}
|
||||
|
||||
impl<'self, A, B, Env: Clone, I: Iterator<A>> Iterator<B> for MapE<A, B, Env, I> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
match self.iter.next() {
|
||||
Some(elt) => Some((self.f)(elt, self.env.clone())),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BitvSetIterator<'self> {
|
||||
priv set: &'self BitvSet,
|
||||
priv next_idx: uint
|
||||
|
@ -19,7 +19,8 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
|
||||
use clone::Clone;
|
||||
use cmp::{Eq, Equiv};
|
||||
use hash::Hash;
|
||||
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, Chain, range};
|
||||
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, range};
|
||||
use iterator::{FilterMap, Chain, Repeat, Zip};
|
||||
use num;
|
||||
use option::{None, Option, Some};
|
||||
use rand::RngUtil;
|
||||
@ -712,10 +713,12 @@ impl<T:Hash + Eq> HashSet<T> {
|
||||
}
|
||||
|
||||
/// Visit the values representing the difference
|
||||
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>)
|
||||
-> SetAlgebraIter<'a, T> {
|
||||
EnvFilterIterator{iter: self.iter(), env: other,
|
||||
filter: |elt, other| !other.contains(elt) }
|
||||
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>) -> SetAlgebraIter<'a, T> {
|
||||
Repeat::new(other)
|
||||
.zip(self.iter())
|
||||
.filter_map(|(other, elt)| {
|
||||
if !other.contains(elt) { Some(elt) } else { None }
|
||||
})
|
||||
}
|
||||
|
||||
/// Visit the values representing the symmetric difference
|
||||
@ -727,8 +730,11 @@ impl<T:Hash + Eq> HashSet<T> {
|
||||
/// Visit the values representing the intersection
|
||||
pub fn intersection_iter<'a>(&'a self, other: &'a HashSet<T>)
|
||||
-> SetAlgebraIter<'a, T> {
|
||||
EnvFilterIterator{iter: self.iter(), env: other,
|
||||
filter: |elt, other| other.contains(elt) }
|
||||
Repeat::new(other)
|
||||
.zip(self.iter())
|
||||
.filter_map(|(other, elt)| {
|
||||
if other.contains(elt) { Some(elt) } else { None }
|
||||
})
|
||||
}
|
||||
|
||||
/// Visit the values representing the union
|
||||
@ -756,38 +762,12 @@ impl<K: Eq + Hash, T: Iterator<K>> Extendable<K, T> for HashSet<K> {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME #7814: use std::iterator::FilterIterator
|
||||
/// Building block for Set operation iterators
|
||||
pub struct EnvFilterIterator<A, Env, I> {
|
||||
priv env: Env,
|
||||
priv filter: &'static fn(&A, Env) -> bool,
|
||||
priv iter: I,
|
||||
}
|
||||
|
||||
impl<'self, A, Env: Clone, I: Iterator<&'self A>> Iterator<&'self A>
|
||||
for EnvFilterIterator<A, Env, I> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'self A> {
|
||||
loop {
|
||||
match self.iter.next() {
|
||||
Some(elt) => if (self.filter)(elt, self.env.clone()) {
|
||||
return Some(elt)
|
||||
},
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper)
|
||||
}
|
||||
}
|
||||
|
||||
// `Repeat` is used to feed the filter closure an explicit capture
|
||||
// of a reference to the other set
|
||||
/// Set operations iterator
|
||||
pub type SetAlgebraIter<'self, T> =
|
||||
EnvFilterIterator<T, &'self HashSet<T>, HashSetIterator<'self, T>>;
|
||||
FilterMap<'static,(&'self HashSet<T>, &'self T), &'self T,
|
||||
Zip<Repeat<&'self HashSet<T>>,HashSetIterator<'self,T>>>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -82,6 +82,17 @@ pub trait DoubleEndedIteratorUtil {
|
||||
/// In the future these will be default methods instead of a utility trait.
|
||||
impl<A, T: DoubleEndedIterator<A>> DoubleEndedIteratorUtil for T {
|
||||
/// Flip the direction of the iterator
|
||||
///
|
||||
/// The inverted iterator flips the ends on an iterator that can already
|
||||
/// be iterated from the front and from the back.
|
||||
///
|
||||
///
|
||||
/// If the iterator also implements RandomAccessIterator, the inverted
|
||||
/// iterator is also random access, with the indices starting at the back
|
||||
/// of the original iterator.
|
||||
///
|
||||
/// Note: Random access with inverted indices still only applies to the first
|
||||
/// `uint::max_value` elements of the original iterator.
|
||||
#[inline]
|
||||
fn invert(self) -> Invert<T> {
|
||||
Invert{iter: self}
|
||||
@ -106,6 +117,16 @@ impl<A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Invert<T> {
|
||||
fn next_back(&mut self) -> Option<A> { self.iter.next() }
|
||||
}
|
||||
|
||||
impl<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterator<A>
|
||||
for Invert<T> {
|
||||
#[inline]
|
||||
fn indexable(&self) -> uint { self.iter.indexable() }
|
||||
#[inline]
|
||||
fn idx(&self, index: uint) -> Option<A> {
|
||||
self.iter.idx(self.indexable() - index - 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
|
||||
/// implementations of the `Iterator` trait.
|
||||
///
|
||||
@ -1555,6 +1576,39 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that repeats an element endlessly
|
||||
#[deriving(Clone, DeepClone)]
|
||||
pub struct Repeat<A> {
|
||||
priv element: A
|
||||
}
|
||||
|
||||
impl<A: Clone> Repeat<A> {
|
||||
/// Create a new `Repeat` that enlessly repeats the element `elt`.
|
||||
#[inline]
|
||||
pub fn new(elt: A) -> Repeat<A> {
|
||||
Repeat{element: elt}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Clone> Iterator<A> for Repeat<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> { self.idx(0) }
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { (uint::max_value, None) }
|
||||
}
|
||||
|
||||
impl<A: Clone> DoubleEndedIterator<A> for Repeat<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> { self.idx(0) }
|
||||
}
|
||||
|
||||
impl<A: Clone> RandomAccessIterator<A> for Repeat<A> {
|
||||
#[inline]
|
||||
fn indexable(&self) -> uint { uint::max_value }
|
||||
#[inline]
|
||||
fn idx(&self, _: uint) -> Option<A> { Some(self.element.clone()) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -2017,6 +2071,17 @@ mod tests {
|
||||
check_randacc_iter(xs.iter().enumerate(), xs.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_access_invert() {
|
||||
let xs = [1, 2, 3, 4, 5];
|
||||
check_randacc_iter(xs.iter().invert(), xs.len());
|
||||
let mut it = xs.iter().invert();
|
||||
it.next();
|
||||
it.next_back();
|
||||
it.next();
|
||||
check_randacc_iter(it, xs.len() - 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_access_zip() {
|
||||
let xs = [1, 2, 3, 4, 5];
|
||||
|
@ -70,30 +70,6 @@ pub fn div_round(x: uint, y: uint) -> uint {
|
||||
///
|
||||
pub fn div_floor(x: uint, y: uint) -> uint { return x / y; }
|
||||
|
||||
///
|
||||
/// Iterate over the range [`lo`..`hi`), or stop when requested
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * lo - The integer at which to start the loop (included)
|
||||
/// * hi - The integer at which to stop the loop (excluded)
|
||||
/// * it - A block to execute with each consecutive integer of the range.
|
||||
/// Return `true` to continue, `false` to stop.
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `true` If execution proceeded correctly, `false` if it was interrupted,
|
||||
/// that is if `it` returned `false` at any point.
|
||||
///
|
||||
pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
|
||||
let mut i = lo;
|
||||
while i < hi {
|
||||
if (!it(i)) { return false; }
|
||||
i += 1u;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
impl iter::Times for uint {
|
||||
#[inline]
|
||||
///
|
||||
|
@ -116,7 +116,7 @@ impl<T: ToStr> ToStr for Option<T> {
|
||||
impl<T> Option<T> {
|
||||
/// Return an iterator over the possibly contained value
|
||||
#[inline]
|
||||
pub fn iter<'r>(&'r self) -> OptionIterator<'r, T> {
|
||||
pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
|
||||
match *self {
|
||||
Some(ref x) => OptionIterator{opt: Some(x)},
|
||||
None => OptionIterator{opt: None}
|
||||
@ -125,13 +125,19 @@ impl<T> Option<T> {
|
||||
|
||||
/// Return a mutable iterator over the possibly contained value
|
||||
#[inline]
|
||||
pub fn mut_iter<'r>(&'r mut self) -> OptionMutIterator<'r, T> {
|
||||
pub fn mut_iter<'r>(&'r mut self) -> OptionIterator<&'r mut T> {
|
||||
match *self {
|
||||
Some(ref mut x) => OptionMutIterator{opt: Some(x)},
|
||||
None => OptionMutIterator{opt: None}
|
||||
Some(ref mut x) => OptionIterator{opt: Some(x)},
|
||||
None => OptionIterator{opt: None}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a consuming iterator over the possibly contained value
|
||||
#[inline]
|
||||
pub fn consume(self) -> OptionIterator<T> {
|
||||
OptionIterator{opt: self}
|
||||
}
|
||||
|
||||
/// Returns true if the option equals `None`
|
||||
#[inline]
|
||||
pub fn is_none(&self) -> bool {
|
||||
@ -404,34 +410,18 @@ impl<T> Zero for Option<T> {
|
||||
fn is_zero(&self) -> bool { self.is_none() }
|
||||
}
|
||||
|
||||
/// Immutable iterator over an `Option<A>`
|
||||
pub struct OptionIterator<'self, A> {
|
||||
priv opt: Option<&'self A>
|
||||
/// An iterator that yields either one or zero elements
|
||||
pub struct OptionIterator<A> {
|
||||
priv opt: Option<A>
|
||||
}
|
||||
|
||||
impl<'self, A> Iterator<&'self A> for OptionIterator<'self, A> {
|
||||
fn next(&mut self) -> Option<&'self A> {
|
||||
util::replace(&mut self.opt, None)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
match self.opt {
|
||||
Some(_) => (1, Some(1)),
|
||||
None => (0, Some(0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable iterator over an `Option<A>`
|
||||
pub struct OptionMutIterator<'self, A> {
|
||||
priv opt: Option<&'self mut A>
|
||||
}
|
||||
|
||||
impl<'self, A> Iterator<&'self mut A> for OptionMutIterator<'self, A> {
|
||||
fn next(&mut self) -> Option<&'self mut A> {
|
||||
util::replace(&mut self.opt, None)
|
||||
impl<A> Iterator<A> for OptionIterator<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
self.opt.take()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
match self.opt {
|
||||
Some(_) => (1, Some(1)),
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
use cast;
|
||||
use clone::Clone;
|
||||
use iterator::{range, Iterator};
|
||||
use option::{Option, Some, None};
|
||||
use unstable::intrinsics;
|
||||
use util::swap;
|
||||
@ -20,7 +21,6 @@ use util::swap;
|
||||
#[cfg(not(test))] use num::Int;
|
||||
|
||||
#[cfg(not(test))] use cmp::{Eq, Ord};
|
||||
use uint;
|
||||
|
||||
/// Calculate the offset from a pointer
|
||||
#[inline]
|
||||
@ -240,11 +240,10 @@ pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: &fn(*T)) {
|
||||
fail!("ptr::array_each_with_len failure: arr input is null pointer");
|
||||
}
|
||||
//let start_ptr = *arr;
|
||||
uint::iterate(0, len, |e| {
|
||||
for e in range(0, len) {
|
||||
let n = offset(arr, e as int);
|
||||
cb(*n);
|
||||
true
|
||||
});
|
||||
}
|
||||
debug!("array_each_with_len: after iterate");
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ use clone::Clone;
|
||||
use cmp::Eq;
|
||||
use either;
|
||||
use iterator::Iterator;
|
||||
use option::{None, Option, Some};
|
||||
use option::{None, Option, Some, OptionIterator};
|
||||
use vec;
|
||||
use vec::{OwnedVector, ImmutableVector};
|
||||
use container::Container;
|
||||
@ -86,15 +86,15 @@ impl<T, E: ToStr> Result<T, E> {
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// do read_file(file).iter |buf| {
|
||||
/// for buf in read_file(file) {
|
||||
/// print_buf(buf)
|
||||
/// }
|
||||
#[inline]
|
||||
pub fn iter(&self, f: &fn(&T)) {
|
||||
pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
|
||||
match *self {
|
||||
Ok(ref t) => f(t),
|
||||
Err(_) => (),
|
||||
}
|
||||
Ok(ref t) => Some(t),
|
||||
Err(*) => None,
|
||||
}.consume()
|
||||
}
|
||||
|
||||
/// Call a method based on a previous result
|
||||
@ -104,11 +104,11 @@ impl<T, E: ToStr> Result<T, E> {
|
||||
/// immediately returned. This function can be used to pass through a
|
||||
/// successful result while handling an error.
|
||||
#[inline]
|
||||
pub fn iter_err(&self, f: &fn(&E)) {
|
||||
pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> {
|
||||
match *self {
|
||||
Ok(_) => (),
|
||||
Err(ref e) => f(e),
|
||||
}
|
||||
Ok(*) => None,
|
||||
Err(ref t) => Some(t),
|
||||
}.consume()
|
||||
}
|
||||
|
||||
/// Unwraps a result, yielding the content of an `Ok`.
|
||||
@ -214,7 +214,7 @@ impl<T, E: Clone + ToStr> Result<T, E> {
|
||||
/// parse_bytes(buf)
|
||||
/// };
|
||||
#[inline]
|
||||
pub fn map<U: Clone>(&self, op: &fn(&T) -> U) -> Result<U,E> {
|
||||
pub fn map<U>(&self, op: &fn(&T) -> U) -> Result<U,E> {
|
||||
match *self {
|
||||
Ok(ref t) => Ok(op(t)),
|
||||
Err(ref e) => Err(e.clone())
|
||||
@ -335,21 +335,25 @@ mod tests {
|
||||
#[test]
|
||||
pub fn test_impl_iter() {
|
||||
let mut valid = false;
|
||||
Ok::<~str, ~str>(~"a").iter(|_x| valid = true);
|
||||
let okval = Ok::<~str, ~str>(~"a");
|
||||
do okval.iter().next().map |_| { valid = true; };
|
||||
assert!(valid);
|
||||
|
||||
Err::<~str, ~str>(~"b").iter(|_x| valid = false);
|
||||
let errval = Err::<~str, ~str>(~"b");
|
||||
do errval.iter().next().map |_| { valid = false; };
|
||||
assert!(valid);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_impl_iter_err() {
|
||||
let mut valid = true;
|
||||
Ok::<~str, ~str>(~"a").iter_err(|_x| valid = false);
|
||||
let okval = Ok::<~str, ~str>(~"a");
|
||||
do okval.iter_err().next().map |_| { valid = false };
|
||||
assert!(valid);
|
||||
|
||||
valid = false;
|
||||
Err::<~str, ~str>(~"b").iter_err(|_x| valid = true);
|
||||
let errval = Err::<~str, ~str>(~"b");
|
||||
do errval.iter_err().next().map |_| { valid = true };
|
||||
assert!(valid);
|
||||
}
|
||||
|
||||
|
@ -479,6 +479,7 @@ pub fn each_permutation<T:Clone>(values: &[T], fun: &fn(perm : &[T]) -> bool) ->
|
||||
|
||||
/// An iterator over the (overlapping) slices of length `size` within
|
||||
/// a vector.
|
||||
#[deriving(Clone)]
|
||||
pub struct WindowIter<'self, T> {
|
||||
priv v: &'self [T],
|
||||
priv size: uint
|
||||
@ -498,6 +499,10 @@ impl<'self, T> Iterator<&'self [T]> for WindowIter<'self, T> {
|
||||
|
||||
/// An iterator over a vector in (non-overlapping) chunks (`size`
|
||||
/// elements at a time).
|
||||
///
|
||||
/// When the vector len is not evenly divided by the chunk size,
|
||||
/// the last slice of the iteration will be the remainer.
|
||||
#[deriving(Clone)]
|
||||
pub struct ChunkIter<'self, T> {
|
||||
priv v: &'self [T],
|
||||
priv size: uint
|
||||
@ -505,16 +510,49 @@ pub struct ChunkIter<'self, T> {
|
||||
|
||||
impl<'self, T> Iterator<&'self [T]> for ChunkIter<'self, T> {
|
||||
fn next(&mut self) -> Option<&'self [T]> {
|
||||
if self.size == 0 {
|
||||
if self.v.len() == 0 {
|
||||
None
|
||||
} else if self.size >= self.v.len() {
|
||||
// finished
|
||||
self.size = 0;
|
||||
Some(self.v)
|
||||
} else {
|
||||
let ret = Some(self.v.slice(0, self.size));
|
||||
self.v = self.v.slice(self.size, self.v.len());
|
||||
ret
|
||||
let chunksz = cmp::min(self.v.len(), self.size);
|
||||
let (fst, snd) = (self.v.slice_to(chunksz),
|
||||
self.v.slice_from(chunksz));
|
||||
self.v = snd;
|
||||
Some(fst)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, T> DoubleEndedIterator<&'self [T]> for ChunkIter<'self, T> {
|
||||
fn next_back(&mut self) -> Option<&'self [T]> {
|
||||
if self.v.len() == 0 {
|
||||
None
|
||||
} else {
|
||||
let remainder = self.v.len() % self.size;
|
||||
let chunksz = if remainder != 0 { remainder } else { self.size };
|
||||
let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz),
|
||||
self.v.slice_from(self.v.len() - chunksz));
|
||||
self.v = fst;
|
||||
Some(snd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, T> RandomAccessIterator<&'self [T]> for ChunkIter<'self, T> {
|
||||
#[inline]
|
||||
fn indexable(&self) -> uint {
|
||||
self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn idx(&self, index: uint) -> Option<&'self [T]> {
|
||||
if index < self.indexable() {
|
||||
let lo = index * self.size;
|
||||
let mut hi = lo + self.size;
|
||||
if hi < lo || hi > self.v.len() { hi = self.v.len(); }
|
||||
|
||||
Some(self.v.slice(lo, hi))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3378,6 +3416,14 @@ mod tests {
|
||||
assert_eq!(v.chunk_iter(2).collect::<~[&[int]]>(), ~[&[1i,2], &[3,4], &[5]]);
|
||||
assert_eq!(v.chunk_iter(3).collect::<~[&[int]]>(), ~[&[1i,2,3], &[4,5]]);
|
||||
assert_eq!(v.chunk_iter(6).collect::<~[&[int]]>(), ~[&[1i,2,3,4,5]]);
|
||||
|
||||
assert_eq!(v.chunk_iter(2).invert().collect::<~[&[int]]>(), ~[&[5i], &[3,4], &[1,2]]);
|
||||
let it = v.chunk_iter(2);
|
||||
assert_eq!(it.indexable(), 3);
|
||||
assert_eq!(it.idx(0).unwrap(), &[1,2]);
|
||||
assert_eq!(it.idx(1).unwrap(), &[3,4]);
|
||||
assert_eq!(it.idx(2).unwrap(), &[5]);
|
||||
assert_eq!(it.idx(3), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user