diff options
| author | Brian Anderson <banderson@mozilla.com> | 2013-07-08 16:20:38 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-07-08 16:29:54 -0700 |
| commit | fae33367692c634356d861dc4badb967dc72a573 (patch) | |
| tree | d73190f2523bed7d010da69442b0c28973631ac1 /src/libstd | |
| parent | b227583dadd1500bba7752c7e5d9f2ac931611bc (diff) | |
| parent | f503e539bf60416a731f9ecc12b6aab31ef2fe87 (diff) | |
| download | rust-fae33367692c634356d861dc4badb967dc72a573.tar.gz rust-fae33367692c634356d861dc4badb967dc72a573.zip | |
Merge remote-tracking branch 'mozilla/master'
Conflicts: src/libextra/test.rs src/libstd/rt/global_heap.rs src/libstd/unstable/lang.rs src/libstd/vec.rs
Diffstat (limited to 'src/libstd')
36 files changed, 1018 insertions, 1341 deletions
diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index 75d0fe7a0b2..dfd39af093d 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -17,8 +17,7 @@ use kinds::Copy; use option::Option; use sys; use uint; -use vec; -use vec::ImmutableVector; +use vec::{ImmutableVector, OwnedVector}; /// Code for dealing with @-vectors. This is pretty incomplete, and /// contains a bunch of duplication from the code for ~-vectors. @@ -142,7 +141,7 @@ pub fn to_managed_consume<T>(v: ~[T]) -> @[T] { let mut av = @[]; unsafe { raw::reserve(&mut av, v.len()); - do vec::consume(v) |_i, x| { + for v.consume_iter().advance |x| { raw::push(&mut av, x); } transmute(av) @@ -160,13 +159,14 @@ pub fn to_managed<T:Copy>(v: &[T]) -> @[T] { #[cfg(not(test))] pub mod traits { use at_vec::append; + use vec::Vector; use kinds::Copy; use ops::Add; - impl<'self,T:Copy> Add<&'self [T],@[T]> for @[T] { + impl<'self,T:Copy, V: Vector<T>> Add<V,@[T]> for @[T] { #[inline] - fn add(&self, rhs: & &'self [T]) -> @[T] { - append(*self, (*rhs)) + fn add(&self, rhs: &V) -> @[T] { + append(*self, rhs.as_slice()) } } } @@ -335,7 +335,7 @@ mod test { #[test] fn append_test() { - assert_eq!(@[1,2,3] + [4,5,6], @[1,2,3,4,5,6]); + assert_eq!(@[1,2,3] + &[4,5,6], @[1,2,3,4,5,6]); } #[test] diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs index e6be164099b..b0b586df4b5 100644 --- a/src/libstd/bool.rs +++ b/src/libstd/bool.rs @@ -122,6 +122,7 @@ pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) } * ~~~ {.rust} * rusti> std::bool::implies(true, true) * true +* ~~~ * * ~~~ {.rust} * rusti> std::bool::implies(true, false) diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 6a9555f4efc..47473c2faba 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -82,7 +82,8 @@ pub fn is_uppercase(c: char) -> bool { general_category::Lu(c) } /// #[inline] pub fn is_whitespace(c: char) -> bool { - ('\x09' <= c && c <= '\x0d') + c == ' ' + || ('\x09' <= c && c <= '\x0d') || general_category::Zs(c) || general_category::Zl(c) || general_category::Zp(c) diff --git a/src/libstd/either.rs b/src/libstd/either.rs index b6da93f9d40..8b9b3102831 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -73,7 +73,7 @@ pub fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] { pub fn partition<T, U>(eithers: ~[Either<T, U>]) -> (~[T], ~[U]) { let mut lefts: ~[T] = ~[]; let mut rights: ~[U] = ~[]; - do vec::consume(eithers) |_i, elt| { + for eithers.consume_iter().advance |elt| { match elt { Left(l) => lefts.push(l), Right(r) => rights.push(r) diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs index c9e33219fa5..f92561edcb0 100644 --- a/src/libstd/gc.rs +++ b/src/libstd/gc.rs @@ -9,6 +9,7 @@ // except according to those terms. #[doc(hidden)]; +#[allow(non_uppercase_statics)]; /*! Precise garbage collector diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 85dca1154bc..2d80dc2be15 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -24,7 +24,7 @@ use rand::RngUtil; use rand; use uint; use vec; -use vec::{ImmutableVector, MutableVector}; +use vec::{ImmutableVector, MutableVector, OwnedVector}; use kinds::Copy; use util::{replace, unreachable}; @@ -175,7 +175,8 @@ impl<K:Hash + Eq,V> HashMap<K, V> { vec::from_fn(new_capacity, |_| None)); self.size = 0; - do vec::consume(old_buckets) |_, bucket| { + // consume_rev_iter is more efficient + for old_buckets.consume_rev_iter().advance |bucket| { self.insert_opt_bucket(bucket); } } @@ -441,7 +442,7 @@ impl<K: Hash + Eq, V> HashMap<K, V> { vec::from_fn(INITIAL_CAPACITY, |_| None)); self.size = 0; - do vec::consume(buckets) |_, bucket| { + for buckets.consume_iter().advance |bucket| { match bucket { None => {}, Some(Bucket{key, value, _}) => { diff --git a/src/libstd/io.rs b/src/libstd/io.rs index bdcad15f45c..38826dd411b 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -917,7 +917,7 @@ fn convert_whence(whence: SeekStyle) -> i32 { impl Reader for *libc::FILE { fn read(&self, bytes: &mut [u8], len: uint) -> uint { unsafe { - do vec::as_mut_buf(bytes) |buf_p, buf_len| { + do bytes.as_mut_buf |buf_p, buf_len| { assert!(buf_len >= len); let count = libc::fread(buf_p as *mut c_void, 1u as size_t, @@ -1152,7 +1152,7 @@ impl<W:Writer,C> Writer for Wrapper<W, C> { impl Writer for *libc::FILE { fn write(&self, v: &[u8]) { unsafe { - do vec::as_imm_buf(v) |vbuf, len| { + do v.as_imm_buf |vbuf, len| { let nout = libc::fwrite(vbuf as *c_void, 1, len as size_t, @@ -1203,7 +1203,7 @@ impl Writer for fd_t { fn write(&self, v: &[u8]) { unsafe { let mut count = 0u; - do vec::as_imm_buf(v) |vbuf, len| { + do v.as_imm_buf |vbuf, len| { while count < len { let vb = ptr::offset(vbuf, count) as *c_void; let nout = libc::write(*self, vb, len as size_t); diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 4e598a4aa1c..2092ae588d0 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -8,316 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Composable internal iterators - -Internal iterators are functions implementing the protocol used by the `for` loop. - -An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal -breaking out of iteration. The adaptors in the module work with any such iterator, not just ones -tied to specific traits. For example: +/*! Times trait ~~~ {.rust} -println(iter::to_vec(|f| uint::range(0, 20, f)).to_str()); +use iter::Times; +let ten = 10 as uint; +let mut accum = 0; +for ten.times { accum += 1; } ~~~ -An external iterator object implementing the interface in the `iterator` module can be used as an -internal iterator by calling the `advance` method. For example: - -~~~ {.rust} -let xs = [0u, 1, 2, 3, 4, 5]; -let ys = [30, 40, 50, 60]; -let mut it = xs.iter().chain(ys.iter()); -for it.advance |&x: &uint| { - println(x.to_str()); -} -~~~ - -Internal iterators provide a subset of the functionality of an external iterator. It's not possible -to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often -much easier to implement. - */ -use cmp::Ord; -use option::{Option, Some, None}; -use num::{One, Zero}; -use ops::{Add, Mul}; - #[allow(missing_doc)] pub trait Times { fn times(&self, it: &fn() -> bool) -> bool; } -#[allow(missing_doc)] -pub trait FromIter<T> { - /// Build a container with elements from an internal iterator. - /// - /// # Example: - /// - /// ~~~ {.rust} - /// let xs = ~[1, 2, 3]; - /// let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) }; - /// assert_eq!(xs, ys); - /// ~~~ - pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self; -} - -/** - * Return true if `predicate` is true for any values yielded by an internal iterator. - * - * Example: - * - * ~~~ {.rust} - * let xs = ~[1u, 2, 3, 4, 5]; - * assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f))); - * assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f))); - * ~~~ - */ -#[inline] -pub fn any<T>(predicate: &fn(T) -> bool, - iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { - for iter |x| { - if predicate(x) { - return true; - } - } - return false; -} - -/** - * Return true if `predicate` is true for all values yielded by an internal iterator. - * - * # Example: - * - * ~~~ {.rust} - * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f))); - * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); - * ~~~ - */ -#[inline] -pub fn all<T>(predicate: &fn(T) -> bool, - iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { - // If we ever break, iter will return false, so this will only return true - // if predicate returns true for everything. - iter(|x| predicate(x)) -} - -/** - * Return the first element where `predicate` returns `true`. Return `None` if no element is found. - * - * # Example: - * - * ~~~ {.rust} - * let xs = ~[1u, 2, 3, 4, 5, 6]; - * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4); - * ~~~ - */ -#[inline] -pub fn find<T>(predicate: &fn(&T) -> bool, - iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { - for iter |x| { - if predicate(&x) { - return Some(x); - } - } - None -} - -/** - * Return the largest item yielded by an iterator. Return `None` if the iterator is empty. - * - * # Example: - * - * ~~~ {.rust} - * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - * assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15); - * ~~~ - */ -#[inline] -pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { - let mut result = None; - for iter |x| { - match result { - Some(ref mut y) => { - if x > *y { - *y = x; - } - } - None => result = Some(x) - } - } - result -} - -/** - * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty. - * - * # Example: - * - * ~~~ {.rust} - * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - * assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &-5); - * ~~~ - */ -#[inline] -pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { - let mut result = None; - for iter |x| { - match result { - Some(ref mut y) => { - if x < *y { - *y = x; - } - } - None => result = Some(x) - } - } - result -} - -/** - * Reduce an iterator to an accumulated value. - * - * # Example: - * - * ~~~ {.rust} - * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10); - * ~~~ - */ -#[inline] -pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T { - let mut result = start; - for iter |x| { - f(&mut result, x); - } - result -} - -/** - * Reduce an iterator to an accumulated value. - * - * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it - * forces the iterator to yield borrowed pointers. - * - * # Example: - * - * ~~~ {.rust} - * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { - * fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x)) - * } - * ~~~ - */ -#[inline] -pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T { - let mut result = start; - for iter |x| { - f(&mut result, x); - } - result -} - -/** - * Return the sum of the items yielding by an iterator. - * - * # Example: - * - * ~~~ {.rust} - * let xs: ~[int] = ~[1, 2, 3, 4]; - * assert_eq!(do sum |f| { xs.iter().advance(f) }, 10); - * ~~~ - */ -#[inline] -pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { - fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x)) -} - -/** - * Return the product of the items yielded by an iterator. - * - * # Example: - * - * ~~~ {.rust} - * let xs: ~[int] = ~[1, 2, 3, 4]; - * assert_eq!(do product |f| { xs.iter().advance(f) }, 24); - * ~~~ - */ -#[inline] -pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { - fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x)) -} - -#[cfg(test)] -mod tests { - use super::*; - use prelude::*; - - use int; - use uint; - - #[test] - fn test_from_iter() { - let xs = ~[1, 2, 3]; - let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) }; - assert_eq!(xs, ys); - } - - #[test] - fn test_any() { - let xs = ~[1u, 2, 3, 4, 5]; - assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f))); - assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f))); - } - - #[test] - fn test_all() { - assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f))); - assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f))); - } - - #[test] - fn test_find() { - let xs = ~[1u, 2, 3, 4, 5, 6]; - assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4); - } - - #[test] - fn test_max() { - let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15); - } - - #[test] - fn test_min() { - let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - assert_eq!(min(|f| xs.iter().advance(f)).unwrap(), &-5); - } - - #[test] - fn test_fold() { - assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10); - } - - #[test] - fn test_sum() { - let xs: ~[int] = ~[1, 2, 3, 4]; - assert_eq!(do sum |f| { xs.iter().advance(f) }, 10); - } - - #[test] - fn test_empty_sum() { - let xs: ~[int] = ~[]; - assert_eq!(do sum |f| { xs.iter().advance(f) }, 0); - } - - #[test] - fn test_product() { - let xs: ~[int] = ~[1, 2, 3, 4]; - assert_eq!(do product |f| { xs.iter().advance(f) }, 24); - } - - #[test] - fn test_empty_product() { - let xs: ~[int] = ~[]; - assert_eq!(do product |f| { xs.iter().advance(f) }, 1); - } -} diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 77befbf19aa..4f5f1bd85c7 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -26,6 +26,7 @@ use option::{Option, Some, None}; use ops::{Add, Mul}; use cmp::Ord; use clone::Clone; +use uint; /// Conversion from an `Iterator` pub trait FromIterator<A, T: Iterator<A>> { @@ -43,7 +44,7 @@ pub trait Iterator<A> { /// Return a lower bound and upper bound on the remaining length of the iterator. /// /// The common use case for the estimate is pre-allocating space to store the results. - fn size_hint(&self) -> (Option<uint>, Option<uint>) { (None, None) } + fn size_hint(&self) -> (uint, Option<uint>) { (0, None) } } /// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also @@ -244,6 +245,25 @@ pub trait IteratorUtil<A> { fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U) -> FlatMapIterator<'r, A, B, Self, U>; + /// Creates an iterator that calls a function with a reference to each + /// element before yielding it. This is often useful for debugging an + /// iterator pipeline. + /// + /// # Example + /// + /// ~~~ {.rust} + ///let xs = [1u, 4, 2, 3, 8, 9, 6]; + ///let sum = xs.iter() + /// .transform(|&x| x) + /// .peek_(|&x| debug!("filtering %u", x)) + /// .filter(|&x| x % 2 == 0) + /// .peek_(|&x| debug!("%u made it through", x)) + /// .sum(); + ///println(sum.to_str()); + /// ~~~ + // FIXME: #5898: should be called `peek` + fn peek_<'r>(self, f: &'r fn(&A)) -> PeekIterator<'r, A, Self>; + /// An adaptation of an external iterator to the for-loop protocol of rust. /// /// # Example @@ -337,16 +357,16 @@ pub trait IteratorUtil<A> { /// ~~~ {.rust} /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); - /// assert!(it.any_(|&x| *x == 3)); - /// assert!(!it.any_(|&x| *x == 3)); + /// assert!(it.any(|&x| *x == 3)); + /// assert!(!it.any(|&x| *x == 3)); /// ~~~ - fn any_(&mut self, f: &fn(A) -> bool) -> bool; + fn any(&mut self, f: &fn(A) -> bool) -> bool; /// Return the first element satisfying the specified predicate fn find_(&mut self, predicate: &fn(&A) -> bool) -> Option<A>; /// Return the index of the first element satisfying the specified predicate - fn position_(&mut self, predicate: &fn(A) -> bool) -> Option<uint>; + fn position(&mut self, predicate: &fn(A) -> bool) -> Option<uint>; /// Count the number of elements satisfying the specified predicate fn count(&mut self, predicate: &fn(A) -> bool) -> uint; @@ -441,6 +461,12 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T { FlatMapIterator{iter: self, f: f, subiter: None } } + // FIXME: #5898: should be called `peek` + #[inline] + fn peek_<'r>(self, f: &'r fn(&A)) -> PeekIterator<'r, A, T> { + PeekIterator{iter: self, f: f} + } + /// A shim implementing the `for` loop iteration protocol for iterator objects #[inline] fn advance(&mut self, f: &fn(A) -> bool) -> bool { @@ -503,7 +529,7 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T { } #[inline] - fn any_(&mut self, f: &fn(A) -> bool) -> bool { + fn any(&mut self, f: &fn(A) -> bool) -> bool { for self.advance |x| { if f(x) { return true; } } false } @@ -519,7 +545,7 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T { /// Return the index of the first element satisfying the specified predicate #[inline] - fn position_(&mut self, predicate: &fn(A) -> bool) -> Option<uint> { + fn position(&mut self, predicate: &fn(A) -> bool) -> Option<uint> { let mut i = 0; for self.advance |x| { if predicate(x) { @@ -684,18 +710,18 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> { } #[inline] - fn size_hint(&self) -> (Option<uint>, Option<uint>) { + fn size_hint(&self) -> (uint, Option<uint>) { let (a_lower, a_upper) = self.a.size_hint(); let (b_lower, b_upper) = self.b.size_hint(); - let lower = match (a_lower, b_lower) { - (Some(x), Some(y)) => Some(x + y), - (Some(x), None) => Some(x), - (None, Some(y)) => Some(y), - (None, None) => None + let lower = if uint::max_value - a_lower < b_lower { + uint::max_value + } else { + a_lower + b_lower }; let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value), (Some(x), Some(y)) => Some(x + y), _ => None }; @@ -719,6 +745,23 @@ impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for ZipIterator<A, T _ => None } } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = cmp::min(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::min(x,y)), + (Some(x), None) => Some(x), + (None, Some(y)) => Some(y), + (None, None) => None + }; + + (lower, upper) + } } /// An iterator which maps the values of `iter` with `f` @@ -737,7 +780,7 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> { } #[inline] - fn size_hint(&self) -> (Option<uint>, Option<uint>) { + fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() } } @@ -762,9 +805,9 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> { } #[inline] - fn size_hint(&self) -> (Option<uint>, Option<uint>) { + fn size_hint(&self) -> (uint, Option<uint>) { let (_, upper) = self.iter.size_hint(); - (None, upper) // can't know a lower bound, due to the predicate + (0, upper) // can't know a lower bound, due to the predicate } } @@ -787,9 +830,9 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B, } #[inline] - fn size_hint(&self) -> (Option<uint>, Option<uint>) { + fn size_hint(&self) -> (uint, Option<uint>) { let (_, upper) = self.iter.size_hint(); - (None, upper) // can't know a lower bound, due to the predicate + (0, upper) // can't know a lower bound, due to the predicate } } @@ -812,6 +855,11 @@ impl<A, T: Iterator<A>> Iterator<(uint, A)> for EnumerateIterator<A, T> { _ => None } } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + self.iter.size_hint() + } } /// An iterator which rejects elements while `predicate` is true @@ -844,6 +892,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for SkipWhileIterator<'self, A, T> { } } } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } } /// An iterator which only accepts elements while `predicate` is true @@ -872,6 +926,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for TakeWhileIterator<'self, A, T> { } } } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } } /// An iterator which skips over `n` elements of `iter`. @@ -905,6 +965,21 @@ impl<A, T: Iterator<A>> Iterator<A> for SkipIterator<A, T> { next } } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + let (lower, upper) = self.iter.size_hint(); + + let lower = if lower >= self.n { lower - self.n } else { 0 }; + + let upper = match upper { + Some(x) if x >= self.n => Some(x - self.n), + Some(_) => Some(0), + None => None + }; + + (lower, upper) + } } /// An iterator which only iterates over the first `n` iterations of `iter`. @@ -925,6 +1000,20 @@ impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<A, T> { None } } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + let (lower, upper) = self.iter.size_hint(); + + let lower = cmp::min(lower, self.n); + + let upper = match upper { + Some(x) if x < self.n => Some(x), + _ => Some(self.n) + }; + + (lower, upper) + } } /// An iterator to maintain state while iterating another iterator @@ -941,6 +1030,12 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B, fn next(&mut self) -> Option<B> { self.iter.next().chain(|a| (self.f)(&mut self.state, a)) } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the scan function + } } /// An iterator that maps each element to an iterator, @@ -971,6 +1066,32 @@ impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for } } +/// An iterator that calls a function with a reference to each +/// element before yielding it. +pub struct PeekIterator<'self, A, T> { + priv iter: T, + priv f: &'self fn(&A) +} + +impl<'self, A, T: Iterator<A>> Iterator<A> for PeekIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option<A> { + let next = self.iter.next(); + + match next { + Some(ref a) => (self.f)(a), + None => () + } + + next + } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + self.iter.size_hint() + } +} + /// An iterator which just modifies the contained state throughout iteration. pub struct UnfoldrIterator<'self, A, St> { priv f: &'self fn(&mut St) -> Option<A>, @@ -1022,6 +1143,11 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> { self.state = self.state.add(&self.step); // FIXME: #6050 Some(result) } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + (uint::max_value, None) // Too bad we can't specify an infinite lower bound + } } #[cfg(test)] @@ -1162,6 +1288,20 @@ mod tests { } #[test] + fn test_peek() { + let xs = [1u, 2, 3, 4]; + let mut n = 0; + + let ys = xs.iter() + .transform(|&x| x) + .peek_(|_| n += 1) + .collect::<~[uint]>(); + + assert_eq!(n, xs.len()); + assert_eq!(xs, ys.as_slice()); + } + + #[test] fn test_unfoldr() { fn count(st: &mut uint) -> Option<uint> { if *st < 10 { @@ -1238,6 +1378,43 @@ mod tests { } #[test] + fn test_iterator_size_hint() { + let c = Counter::new(0, 1); + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let v2 = &[10, 11, 12]; + let vi = v.iter(); + + assert_eq!(c.size_hint(), (uint::max_value, None)); + assert_eq!(vi.size_hint(), (10, Some(10))); + + assert_eq!(c.take_(5).size_hint(), (5, Some(5))); + assert_eq!(c.skip(5).size_hint().second(), None); + assert_eq!(c.take_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.skip_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.enumerate().size_hint(), (uint::max_value, None)); + assert_eq!(c.chain_(vi.transform(|&i| i)).size_hint(), (uint::max_value, None)); + assert_eq!(c.zip(vi).size_hint(), (10, Some(10))); + assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None)); + assert_eq!(c.filter(|_| false).size_hint(), (0, None)); + assert_eq!(c.transform(|_| 0).size_hint(), (uint::max_value, None)); + assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); + + assert_eq!(vi.take_(5).size_hint(), (5, Some(5))); + assert_eq!(vi.take_(12).size_hint(), (10, Some(10))); + assert_eq!(vi.skip(3).size_hint(), (7, Some(7))); + assert_eq!(vi.skip(12).size_hint(), (0, Some(0))); + assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.enumerate().size_hint(), (10, Some(10))); + assert_eq!(vi.chain_(v2.iter()).size_hint(), (13, Some(13))); + assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3))); + assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10))); + assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.transform(|i| i+1).size_hint(), (10, Some(10))); + assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10))); + } + + #[test] fn test_collect() { let a = ~[1, 2, 3, 4, 5]; let b: ~[int] = a.iter().transform(|&x| x).collect(); @@ -1256,10 +1433,10 @@ mod tests { #[test] fn test_any() { let v = ~&[1, 2, 3, 4, 5]; - assert!(v.iter().any_(|&x| x < 10)); - assert!(v.iter().any_(|&x| x.is_even())); - assert!(!v.iter().any_(|&x| x > 100)); - assert!(!v.slice(0, 0).iter().any_(|_| fail!())); + assert!(v.iter().any(|&x| x < 10)); + assert!(v.iter().any(|&x| x.is_even())); + assert!(!v.iter().any(|&x| x > 100)); + assert!(!v.slice(0, 0).iter().any(|_| fail!())); } #[test] @@ -1273,9 +1450,9 @@ mod tests { #[test] fn test_position() { let v = &[1, 3, 9, 27, 103, 14, 11]; - assert_eq!(v.iter().position_(|x| *x & 1 == 0).unwrap(), 5); - assert_eq!(v.iter().position_(|x| *x % 3 == 0).unwrap(), 1); - assert!(v.iter().position_(|x| *x % 12 == 0).is_none()); + assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5); + assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1); + assert!(v.iter().position(|x| *x % 12 == 0).is_none()); } #[test] diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index f350e106168..6c16ecc0d4e 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -18,7 +18,7 @@ intrinsic properties of the type. These classifications, often called They cannot be implemented by user code, but are instead implemented by the compiler automatically for the types to which they apply. -The 4 kinds are +The 3 kinds are * Copy - types that may be copied without allocation. This includes scalar types and managed pointers, and exludes owned pointers. It diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index f4ea29b5c05..14e719bc8dd 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -64,6 +64,7 @@ */ #[allow(non_camel_case_types)]; +#[allow(non_uppercase_statics)]; #[allow(missing_doc)]; // Initial glob-exports mean that all the contents of all the modules diff --git a/src/libstd/num/cmath.rs b/src/libstd/num/cmath.rs index 96d3b79e338..c89fc73693c 100644 --- a/src/libstd/num/cmath.rs +++ b/src/libstd/num/cmath.rs @@ -9,6 +9,7 @@ // except according to those terms. #[allow(missing_doc)]; +#[allow(non_uppercase_statics)]; // function names are almost identical to C's libmath, a few have been // renamed, grep for "rename:" diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 0b6eb766b29..a84c27cd918 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -10,6 +10,7 @@ //! Operations and constants for `f32` #[allow(missing_doc)]; +#[allow(non_uppercase_statics)]; use libc::c_int; use num::{Zero, One, strconv}; diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index c39c7a3a57d..216963e0414 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -11,6 +11,7 @@ //! Operations and constants for `f64` #[allow(missing_doc)]; +#[allow(non_uppercase_statics)]; use libc::c_int; use num::{Zero, One, strconv}; diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs index 7a6e3042e7b..d73ff16c6f7 100644 --- a/src/libstd/num/float.rs +++ b/src/libstd/num/float.rs @@ -21,6 +21,7 @@ // PORT this must match in width according to architecture #[allow(missing_doc)]; +#[allow(non_uppercase_statics)]; use f64; use libc::c_int; diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index d3c2733b47d..d39b4b2b911 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -10,6 +10,8 @@ //! Operations and constants for `int` +#[allow(non_uppercase_statics)]; + use num::BitCount; pub use self::generated::*; diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index f152d60cb7a..c2eebf9a3e4 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -14,6 +14,8 @@ macro_rules! int_module (($T:ty, $bits:expr) => (mod generated { +#[allow(non_uppercase_statics)]; + use num::{ToStrRadix, FromStrRadix}; use num::{Zero, One, strconv}; use prelude::*; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index f6dff4267b7..337d804ce73 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -101,12 +101,12 @@ impl_NumStrConv_Integer!(u64) // Special value strings as [u8] consts. -static inf_buf: [u8, ..3] = ['i' as u8, 'n' as u8, 'f' as u8]; -static positive_inf_buf: [u8, ..4] = ['+' as u8, 'i' as u8, 'n' as u8, +static INF_BUF: [u8, ..3] = ['i' as u8, 'n' as u8, 'f' as u8]; +static POS_INF_BUF: [u8, ..4] = ['+' as u8, 'i' as u8, 'n' as u8, 'f' as u8]; -static negative_inf_buf: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' as u8, +static NEG_INF_BUF: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' as u8, 'f' as u8]; -static nan_buf: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8]; +static NAN_BUF: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8]; /** * Converts an integral number to its string representation as a byte vector. @@ -506,15 +506,15 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ } if special { - if buf == inf_buf || buf == positive_inf_buf { + if buf == INF_BUF || buf == POS_INF_BUF { return NumStrConv::inf(); - } else if buf == negative_inf_buf { + } else if buf == NEG_INF_BUF { if negative { return NumStrConv::neg_inf(); } else { return None; } - } else if buf == nan_buf { + } else if buf == NAN_BUF { return NumStrConv::NaN(); } } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 25e338fcd0f..d185b2a05a8 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -14,6 +14,8 @@ macro_rules! uint_module (($T:ty, $T_SIGNED:ty, $bits:expr) => (mod generated { +#[allow(non_uppercase_statics)]; + use num::BitCount; use num::{ToStrRadix, FromStrRadix}; use num::{Zero, One, strconv}; diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 64381231258..fb9962f8a44 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -161,7 +161,7 @@ impl<T> Option<T> { /// Filters an optional value using given function. #[inline(always)] - pub fn filtered<'a>(self, f: &fn(t: &'a T) -> bool) -> Option<T> { + pub fn filtered(self, f: &fn(t: &T) -> bool) -> Option<T> { match self { Some(x) => if(f(&x)) {Some(x)} else {None}, None => None @@ -170,10 +170,16 @@ impl<T> Option<T> { /// Maps a `some` value from one type to another by reference #[inline] - pub fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option<U> { + pub fn map<'a, U>(&'a self, f: &fn(&'a T) -> U) -> Option<U> { match *self { Some(ref x) => Some(f(x)), None => None } } + /// Maps a `some` value from one type to another by a mutable reference + #[inline] + pub fn map_mut<'a, U>(&'a mut self, f: &fn(&'a mut T) -> U) -> Option<U> { + match *self { Some(ref mut x) => Some(f(x)), None => None } + } + /// As `map`, but consumes the option and gives `f` ownership to avoid /// copying. #[inline] diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 20c4346d618..c26020dd06d 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -92,7 +92,7 @@ pub fn as_c_charp<T>(s: &str, f: &fn(*c_char) -> T) -> T { pub fn fill_charp_buf(f: &fn(*mut c_char, size_t) -> bool) -> Option<~str> { let mut buf = vec::from_elem(TMPBUF_SZ, 0u8 as c_char); - do vec::as_mut_buf(buf) |b, sz| { + do buf.as_mut_buf |b, sz| { if f(b, sz as size_t) { unsafe { Some(str::raw::from_buf(b as *u8)) @@ -122,7 +122,7 @@ pub mod win32 { while !done { let mut k: DWORD = 0; let mut buf = vec::from_elem(n as uint, 0u16); - do vec::as_mut_buf(buf) |b, _sz| { + do buf.as_mut_buf |b, _sz| { k = f(b, TMPBUF_SZ as DWORD); if k == (0 as DWORD) { done = true; @@ -147,7 +147,7 @@ pub mod win32 { let mut t = s.to_utf16(); // Null terminate before passing on. t.push(0u16); - vec::as_imm_buf(t, |buf, _len| f(buf)) + t.as_imm_buf(|buf, _len| f(buf)) } } @@ -778,9 +778,9 @@ pub fn list_dir(p: &Path) -> ~[~str] { strings } } - do get_list(p).filtered |filename| { - *filename != ~"." && *filename != ~".." - } + do get_list(p).consume_iter().filter |filename| { + "." != *filename && ".." != *filename + }.collect() } } @@ -938,7 +938,7 @@ pub fn copy_file(from: &Path, to: &Path) -> bool { let mut done = false; let mut ok = true; while !done { - do vec::as_mut_buf(buf) |b, _sz| { + do buf.as_mut_buf |b, _sz| { let nread = libc::fread(b as *mut c_void, 1u as size_t, bufsize as size_t, istream); @@ -1694,7 +1694,7 @@ mod tests { let s = ~"hello"; let mut buf = s.as_bytes_with_null().to_owned(); let len = buf.len(); - do vec::as_mut_buf(buf) |b, _len| { + do buf.as_mut_buf |b, _len| { assert_eq!(libc::fwrite(b as *c_void, 1u as size_t, (s.len() + 1u) as size_t, ostream), len as size_t) diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index d560ce621ea..db534cca971 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -47,7 +47,7 @@ pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Great pub use char::Char; pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; -pub use iter::{Times, FromIter}; +pub use iter::{Times}; pub use iterator::{Iterator, IteratorUtil, OrdIterator}; pub use num::{Num, NumCast}; pub use num::{Orderable, Signed, Unsigned, Round}; @@ -72,7 +72,7 @@ pub use tuple::{CloneableTuple10, CloneableTuple11, CloneableTuple12}; pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTuple5}; pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9}; pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12}; -pub use vec::{VectorVector, CopyableVector, ImmutableVector}; +pub use vec::{Vector, VectorVector, CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableTotalOrdVector, ImmutableCopyableVector}; pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector, MutableVector}; pub use io::{Reader, ReaderUtil, Writer, WriterUtil}; diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index 473f56ddd79..aee6f1bd204 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -406,7 +406,7 @@ pub mod ptr_tests { do str::as_c_str(s1) |p1| { do str::as_c_str(s2) |p2| { let v = ~[p0, p1, p2, null()]; - do vec::as_imm_buf(v) |vp, len| { + do v.as_imm_buf |vp, len| { assert_eq!(unsafe { buf_len(vp) }, 3u); assert_eq!(len, 4u); } diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 5f96e38a55a..5054763d742 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -157,7 +157,7 @@ impl Rand for f32 { } } -static scale : f64 = (u32::max_value as f64) + 1.0f64; +static SCALE : f64 = (u32::max_value as f64) + 1.0f64; impl Rand for f64 { #[inline] fn rand<R: Rng>(rng: &mut R) -> f64 { @@ -165,7 +165,7 @@ impl Rand for f64 { let u2 = rng.next() as f64; let u3 = rng.next() as f64; - ((u1 / scale + u2) / scale + u3) / scale + ((u1 / SCALE + u2) / SCALE + u3) / SCALE } } @@ -724,7 +724,7 @@ impl IsaacRng { let mut a = self.a; let mut b = self.b + self.c; - static midpoint: uint = RAND_SIZE as uint / 2; + static MIDPOINT: uint = RAND_SIZE as uint / 2; macro_rules! ind (($x:expr) => { self.mem[($x >> 2) & (RAND_SIZE - 1)] @@ -748,9 +748,9 @@ impl IsaacRng { }} ); - let r = [(0, midpoint), (midpoint, 0)]; + let r = [(0, MIDPOINT), (MIDPOINT, 0)]; for r.iter().advance |&(mr_offset, m2_offset)| { - for uint::range_step(0, midpoint, 4) |base| { + for uint::range_step(0, MIDPOINT, 4) |base| { rngstep!(0, 13); rngstep!(1, -6); rngstep!(2, 2); @@ -830,7 +830,7 @@ pub fn seed() -> ~[u8] { unsafe { let n = rustrt::rand_seed_size() as uint; let mut s = vec::from_elem(n, 0_u8); - do vec::as_mut_buf(s) |p, sz| { + do s.as_mut_buf |p, sz| { rustrt::rand_gen_seed(p, sz as size_t) } s @@ -1087,7 +1087,7 @@ mod tests { for 10.times { unsafe { let seed = super::seed(); - let rt_rng = do vec::as_imm_buf(seed) |p, sz| { + let rt_rng = do seed.as_imm_buf |p, sz| { rustrt::rand_new_seeded(p, sz as size_t) }; let mut rng = IsaacRng::new_seeded(seed); diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index 16ab4771d0d..9075133b086 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -248,6 +248,14 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> { true } + #[cfg(not(stage0))] + fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<~u8>(); + if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; } + self.bump_past::<~u8>(); + true + } + fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<*u8>(); if ! self.inner.visit_ptr(mtbl, inner) { return false; } diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index fdda65d3e95..dd5075f8e66 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -302,6 +302,15 @@ impl TyVisitor for ReprVisitor { fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { self.writer.write_char('~'); self.write_mut_qualifier(mtbl); + do self.get::<*c_void> |b| { + self.visit_ptr_inner(*b, inner); + } + } + + #[cfg(not(stage0))] + fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write_char('~'); + self.write_mut_qualifier(mtbl); do self.get::<&managed::raw::BoxRepr> |b| { let p = ptr::to_unsafe_ptr(&b.data) as *c_void; self.visit_ptr_inner(p, inner); diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 4b475d74397..c9bf3b28530 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -60,12 +60,6 @@ pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void { #[cfg(stage0, not(test))] #[lang="exchange_malloc"] #[inline] -pub unsafe fn exchange_malloc_(td: *c_char, size: uintptr_t) -> *c_char { - exchange_malloc(td, size) -} - -#[cfg(stage0)] -#[inline] pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { let td = td as *TyDesc; let size = size as uint; @@ -86,13 +80,14 @@ pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { #[cfg(not(stage0), not(test))] #[lang="exchange_malloc"] #[inline] -pub unsafe fn exchange_malloc_(align: u32, size: uintptr_t) -> *c_char { - exchange_malloc(align, size) +pub unsafe fn exchange_malloc(align: u32, size: uintptr_t) -> *c_char { + malloc_raw(size as uint) as *c_char } -#[cfg(not(stage0))] +#[cfg(not(test))] +#[lang="vector_exchange_malloc"] #[inline] -pub unsafe fn exchange_malloc(align: u32, size: uintptr_t) -> *c_char { +pub unsafe fn vector_exchange_malloc(align: u32, size: uintptr_t) -> *c_char { let total_size = get_box_size(size as uint, align as uint); malloc_raw(total_size as uint) as *c_char } diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs index e39a6384bc6..0eaf0dd3ab6 100644 --- a/src/libstd/rt/uv/mod.rs +++ b/src/libstd/rt/uv/mod.rs @@ -40,6 +40,7 @@ use str::raw::from_c_str; use to_str::ToStr; use ptr::RawPtr; use vec; +use vec::ImmutableVector; use ptr; use str; use libc::{c_void, c_int, size_t, malloc, free}; @@ -312,7 +313,7 @@ pub fn vec_to_uv_buf(v: ~[u8]) -> Buf { unsafe { let data = malloc(v.len() as size_t) as *u8; assert!(data.is_not_null()); - do vec::as_imm_buf(v) |b, l| { + do v.as_imm_buf |b, l| { let data = data as *mut u8; ptr::copy_memory(data, b, l) } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 9e5def253c7..7e051b62171 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -24,7 +24,7 @@ use prelude::*; use ptr; use str; use task; -use vec; +use vec::ImmutableVector; /** * A value representing a child process. @@ -587,7 +587,7 @@ pub fn make_command_line(prog: &str, args: &[~str]) -> ~str { return cmd; fn append_arg(cmd: &mut ~str, arg: &str) { - let quote = arg.iter().any_(|c| c == ' ' || c == '\t'); + let quote = arg.iter().any(|c| c == ' ' || c == '\t'); if quote { cmd.push_char('"'); } @@ -703,7 +703,7 @@ fn with_argv<T>(prog: &str, args: &[~str], argptrs.push(str::as_c_str(*t, |b| b)); } argptrs.push(ptr::null()); - vec::as_imm_buf(argptrs, |buf, _len| cb(buf)) + argptrs.as_imm_buf(|buf, _len| cb(buf)) } #[cfg(unix)] @@ -722,7 +722,7 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T { } ptrs.push(ptr::null()); - vec::as_imm_buf(ptrs, |p, _len| + ptrs.as_imm_buf(|p, _len| unsafe { cb(::cast::transmute(p)) } ) } @@ -743,7 +743,7 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T { blk.push_all(kv.as_bytes_with_null_consume()); } blk.push(0); - vec::as_imm_buf(blk, |p, _len| + blk.as_imm_buf(|p, _len| unsafe { cb(::cast::transmute(p)) } ) } diff --git a/src/libstd/std.rs b/src/libstd/std.rs index f0f3bcdd4e9..8f86216d240 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -49,7 +49,7 @@ they contained the following prologue: #[link(name = "std", - vers = "0.7", + vers = "0.8-pre", uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 4115cad6559..3ecafa46a9c 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -13,8 +13,7 @@ * * Strings are a packed UTF-8 representation of text, stored as null * terminated buffers of u8 bytes. Strings should be indexed in bytes, - * for efficiency, but UTF-8 unsafe operations should be avoided. For - * some heavy-duty uses, try extra::rope. + * for efficiency, but UTF-8 unsafe operations should be avoided. */ use at_vec; @@ -279,7 +278,7 @@ impl CharEq for extern "Rust" fn(char) -> bool { impl<'self, C: CharEq> CharEq for &'self [C] { #[inline] fn matches(&self, c: char) -> bool { - self.iter().any_(|m| m.matches(c)) + self.iter().any(|m| m.matches(c)) } fn only_ascii(&self) -> bool { @@ -602,7 +601,7 @@ pub fn is_utf8(v: &[u8]) -> bool { if i + chsize > total { return false; } i += 1u; while chsize > 1u { - if v[i] & 192u8 != tag_cont_u8 { return false; } + if v[i] & 192u8 != TAG_CONT_U8 { return false; } i += 1u; chsize -= 1u; } @@ -743,18 +742,18 @@ pub struct CharRange { } // UTF-8 tags and ranges -static tag_cont_u8: u8 = 128u8; -static tag_cont: uint = 128u; -static max_one_b: uint = 128u; -static tag_two_b: uint = 192u; -static max_two_b: uint = 2048u; -static tag_three_b: uint = 224u; -static max_three_b: uint = 65536u; -static tag_four_b: uint = 240u; -static max_four_b: uint = 2097152u; -static tag_five_b: uint = 248u; -static max_five_b: uint = 67108864u; -static tag_six_b: uint = 252u; +static TAG_CONT_U8: u8 = 128u8; +static TAG_CONT: uint = 128u; +static MAX_ONE_B: uint = 128u; +static TAG_TWO_B: uint = 192u; +static MAX_TWO_B: uint = 2048u; +static TAG_THREE_B: uint = 224u; +static MAX_THREE_B: uint = 65536u; +static TAG_FOUR_B: uint = 240u; +static MAX_FOUR_B: uint = 2097152u; +static TAG_FIVE_B: uint = 248u; +static MAX_FIVE_B: uint = 67108864u; +static TAG_SIX_B: uint = 252u; /** * A dummy trait to hold all the utility methods that we implement on strings. @@ -826,6 +825,7 @@ pub mod raw { use str::raw; use str::{as_buf, is_utf8}; use vec; + use vec::MutableVector; /// Create a Rust string from a null-terminated *u8 buffer pub unsafe fn from_buf(buf: *u8) -> ~str { @@ -841,7 +841,7 @@ pub mod raw { /// Create a Rust string from a *u8 buffer of the given length pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str { let mut v: ~[u8] = vec::with_capacity(len + 1); - vec::as_mut_buf(v, |vbuf, _len| { + v.as_mut_buf(|vbuf, _len| { ptr::copy_memory(vbuf, buf as *u8, len) }); vec::raw::set_len(&mut v, len); @@ -863,7 +863,7 @@ pub mod raw { /// Converts a vector of bytes to a new owned string. pub unsafe fn from_bytes(v: &[u8]) -> ~str { - do vec::as_imm_buf(v) |buf, len| { + do v.as_imm_buf |buf, len| { from_buf_len(buf, len) } } @@ -917,7 +917,7 @@ pub mod raw { assert!((end <= n)); let mut v = vec::with_capacity(end - begin + 1u); - do vec::as_imm_buf(v) |vbuf, _vlen| { + do v.as_imm_buf |vbuf, _vlen| { let vbuf = ::cast::transmute_mut_unsafe(vbuf); let src = ptr::offset(sbuf, begin); ptr::copy_memory(vbuf, src, end - begin); @@ -1728,7 +1728,7 @@ impl<'self> StrSlice<'self> for &'self str { let mut i = i + 1u; while i < end { let byte = self[i]; - assert_eq!(byte & 192u8, tag_cont_u8); + assert_eq!(byte & 192u8, TAG_CONT_U8); val <<= 6u; val += (byte & 63u8) as uint; i += 1u; @@ -1755,7 +1755,7 @@ impl<'self> StrSlice<'self> for &'self str { let mut prev = start; // while there is a previous byte == 10...... - while prev > 0u && self[prev - 1u] & 192u8 == tag_cont_u8 { + while prev > 0u && self[prev - 1u] & 192u8 == TAG_CONT_U8 { prev -= 1u; } @@ -2071,11 +2071,11 @@ impl OwnedStr for ~str { fn push_char(&mut self, c: char) { unsafe { let code = c as uint; - let nb = if code < max_one_b { 1u } - else if code < max_two_b { 2u } - else if code < max_three_b { 3u } - else if code < max_four_b { 4u } - else if code < max_five_b { 5u } + let nb = if code < MAX_ONE_B { 1u } + else if code < MAX_TWO_B { 2u } + else if code < MAX_THREE_B { 3u } + else if code < MAX_FOUR_B { 4u } + else if code < MAX_FIVE_B { 5u } else { 6u }; let len = self.len(); let new_len = len + nb; @@ -2088,34 +2088,34 @@ impl OwnedStr for ~str { *ptr::mut_offset(buf, off) = code as u8; } 2u => { - *ptr::mut_offset(buf, off) = (code >> 6u & 31u | tag_two_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off) = (code >> 6u & 31u | TAG_TWO_B) as u8; + *ptr::mut_offset(buf, off + 1u) = (code & 63u | TAG_CONT) as u8; } 3u => { - *ptr::mut_offset(buf, off) = (code >> 12u & 15u | tag_three_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off) = (code >> 12u & 15u | TAG_THREE_B) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 2u) = (code & 63u | TAG_CONT) as u8; } 4u => { - *ptr::mut_offset(buf, off) = (code >> 18u & 7u | tag_four_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = (code & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off) = (code >> 18u & 7u | TAG_FOUR_B) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 3u) = (code & 63u | TAG_CONT) as u8; } 5u => { - *ptr::mut_offset(buf, off) = (code >> 24u & 3u | tag_five_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 4u) = (code & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off) = (code >> 24u & 3u | TAG_FIVE_B) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 4u) = (code & 63u | TAG_CONT) as u8; } 6u => { - *ptr::mut_offset(buf, off) = (code >> 30u & 1u | tag_six_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 5u) = (code & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off) = (code >> 30u & 1u | TAG_SIX_B) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | TAG_CONT) as u8; + *ptr::mut_offset(buf, off + 5u) = (code & 63u | TAG_CONT) as u8; } _ => {} } diff --git a/src/libstd/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs index 0956b76c970..8dd96df4545 100644 --- a/src/libstd/task/local_data_priv.rs +++ b/src/libstd/task/local_data_priv.rs @@ -142,7 +142,7 @@ unsafe fn local_data_lookup<T: 'static>( -> Option<(uint, *libc::c_void)> { let key_value = key_to_key_value(key); - let map_pos = (*map).iter().position_(|entry| + let map_pos = (*map).iter().position(|entry| match *entry { Some((k,_,_)) => k == key_value, None => false @@ -215,7 +215,7 @@ pub unsafe fn local_set<T: 'static>( } None => { // Find an empty slot. If not, grow the vector. - match (*map).iter().position_(|x| x.is_none()) { + match (*map).iter().position(|x| x.is_none()) { Some(empty_index) => { map[empty_index] = new_entry; } None => { map.push(new_entry); } } diff --git a/src/libstd/unicode.rs b/src/libstd/unicode.rs index 1e2d5c76fea..460c0a847c8 100644 --- a/src/libstd/unicode.rs +++ b/src/libstd/unicode.rs @@ -11,6 +11,7 @@ // The following code was generated by "src/etc/unicode.py" #[allow(missing_doc)]; +#[allow(non_uppercase_statics)]; pub mod general_category { diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs index 624062a7ec4..b1df5175c92 100644 --- a/src/libstd/unstable/extfmt.rs +++ b/src/libstd/unstable/extfmt.rs @@ -472,6 +472,7 @@ pub mod ct { // conditions can be evaluated at compile-time. For now though it's cleaner to // implement it this way, I think. #[doc(hidden)] +#[allow(non_uppercase_statics)] pub mod rt { use float; use str; diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 500143fb577..ce5ccf2401d 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -91,6 +91,7 @@ pub trait TyVisitor { fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool; fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool; fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool; fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool; @@ -417,3 +418,17 @@ pub extern "rust-intrinsic" { pub fn bswap32(x: i32) -> i32; pub fn bswap64(x: i64) -> i64; } + +#[cfg(target_endian = "little")] pub fn to_le16(x: i16) -> i16 { x } +#[cfg(target_endian = "big")] pub fn to_le16(x: i16) -> i16 { unsafe { bswap16(x) } } +#[cfg(target_endian = "little")] pub fn to_le32(x: i32) -> i32 { x } +#[cfg(target_endian = "big")] pub fn to_le32(x: i32) -> i32 { unsafe { bswap32(x) } } +#[cfg(target_endian = "little")] pub fn to_le64(x: i64) -> i64 { x } +#[cfg(target_endian = "big")] pub fn to_le64(x: i64) -> i64 { unsafe { bswap64(x) } } + +#[cfg(target_endian = "little")] pub fn to_be16(x: i16) -> i16 { unsafe { bswap16(x) } } +#[cfg(target_endian = "big")] pub fn to_be16(x: i16) -> i16 { x } +#[cfg(target_endian = "little")] pub fn to_be32(x: i32) -> i32 { unsafe { bswap32(x) } } +#[cfg(target_endian = "big")] pub fn to_be32(x: i32) -> i32 { x } +#[cfg(target_endian = "little")] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } } +#[cfg(target_endian = "big")] pub fn to_be64(x: i64) -> i64 { x } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 1180ac883e7..2c1e913511e 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -16,14 +16,12 @@ use cast::transmute; use cast; use container::{Container, Mutable}; use cmp; -use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; +use cmp::{Eq, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use clone::Clone; use iterator::{FromIterator, Iterator, IteratorUtil}; -use iter::FromIter; use kinds::Copy; use libc::c_void; use num::Zero; -use ops::Add; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; use ptr; @@ -34,9 +32,9 @@ use sys::size_of; use uint; use unstable::intrinsics; #[cfg(stage0)] -use intrinsic::{get_tydesc}; +use intrinsic::{get_tydesc, TyDesc}; #[cfg(not(stage0))] -use unstable::intrinsics::{get_tydesc, contains_managed}; +use unstable::intrinsics::{get_tydesc, contains_managed, TyDesc}; use vec; use util; @@ -56,7 +54,7 @@ pub fn same_length<T, U>(xs: &[T], ys: &[U]) -> bool { pub fn from_fn<T>(n_elts: uint, op: &fn(uint) -> T) -> ~[T] { unsafe { let mut v = with_capacity(n_elts); - do as_mut_buf(v) |p, _len| { + do v.as_mut_buf |p, _len| { let mut i: uint = 0u; while i < n_elts { intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), op(i)); @@ -81,7 +79,7 @@ pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> ~[T] { // vec::with_capacity/ptr::set_memory for primitive types. unsafe { let mut v = with_capacity(n_elts); - do as_mut_buf(v) |p, _len| { + do v.as_mut_buf |p, _len| { let mut i = 0u; while i < n_elts { intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), copy t); @@ -158,165 +156,69 @@ pub fn build_sized_opt<A>(size: Option<uint>, build_sized(size.get_or_default(4), builder) } -// Accessors - -/// Copies +/// An iterator over the slices of a vector separated by elements that +/// match a predicate function. +pub struct VecSplitIterator<'self, T> { + priv v: &'self [T], + priv n: uint, + priv pred: &'self fn(t: &T) -> bool, + priv finished: bool +} -/// Split the vector `v` by applying each element against the predicate `f`. -pub fn split<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] { - let ln = v.len(); - if (ln == 0u) { return ~[] } +impl<'self, T> Iterator<&'self [T]> for VecSplitIterator<'self, T> { + fn next(&mut self) -> Option<&'self [T]> { + if self.finished { return None; } - let mut start = 0u; - let mut result = ~[]; - while start < ln { - match v.slice(start, ln).iter().position_(|t| f(t)) { - None => break, - Some(i) => { - result.push(v.slice(start, start + i).to_owned()); - start += i + 1u; - } + if self.n == 0 { + self.finished = true; + return Some(self.v); } - } - result.push(v.slice(start, ln).to_owned()); - result -} - -/** - * Split the vector `v` by applying each element against the predicate `f` up - * to `n` times. - */ -pub fn splitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] { - let ln = v.len(); - if (ln == 0u) { return ~[] } - let mut start = 0u; - let mut count = n; - let mut result = ~[]; - while start < ln && count > 0u { - match v.slice(start, ln).iter().position_(|t| f(t)) { - None => break, - Some(i) => { - result.push(v.slice(start, start + i).to_owned()); - // Make sure to skip the separator. - start += i + 1u; - count -= 1u; + match self.v.iter().position(|x| (self.pred)(x)) { + None => { + self.finished = true; + Some(self.v) + } + Some(idx) => { + let ret = Some(self.v.slice(0, idx)); + self.v = self.v.slice(idx + 1, self.v.len()); + self.n -= 1; + ret } } } - result.push(v.slice(start, ln).to_owned()); - result } -/** - * Reverse split the vector `v` by applying each element against the predicate - * `f`. - */ -pub fn rsplit<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] { - let ln = v.len(); - if (ln == 0) { return ~[] } - - let mut end = ln; - let mut result = ~[]; - while end > 0 { - match v.slice(0, end).rposition(|t| f(t)) { - None => break, - Some(i) => { - result.push(v.slice(i + 1, end).to_owned()); - end = i; - } - } - } - result.push(v.slice(0u, end).to_owned()); - result.reverse(); - result +/// An iterator over the slices of a vector separated by elements that +/// match a predicate function, from back to front. +pub struct VecRSplitIterator<'self, T> { + priv v: &'self [T], + priv n: uint, + priv pred: &'self fn(t: &T) -> bool, + priv finished: bool } -/** - * Reverse split the vector `v` by applying each element against the predicate - * `f` up to `n times. - */ -pub fn rsplitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] { - let ln = v.len(); - if (ln == 0u) { return ~[] } +impl<'self, T> Iterator<&'self [T]> for VecRSplitIterator<'self, T> { + fn next(&mut self) -> Option<&'self [T]> { + if self.finished { return None; } - let mut end = ln; - let mut count = n; - let mut result = ~[]; - while end > 0u && count > 0u { - match v.slice(0, end).rposition(|t| f(t)) { - None => break, - Some(i) => { - result.push(v.slice(i + 1u, end).to_owned()); - // Make sure to skip the separator. - end = i; - count -= 1u; - } + if self.n == 0 { + self.finished = true; + return Some(self.v); } - } - result.push(v.slice(0u, end).to_owned()); - result.reverse(); - result -} -/// Consumes all elements, in a vector, moving them out into the / closure -/// provided. The vector is traversed from the start to the end. -/// -/// This method does not impose any requirements on the type of the vector being -/// consumed, but it prevents any usage of the vector after this function is -/// called. -/// -/// # Examples -/// -/// ~~~ {.rust} -/// let v = ~[~"a", ~"b"]; -/// do vec::consume(v) |i, s| { -/// // s has type ~str, not &~str -/// io::println(s + fmt!(" %d", i)); -/// } -/// ~~~ -pub fn consume<T>(mut v: ~[T], f: &fn(uint, v: T)) { - unsafe { - do as_mut_buf(v) |p, ln| { - for uint::range(0, ln) |i| { - // NB: This unsafe operation counts on init writing 0s to the - // holes we create in the vector. That ensures that, if the - // iterator fails then we won't try to clean up the consumed - // elements during unwinding - let x = intrinsics::init(); - let p = ptr::mut_offset(p, i); - f(i, ptr::replace_ptr(p, x)); + match self.v.rposition(|x| (self.pred)(x)) { + None => { + self.finished = true; + Some(self.v) } - } - - raw::set_len(&mut v, 0); - } -} - -/// Consumes all elements, in a vector, moving them out into the / closure -/// provided. The vectors is traversed in reverse order (from end to start). -/// -/// This method does not impose any requirements on the type of the vector being -/// consumed, but it prevents any usage of the vector after this function is -/// called. -pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) { - unsafe { - do as_mut_buf(v) |p, ln| { - let mut i = ln; - while i > 0 { - i -= 1; - - // NB: This unsafe operation counts on init writing 0s to the - // holes we create in the vector. That ensures that, if the - // iterator fails then we won't try to clean up the consumed - // elements during unwinding - let x = intrinsics::init(); - let p = ptr::mut_offset(p, i); - f(i, ptr::replace_ptr(p, x)); + Some(idx) => { + let ret = Some(self.v.slice(idx + 1, self.v.len())); + self.v = self.v.slice(0, idx); + self.n -= 1; + ret } } - - raw::set_len(&mut v, 0); } } @@ -342,20 +244,6 @@ pub fn append_one<T>(lhs: ~[T], x: T) -> ~[T] { // Functional utilities -/// Consumes a vector, mapping it into a different vector. This function takes -/// ownership of the supplied vector `v`, moving each element into the closure -/// provided to generate a new element. The vector of new elements is then -/// returned. -/// -/// The original vector `v` cannot be used after this function call (it is moved -/// inside), but there are no restrictions on the type of the vector. -pub fn map_consume<T, U>(v: ~[T], f: &fn(v: T) -> U) -> ~[U] { - let mut result = ~[]; - do consume(v) |_i, x| { - result.push(f(x)); - } - result -} /** * Apply a function to each element of a vector and return a concatenation * of each result vector @@ -366,79 +254,6 @@ pub fn flat_map<T, U>(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] { result } -pub fn filter_map<T, U>( - v: ~[T], - f: &fn(t: T) -> Option<U>) -> ~[U] -{ - /*! - * - * Apply a function to each element of a vector and return the results. - * Consumes the input vector. If function `f` returns `None` then that - * element is excluded from the resulting vector. - */ - - let mut result = ~[]; - do consume(v) |_, elem| { - match f(elem) { - None => {} - Some(result_elem) => { result.push(result_elem); } - } - } - result -} - -pub fn filter_mapped<T, U: Copy>( - v: &[T], - f: &fn(t: &T) -> Option<U>) -> ~[U] -{ - /*! - * - * Like `filter_map()`, but operates on a borrowed slice - * and does not consume the input. - */ - - let mut result = ~[]; - for v.iter().advance |elem| { - match f(elem) { - None => {/* no-op */ } - Some(result_elem) => { result.push(result_elem); } - } - } - result -} - -/** - * Construct a new vector from the elements of a vector for which some - * predicate holds. - * - * Apply function `f` to each element of `v` and return a vector containing - * only those elements for which `f` returned true. - */ -pub fn filter<T>(v: ~[T], f: &fn(t: &T) -> bool) -> ~[T] { - let mut result = ~[]; - // FIXME (#4355 maybe): using v.consume here crashes - // do v.consume |_, elem| { - do consume(v) |_, elem| { - if f(&elem) { result.push(elem); } - } - result -} - -/** - * Construct a new vector from the elements of a vector for which some - * predicate holds. - * - * Apply function `f` to each element of `v` and return a vector containing - * only those elements for which `f` returned true. - */ -pub fn filtered<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] { - let mut result = ~[]; - for v.iter().advance |elem| { - if f(elem) { result.push(copy *elem); } - } - result -} - /// Flattens a vector of vectors of T into a single vector of T. pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] { v.concat_vec() } @@ -524,7 +339,7 @@ pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) { pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) { let mut ts = ~[]; let mut us = ~[]; - do consume(v) |_i, p| { + for v.consume_iter().advance |p| { let (t, u) = p; ts.push(t); us.push(u); @@ -566,16 +381,6 @@ pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] { w } -/// Returns a vector with the order of elements reversed -pub fn reversed<T:Copy>(v: &[T]) -> ~[T] { - let mut rs: ~[T] = ~[]; - let mut i = v.len(); - if i == 0 { return (rs); } else { i -= 1; } - while i != 0 { rs.push(copy v[i]); i -= 1; } - rs.push(copy v[0]); - rs -} - /** * Iterate over all permutations of vector `v`. * @@ -630,251 +435,222 @@ pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> } } -/** - * Iterate over all contiguous windows of length `n` of the vector `v`. - * - * # Example - * - * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, `[3,4]`) - * - * ~~~ {.rust} - * for windowed(2, &[1,2,3,4]) |v| { - * io::println(fmt!("%?", v)); - * } - * ~~~ - * - */ -pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) -> bool { - assert!(1u <= n); - if n > v.len() { return true; } - for uint::range(0, v.len() - n + 1) |i| { - if !it(v.slice(i, i + n)) { return false; } - } - return true; +/// An iterator over the (overlapping) slices of length `size` within +/// a vector. +pub struct VecWindowIter<'self, T> { + priv v: &'self [T], + priv size: uint } -/** - * Work with the buffer of a vector. - * - * Allows for unsafe manipulation of vector contents, which is useful for - * foreign interop. - */ -#[inline] -pub fn as_imm_buf<T,U>(s: &[T], - /* NB---this CANNOT be const, see below */ - f: &fn(*T, uint) -> U) -> U { - - // NB---Do not change the type of s to `&const [T]`. This is - // unsound. The reason is that we are going to create immutable pointers - // into `s` and pass them to `f()`, but in fact they are potentially - // pointing at *mutable memory*. Use `as_const_buf` or `as_mut_buf` - // instead! - - unsafe { - let v : *(*T,uint) = transmute(&s); - let (buf,len) = *v; - f(buf, len / sys::nonzero_size_of::<T>()) +impl<'self, T> Iterator<&'self [T]> for VecWindowIter<'self, T> { + fn next(&mut self) -> Option<&'self [T]> { + if self.size > self.v.len() { + None + } else { + let ret = Some(self.v.slice(0, self.size)); + self.v = self.v.slice(1, self.v.len()); + ret + } } } -/// Similar to `as_imm_buf` but passing a `*mut T` -#[inline] -pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U { - unsafe { - let v : *(*mut T,uint) = transmute(&s); - let (buf,len) = *v; - f(buf, len / sys::nonzero_size_of::<T>()) +/// An iterator over a vector in (non-overlapping) chunks (`size` +/// elements at a time). +pub struct VecChunkIter<'self, T> { + priv v: &'self [T], + priv size: uint +} + +impl<'self, T> Iterator<&'self [T]> for VecChunkIter<'self, T> { + fn next(&mut self) -> Option<&'self [T]> { + if self.size == 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 + } } } // Equality -/// Tests whether two slices are equal to one another. This is only true if both -/// slices are of the same length, and each of the corresponding elements return -/// true when queried via the `eq` function. -fn eq<T: Eq>(a: &[T], b: &[T]) -> bool { - let (a_len, b_len) = (a.len(), b.len()); - if a_len != b_len { return false; } +#[cfg(not(test))] +pub mod traits { + use super::Vector; + use kinds::Copy; + use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Equal, Equiv}; + use ops::Add; - let mut i = 0; - while i < a_len { - if a[i] != b[i] { return false; } - i += 1; + impl<'self,T:Eq> Eq for &'self [T] { + fn eq(&self, other: & &'self [T]) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()).all(|(s,o)| *s == *o) + } + #[inline] + fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) } } - true -} -/// Similar to the `vec::eq` function, but this is defined for types which -/// implement `TotalEq` as opposed to types which implement `Eq`. Equality -/// comparisons are done via the `equals` function instead of `eq`. -fn equals<T: TotalEq>(a: &[T], b: &[T]) -> bool { - let (a_len, b_len) = (a.len(), b.len()); - if a_len != b_len { return false; } - - let mut i = 0; - while i < a_len { - if !a[i].equals(&b[i]) { return false; } - i += 1; + impl<T:Eq> Eq for ~[T] { + #[inline] + fn eq(&self, other: &~[T]) -> bool { self.as_slice() == *other } + #[inline] + fn ne(&self, other: &~[T]) -> bool { !self.eq(other) } } - true -} - -#[cfg(not(test))] -impl<'self,T:Eq> Eq for &'self [T] { - #[inline] - fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) } - #[inline] - fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) } -} -#[cfg(not(test))] -impl<T:Eq> Eq for ~[T] { - #[inline] - fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) } - #[inline] - fn ne(&self, other: &~[T]) -> bool { !self.eq(other) } -} - -#[cfg(not(test))] -impl<T:Eq> Eq for @[T] { - #[inline] - fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) } - #[inline] - fn ne(&self, other: &@[T]) -> bool { !self.eq(other) } -} + impl<T:Eq> Eq for @[T] { + #[inline] + fn eq(&self, other: &@[T]) -> bool { self.as_slice() == *other } + #[inline] + fn ne(&self, other: &@[T]) -> bool { !self.eq(other) } + } -#[cfg(not(test))] -impl<'self,T:TotalEq> TotalEq for &'self [T] { - #[inline] - fn equals(&self, other: & &'self [T]) -> bool { equals(*self, *other) } -} + impl<'self,T:TotalEq> TotalEq for &'self [T] { + fn equals(&self, other: & &'self [T]) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()).all(|(s,o)| s.equals(o)) + } + } -#[cfg(not(test))] -impl<T:TotalEq> TotalEq for ~[T] { - #[inline] - fn equals(&self, other: &~[T]) -> bool { equals(*self, *other) } -} + impl<T:TotalEq> TotalEq for ~[T] { + #[inline] + fn equals(&self, other: &~[T]) -> bool { self.as_slice().equals(&other.as_slice()) } + } -#[cfg(not(test))] -impl<T:TotalEq> TotalEq for @[T] { - #[inline] - fn equals(&self, other: &@[T]) -> bool { equals(*self, *other) } -} + impl<T:TotalEq> TotalEq for @[T] { + #[inline] + fn equals(&self, other: &@[T]) -> bool { self.as_slice().equals(&other.as_slice()) } + } -#[cfg(not(test))] -impl<'self,T:Eq> Equiv<~[T]> for &'self [T] { - #[inline] - fn equiv(&self, other: &~[T]) -> bool { eq(*self, *other) } -} + impl<'self,T:Eq, V: Vector<T>> Equiv<V> for &'self [T] { + #[inline] + fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } + } -// Lexicographical comparison + impl<'self,T:Eq, V: Vector<T>> Equiv<V> for ~[T] { + #[inline] + fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } + } -fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering { - let low = uint::min(a.len(), b.len()); + impl<'self,T:Eq, V: Vector<T>> Equiv<V> for @[T] { + #[inline] + fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } + } - for uint::range(0, low) |idx| { - match a[idx].cmp(&b[idx]) { - Greater => return Greater, - Less => return Less, - Equal => () + impl<'self,T:TotalOrd> TotalOrd for &'self [T] { + fn cmp(&self, other: & &'self [T]) -> Ordering { + for self.iter().zip(other.iter()).advance |(s,o)| { + match s.cmp(o) { + Equal => {}, + non_eq => { return non_eq; } + } + } + self.len().cmp(&other.len()) } } - a.len().cmp(&b.len()) -} - -#[cfg(not(test))] -impl<'self,T:TotalOrd> TotalOrd for &'self [T] { - #[inline] - fn cmp(&self, other: & &'self [T]) -> Ordering { cmp(*self, *other) } -} + impl<T: TotalOrd> TotalOrd for ~[T] { + #[inline] + fn cmp(&self, other: &~[T]) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } -#[cfg(not(test))] -impl<T: TotalOrd> TotalOrd for ~[T] { - #[inline] - fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) } -} + impl<T: TotalOrd> TotalOrd for @[T] { + #[inline] + fn cmp(&self, other: &@[T]) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } -#[cfg(not(test))] -impl<T: TotalOrd> TotalOrd for @[T] { - #[inline] - fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) } -} + impl<'self,T:Ord> Ord for &'self [T] { + fn lt(&self, other: & &'self [T]) -> bool { + for self.iter().zip(other.iter()).advance |(s,o)| { + if *s < *o { return true; } + if *s > *o { return false; } + } + self.len() < other.len() + } + #[inline] + fn le(&self, other: & &'self [T]) -> bool { !(*other < *self) } + #[inline] + fn ge(&self, other: & &'self [T]) -> bool { !(*self < *other) } + #[inline] + fn gt(&self, other: & &'self [T]) -> bool { *other < *self } + } -fn lt<T:Ord>(a: &[T], b: &[T]) -> bool { - let (a_len, b_len) = (a.len(), b.len()); - let end = uint::min(a_len, b_len); + impl<T:Ord> Ord for ~[T] { + #[inline] + fn lt(&self, other: &~[T]) -> bool { self.as_slice() < other.as_slice() } + #[inline] + fn le(&self, other: &~[T]) -> bool { self.as_slice() <= other.as_slice() } + #[inline] + fn ge(&self, other: &~[T]) -> bool { self.as_slice() >= other.as_slice() } + #[inline] + fn gt(&self, other: &~[T]) -> bool { self.as_slice() > other.as_slice() } + } - let mut i = 0; - while i < end { - let (c_a, c_b) = (&a[i], &b[i]); - if *c_a < *c_b { return true; } - if *c_a > *c_b { return false; } - i += 1; + impl<T:Ord> Ord for @[T] { + #[inline] + fn lt(&self, other: &@[T]) -> bool { self.as_slice() < other.as_slice() } + #[inline] + fn le(&self, other: &@[T]) -> bool { self.as_slice() <= other.as_slice() } + #[inline] + fn ge(&self, other: &@[T]) -> bool { self.as_slice() >= other.as_slice() } + #[inline] + fn gt(&self, other: &@[T]) -> bool { self.as_slice() > other.as_slice() } } - a_len < b_len + impl<'self,T:Copy, V: Vector<T>> Add<V, ~[T]> for &'self [T] { + #[inline] + fn add(&self, rhs: &V) -> ~[T] { + let mut res = self.to_owned(); + res.push_all(rhs.as_slice()); + res + } + } + impl<T:Copy, V: Vector<T>> Add<V, ~[T]> for ~[T] { + #[inline] + fn add(&self, rhs: &V) -> ~[T] { + let mut res = self.to_owned(); + res.push_all(rhs.as_slice()); + res + } + } } -fn le<T:Ord>(a: &[T], b: &[T]) -> bool { !lt(b, a) } -fn ge<T:Ord>(a: &[T], b: &[T]) -> bool { !lt(a, b) } -fn gt<T:Ord>(a: &[T], b: &[T]) -> bool { lt(b, a) } +#[cfg(test)] +pub mod traits {} -#[cfg(not(test))] -impl<'self,T:Ord> Ord for &'self [T] { - #[inline] - fn lt(&self, other: & &'self [T]) -> bool { lt((*self), (*other)) } - #[inline] - fn le(&self, other: & &'self [T]) -> bool { le((*self), (*other)) } - #[inline] - fn ge(&self, other: & &'self [T]) -> bool { ge((*self), (*other)) } - #[inline] - fn gt(&self, other: & &'self [T]) -> bool { gt((*self), (*other)) } +/// Any vector that can be represented as a slice. +pub trait Vector<T> { + /// Work with `self` as a slice. + fn as_slice<'a>(&'a self) -> &'a [T]; } - -#[cfg(not(test))] -impl<T:Ord> Ord for ~[T] { - #[inline] - fn lt(&self, other: &~[T]) -> bool { lt((*self), (*other)) } - #[inline] - fn le(&self, other: &~[T]) -> bool { le((*self), (*other)) } - #[inline] - fn ge(&self, other: &~[T]) -> bool { ge((*self), (*other)) } - #[inline] - fn gt(&self, other: &~[T]) -> bool { gt((*self), (*other)) } +impl<'self,T> Vector<T> for &'self [T] { + #[inline(always)] + fn as_slice<'a>(&'a self) -> &'a [T] { *self } } - -#[cfg(not(test))] -impl<T:Ord> Ord for @[T] { - #[inline] - fn lt(&self, other: &@[T]) -> bool { lt((*self), (*other)) } - #[inline] - fn le(&self, other: &@[T]) -> bool { le((*self), (*other)) } - #[inline] - fn ge(&self, other: &@[T]) -> bool { ge((*self), (*other)) } - #[inline] - fn gt(&self, other: &@[T]) -> bool { gt((*self), (*other)) } +impl<T> Vector<T> for ~[T] { + #[inline(always)] + fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v } } - -#[cfg(not(test))] -impl<'self,T:Copy> Add<&'self [T], ~[T]> for ~[T] { - #[inline] - fn add(&self, rhs: & &'self [T]) -> ~[T] { - append(copy *self, (*rhs)) - } +impl<T> Vector<T> for @[T] { + #[inline(always)] + fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v } } impl<'self, T> Container for &'self [T] { /// Returns true if a vector contains no elements #[inline] fn is_empty(&self) -> bool { - as_imm_buf(*self, |_p, len| len == 0u) + self.as_imm_buf(|_p, len| len == 0u) } /// Returns the length of a vector #[inline] fn len(&self) -> uint { - as_imm_buf(*self, |_p, len| len) + self.as_imm_buf(|_p, len| len) } } @@ -882,13 +658,13 @@ impl<T> Container for ~[T] { /// Returns true if a vector contains no elements #[inline] fn is_empty(&self) -> bool { - as_imm_buf(*self, |_p, len| len == 0u) + self.as_imm_buf(|_p, len| len == 0u) } /// Returns the length of a vector #[inline] fn len(&self) -> uint { - as_imm_buf(*self, |_p, len| len) + self.as_imm_buf(|_p, len| len) } } @@ -915,6 +691,14 @@ pub trait ImmutableVector<'self, T> { fn slice(&self, start: uint, end: uint) -> &'self [T]; fn iter(self) -> VecIterator<'self, T>; fn rev_iter(self) -> VecRevIterator<'self, T>; + fn split_iter(self, pred: &'self fn(&T) -> bool) -> VecSplitIterator<'self, T>; + fn splitn_iter(self, n: uint, pred: &'self fn(&T) -> bool) -> VecSplitIterator<'self, T>; + fn rsplit_iter(self, pred: &'self fn(&T) -> bool) -> VecRSplitIterator<'self, T>; + fn rsplitn_iter(self, n: uint, pred: &'self fn(&T) -> bool) -> VecRSplitIterator<'self, T>; + + fn window_iter(self, size: uint) -> VecWindowIter<'self, T>; + fn chunk_iter(self, size: uint) -> VecChunkIter<'self, T>; + fn head(&self) -> &'self T; fn head_opt(&self) -> Option<&'self T>; fn tail(&self) -> &'self [T]; @@ -925,12 +709,13 @@ pub trait ImmutableVector<'self, T> { fn last_opt(&self) -> Option<&'self T>; fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>; fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U]; - fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U]; unsafe fn unsafe_ref(&self, index: uint) -> *T; fn bsearch(&self, f: &fn(&T) -> Ordering) -> Option<uint>; fn map<U>(&self, &fn(t: &T) -> U) -> ~[U]; + + fn as_imm_buf<U>(&self, f: &fn(*T, uint) -> U) -> U; } /// Extension methods for vectors @@ -940,7 +725,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { fn slice(&self, start: uint, end: uint) -> &'self [T] { assert!(start <= end); assert!(end <= self.len()); - do as_imm_buf(*self) |p, _len| { + do self.as_imm_buf |p, _len| { unsafe { transmute((ptr::offset(p, start), (end - start) * sys::nonzero_size_of::<T>())) @@ -966,6 +751,101 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { } } + /// Returns an iterator over the subslices of the vector which are + /// separated by elements that match `pred`. + #[inline] + fn split_iter(self, pred: &'self fn(&T) -> bool) -> VecSplitIterator<'self, T> { + self.splitn_iter(uint::max_value, pred) + } + /// Returns an iterator over the subslices of the vector which are + /// separated by elements that match `pred`, limited to splitting + /// at most `n` times. + #[inline] + fn splitn_iter(self, n: uint, pred: &'self fn(&T) -> bool) -> VecSplitIterator<'self, T> { + VecSplitIterator { + v: self, + n: n, + pred: pred, + finished: false + } + } + /// Returns an iterator over the subslices of the vector which are + /// separated by elements that match `pred`. This starts at the + /// end of the vector and works backwards. + #[inline] + fn rsplit_iter(self, pred: &'self fn(&T) -> bool) -> VecRSplitIterator<'self, T> { + self.rsplitn_iter(uint::max_value, pred) + } + /// Returns an iterator over the subslices of the vector which are + /// separated by elements that match `pred` limited to splitting + /// at most `n` times. This starts at the end of the vector and + /// works backwards. + #[inline] + fn rsplitn_iter(self, n: uint, pred: &'self fn(&T) -> bool) -> VecRSplitIterator<'self, T> { + VecRSplitIterator { + v: self, + n: n, + pred: pred, + finished: false + } + } + + /** + * Returns an iterator over all contiguous windows of length + * `size`. The windows overlap. If the vector is shorter than + * `size`, the iterator returns no values. + * + * # Failure + * + * Fails if `size` is 0. + * + * # Example + * + * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, + * `[3,4]`): + * + * ~~~ {.rust} + * let v = &[1,2,3,4]; + * for v.window_iter().advance |win| { + * io::println(fmt!("%?", win)); + * } + * ~~~ + * + */ + fn window_iter(self, size: uint) -> VecWindowIter<'self, T> { + assert!(size != 0); + VecWindowIter { v: self, size: size } + } + + /** + * + * Returns an iterator over `size` elements of the vector at a + * time. The chunks do not overlap. If `size` does not divide the + * length of the vector, then the last chunk will not have length + * `size`. + * + * # Failure + * + * Fails if `size` is 0. + * + * # Example + * + * Print the vector two elements at a time (i.e. `[1,2]`, + * `[3,4]`, `[5]`): + * + * ~~~ {.rust} + * let v = &[1,2,3,4,5]; + * for v.chunk_iter().advance |win| { + * io::println(fmt!("%?", win)); + * } + * ~~~ + * + */ + fn chunk_iter(self, size: uint) -> VecChunkIter<'self, T> { + assert!(size != 0); + VecChunkIter { v: self, size: size } + } + /// Returns the first element of a vector, failing if the vector is empty. #[inline] fn head(&self) -> &'self T { @@ -1035,17 +915,6 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U] { flat_map(*self, f) } - /** - * Apply a function to each element of a vector and return the results - * - * If function `f` returns `none` then that element is excluded from - * the resulting vector. - */ - #[inline] - fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U] { - filter_mapped(*self, f) - } - /// Returns a pointer to the element at the given index, without doing /// bounds checking. #[inline] @@ -1089,6 +958,28 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U] { self.iter().transform(f).collect() } + + /** + * Work with the buffer of a vector. + * + * Allows for unsafe manipulation of vector contents, which is useful for + * foreign interop. + */ + #[inline] + fn as_imm_buf<U>(&self, + /* NB---this CANNOT be const, see below */ + f: &fn(*T, uint) -> U) -> U { + // NB---Do not change the type of s to `&const [T]`. This is + // unsound. The reason is that we are going to create immutable pointers + // into `s` and pass them to `f()`, but in fact they are potentially + // pointing at *mutable memory*. Use `as_mut_buf` instead! + + unsafe { + let v : *(*T,uint) = transmute(self); + let (buf,len) = *v; + f(buf, len / sys::nonzero_size_of::<T>()) + } + } } #[allow(missing_doc)] @@ -1102,7 +993,7 @@ impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] { /// Find the first index containing a matching value #[inline] fn position_elem(&self, x: &T) -> Option<uint> { - self.iter().position_(|y| *x == *y) + self.iter().position(|y| *x == *y) } /// Find the last index containing a matching value @@ -1136,7 +1027,6 @@ impl<'self, T: TotalOrd> ImmutableTotalOrdVector<T> for &'self [T] { #[allow(missing_doc)] pub trait ImmutableCopyableVector<T> { - fn filtered(&self, f: &fn(&T) -> bool) -> ~[T]; fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]); unsafe fn unsafe_get(&self, elem: uint) -> T; } @@ -1144,18 +1034,6 @@ pub trait ImmutableCopyableVector<T> { /// Extension methods for vectors impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] { /** - * Construct a new vector from the elements of a vector for which some - * predicate holds. - * - * Apply function `f` to each element of `v` and return a vector - * containing only those elements for which `f` returned true. - */ - #[inline] - fn filtered(&self, f: &fn(t: &T) -> bool) -> ~[T] { - filtered(*self, f) - } - - /** * Partitions the vector into those that satisfies the predicate, and * those that do not. */ @@ -1184,6 +1062,9 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] { #[allow(missing_doc)] pub trait OwnedVector<T> { + fn consume_iter(self) -> VecConsumeIterator<T>; + fn consume_rev_iter(self) -> VecConsumeRevIterator<T>; + fn reserve(&mut self, n: uint); fn reserve_at_least(&mut self, n: uint); fn capacity(&self) -> uint; @@ -1193,21 +1074,46 @@ pub trait OwnedVector<T> { fn push_all_move(&mut self, rhs: ~[T]); fn pop(&mut self) -> T; + fn pop_opt(&mut self) -> Option<T>; fn shift(&mut self) -> T; + fn shift_opt(&mut self) -> Option<T>; fn unshift(&mut self, x: T); fn insert(&mut self, i: uint, x:T); fn remove(&mut self, i: uint) -> T; fn swap_remove(&mut self, index: uint) -> T; fn truncate(&mut self, newlen: uint); fn retain(&mut self, f: &fn(t: &T) -> bool); - fn consume(self, f: &fn(uint, v: T)); - fn consume_reverse(self, f: &fn(uint, v: T)); - fn filter(self, f: &fn(t: &T) -> bool) -> ~[T]; fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]); fn grow_fn(&mut self, n: uint, op: &fn(uint) -> T); } impl<T> OwnedVector<T> for ~[T] { + /// Creates a consuming iterator, that is, one that moves each + /// value out of the vector (from start to end). The vector cannot + /// be used after calling this. + /// + /// Note that this performs O(n) swaps, and so `consume_rev_iter` + /// (which just calls `pop` repeatedly) is more efficient. + /// + /// # Examples + /// + /// ~~~ {.rust} + /// let v = ~[~"a", ~"b"]; + /// for v.consume_iter().advance |s| { + /// // s has type ~str, not &~str + /// println(s); + /// } + /// ~~~ + fn consume_iter(self) -> VecConsumeIterator<T> { + VecConsumeIterator { v: self, idx: 0 } + } + /// Creates a consuming iterator that moves out of the vector in + /// reverse order. Also see `consume_iter`, however note that this + /// is more efficient. + fn consume_rev_iter(self) -> VecConsumeRevIterator<T> { + VecConsumeRevIterator { v: self } + } + /** * Reserves capacity for exactly `n` elements in the given vector. * @@ -1351,7 +1257,7 @@ impl<T> OwnedVector<T> for ~[T] { let new_len = self.len() + rhs.len(); self.reserve(new_len); unsafe { - do as_mut_buf(rhs) |p, len| { + do rhs.as_mut_buf |p, len| { for uint::range(0, len) |i| { let x = ptr::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit()); @@ -1362,35 +1268,49 @@ impl<T> OwnedVector<T> for ~[T] { } } - /// Remove the last element from a vector and return it - fn pop(&mut self) -> T { - let ln = self.len(); - if ln == 0 { - fail!("sorry, cannot pop an empty vector") - } - let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]); - unsafe { - let val = ptr::replace_ptr(valptr, intrinsics::init()); - raw::set_len(self, ln - 1u); - val + /// Remove the last element from a vector and return it, or `None` if it is empty + fn pop_opt(&mut self) -> Option<T> { + match self.len() { + 0 => None, + ln => { + let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]); + unsafe { + let val = ptr::replace_ptr(valptr, intrinsics::init()); + raw::set_len(self, ln - 1u); + Some(val) + } + } } } + + /// Remove the last element from a vector and return it, failing if it is empty + #[inline] + fn pop(&mut self) -> T { + self.pop_opt().expect("pop: empty vector") + } + /// Removes the first element from a vector and return it + #[inline] fn shift(&mut self) -> T { - unsafe { - assert!(!self.is_empty()); - - if self.len() == 1 { return self.pop() } + self.shift_opt().expect("shift: empty vector") + } - if self.len() == 2 { - let last = self.pop(); - let first = self.pop(); - self.push(last); - return first; - } + /// Removes the first element from a vector and return it, or `None` if it is empty + fn shift_opt(&mut self) -> Option<T> { + unsafe { + let ln = match self.len() { + 0 => return None, + 1 => return self.pop_opt(), + 2 => { + let last = self.pop(); + let first = self.pop_opt(); + self.push(last); + return first; + } + x => x + }; - let ln = self.len(); let next_ln = self.len() - 1; // Save the last element. We're going to overwrite its position @@ -1426,7 +1346,7 @@ impl<T> OwnedVector<T> for ~[T] { let vp = raw::to_mut_ptr(*self); let vp = ptr::mut_offset(vp, next_ln - 1); - ptr::replace_ptr(vp, work_elt) + Some(ptr::replace_ptr(vp, work_elt)) } } @@ -1483,7 +1403,7 @@ impl<T> OwnedVector<T> for ~[T] { /// Shorten a vector, dropping excess elements. fn truncate(&mut self, newlen: uint) { - do as_mut_buf(*self) |p, oldlen| { + do self.as_mut_buf |p, oldlen| { assert!(newlen <= oldlen); unsafe { // This loop is optimized out for non-drop types. @@ -1516,21 +1436,6 @@ impl<T> OwnedVector<T> for ~[T] { } } - #[inline] - fn consume(self, f: &fn(uint, v: T)) { - consume(self, f) - } - - #[inline] - fn consume_reverse(self, f: &fn(uint, v: T)) { - consume_reverse(self, f) - } - - #[inline] - fn filter(self, f: &fn(&T) -> bool) -> ~[T] { - filter(self, f) - } - /** * Partitions the vector into those that satisfies the predicate, and * those that do not. @@ -1540,7 +1445,7 @@ impl<T> OwnedVector<T> for ~[T] { let mut lefts = ~[]; let mut rights = ~[]; - do self.consume |_, elt| { + for self.consume_iter().advance |elt| { if f(&elt) { lefts.push(elt); } else { @@ -1656,7 +1561,7 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] { if self.len() == 0 { return; } let mut last_written = 0; let mut next_to_read = 1; - do as_mut_buf(*self) |p, ln| { + do self.as_mut_buf |p, ln| { // last_written < next_to_read <= ln while next_to_read < ln { // last_written < next_to_read < ln @@ -1710,6 +1615,8 @@ pub trait MutableVector<'self, T> { unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T; unsafe fn unsafe_set(&self, index: uint, val: T); + + fn as_mut_buf<U>(&self, f: &fn(*mut T, uint) -> U) -> U; } impl<'self,T> MutableVector<'self, T> for &'self mut [T] { @@ -1718,7 +1625,7 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] { fn mut_slice(self, start: uint, end: uint) -> &'self mut [T] { assert!(start <= end); assert!(end <= self.len()); - do as_mut_buf(self) |p, _len| { + do self.as_mut_buf |p, _len| { unsafe { transmute((ptr::mut_offset(p, start), (end - start) * sys::nonzero_size_of::<T>())) @@ -1791,6 +1698,17 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] { unsafe fn unsafe_set(&self, index: uint, val: T) { *self.unsafe_mut_ref(index) = val; } + + /// Similar to `as_imm_buf` but passing a `*mut T` + #[inline] + fn as_mut_buf<U>(&self, f: &fn(*mut T, uint) -> U) -> U { + unsafe { + let v : *(*mut T,uint) = transmute(self); + let (buf,len) = *v; + f(buf, len / sys::nonzero_size_of::<T>()) + } + } + } /// Trait for ~[T] where T is Cloneable @@ -1840,7 +1758,7 @@ pub mod raw { use ptr; use sys; use unstable::intrinsics; - use vec::{UnboxedVecRepr, as_imm_buf, as_mut_buf, with_capacity}; + use vec::{UnboxedVecRepr, with_capacity, ImmutableVector, MutableVector}; use util; /// The internal representation of a (boxed) vector @@ -1928,7 +1846,7 @@ pub mod raw { */ #[inline] pub unsafe fn get<T:Copy>(v: &[T], i: uint) -> T { - as_imm_buf(v, |p, _len| copy *ptr::offset(p, i)) + v.as_imm_buf(|p, _len| copy *ptr::offset(p, i)) } /** @@ -1939,7 +1857,7 @@ pub mod raw { #[inline] pub unsafe fn init_elem<T>(v: &mut [T], i: uint, val: T) { let mut box = Some(val); - do as_mut_buf(v) |p, _len| { + do v.as_mut_buf |p, _len| { let box2 = util::replace(&mut box, None); intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), box2.unwrap()); @@ -1959,7 +1877,7 @@ pub mod raw { pub unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] { let mut dst = with_capacity(elts); set_len(&mut dst, elts); - as_mut_buf(dst, |p_dst, _len_dst| ptr::copy_memory(p_dst, ptr, elts)); + dst.as_mut_buf(|p_dst, _len_dst| ptr::copy_memory(p_dst, ptr, elts)); dst } @@ -1975,8 +1893,8 @@ pub mod raw { assert!(dst.len() >= count); assert!(src.len() >= count); - do as_mut_buf(dst) |p_dst, _len_dst| { - do as_imm_buf(src) |p_src, _len_src| { + do dst.as_mut_buf |p_dst, _len_dst| { + do src.as_imm_buf |p_src, _len_src| { ptr::copy_memory(p_dst, p_src, count) } } @@ -2000,7 +1918,7 @@ pub mod bytes { impl<'self> MutableByteVector for &'self mut [u8] { #[inline] fn set_memory(self, value: u8) { - do vec::as_mut_buf(self) |p, len| { + do self.as_mut_buf |p, len| { unsafe { ptr::set_memory(p, value, len) }; } } @@ -2107,16 +2025,21 @@ macro_rules! iterator { } #[inline] - fn size_hint(&self) -> (Option<uint>, Option<uint>) { - let exact = Some(((self.end as uint) - (self.ptr as uint)) / size_of::<$elem>()); - (exact, exact) + fn size_hint(&self) -> (uint, Option<uint>) { + let diff = if $step > 0 { + (self.end as uint) - (self.ptr as uint) + } else { + (self.ptr as uint) - (self.end as uint) + }; + let exact = diff / size_of::<$elem>(); + (exact, Some(exact)) } } } } //iterator!{struct VecIterator -> *T, &'self T} -/// An iterator for iterating over a vector +/// An iterator for iterating over a vector. pub struct VecIterator<'self, T> { priv ptr: *T, priv end: *T, @@ -2125,7 +2048,7 @@ pub struct VecIterator<'self, T> { iterator!{impl VecIterator -> &'self T, 1} //iterator!{struct VecRevIterator -> *T, &'self T} -/// An iterator for iterating over a vector in reverse +/// An iterator for iterating over a vector in reverse. pub struct VecRevIterator<'self, T> { priv ptr: *T, priv end: *T, @@ -2134,7 +2057,7 @@ pub struct VecRevIterator<'self, T> { iterator!{impl VecRevIterator -> &'self T, -1} //iterator!{struct VecMutIterator -> *mut T, &'self mut T} -/// An iterator for mutating the elements of a vector +/// An iterator for mutating the elements of a vector. pub struct VecMutIterator<'self, T> { priv ptr: *mut T, priv end: *mut T, @@ -2143,7 +2066,7 @@ pub struct VecMutIterator<'self, T> { iterator!{impl VecMutIterator -> &'self mut T, 1} //iterator!{struct VecMutRevIterator -> *mut T, &'self mut T} -/// An iterator for mutating the elements of a vector in reverse +/// An iterator for mutating the elements of a vector in reverse. pub struct VecMutRevIterator<'self, T> { priv ptr: *mut T, priv end: *mut T, @@ -2151,12 +2074,40 @@ pub struct VecMutRevIterator<'self, T> { } iterator!{impl VecMutRevIterator -> &'self mut T, -1} -impl<T> FromIter<T> for ~[T]{ - #[inline] - pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] { - let mut v = ~[]; - for iter |x| { v.push(x) } - v +/// An iterator that moves out of a vector. +pub struct VecConsumeIterator<T> { + priv v: ~[T], + priv idx: uint, +} + +impl<T> Iterator<T> for VecConsumeIterator<T> { + fn next(&mut self) -> Option<T> { + // this is peculiar, but is required for safety with respect + // to dtors. It traverses the first half of the vec, and + // removes them by swapping them with the last element (and + // popping), which results in the second half in reverse + // order, and so these can just be pop'd off. That is, + // + // [1,2,3,4,5] => 1, [5,2,3,4] => 2, [5,4,3] => 3, [5,4] => 4, + // [5] -> 5, [] + let l = self.v.len(); + if self.idx < l { + self.v.swap(self.idx, l - 1); + self.idx += 1; + } + + self.v.pop_opt() + } +} + +/// An iterator that moves out of a vector in reverse order. +pub struct VecConsumeRevIterator<T> { + priv v: ~[T] +} + +impl<T> Iterator<T> for VecConsumeRevIterator<T> { + fn next(&mut self) -> Option<T> { + self.v.pop_opt() } } @@ -2176,7 +2127,7 @@ impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] { impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] { pub fn from_iterator(iterator: &mut T) -> ~[A] { let (lower, _) = iterator.size_hint(); - let mut xs = with_capacity(lower.get_or_zero()); + let mut xs = with_capacity(lower); for iterator.advance |x| { xs.push(x); } @@ -2459,6 +2410,17 @@ mod tests { } #[test] + fn test_pop_opt() { + let mut v = ~[5]; + let e = v.pop_opt(); + assert_eq!(v.len(), 0); + assert_eq!(e, Some(5)); + let f = v.pop_opt(); + assert_eq!(f, None); + let g = v.pop_opt(); + assert_eq!(g, None); + } + fn test_swap_remove() { let mut v = ~[1, 2, 3, 4, 5]; let mut e = v.swap_remove(0); @@ -2627,87 +2589,6 @@ mod tests { } #[test] - fn test_filter_mapped() { - // Test on-stack filter-map. - let mut v = ~[1u, 2u, 3u]; - let mut w = filter_mapped(v, square_if_odd_r); - assert_eq!(w.len(), 2u); - assert_eq!(w[0], 1u); - assert_eq!(w[1], 9u); - - // Test on-heap filter-map. - v = ~[1u, 2u, 3u, 4u, 5u]; - w = filter_mapped(v, square_if_odd_r); - assert_eq!(w.len(), 3u); - assert_eq!(w[0], 1u); - assert_eq!(w[1], 9u); - assert_eq!(w[2], 25u); - - fn halve(i: &int) -> Option<int> { - if *i % 2 == 0 { - Some::<int>(*i / 2) - } else { - None::<int> - } - } - fn halve_for_sure(i: &int) -> int { *i / 2 } - let all_even: ~[int] = ~[0, 2, 8, 6]; - let all_odd1: ~[int] = ~[1, 7, 3]; - let all_odd2: ~[int] = ~[]; - let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3]; - let mix_dest: ~[int] = ~[1, 3, 0, 0]; - assert!(filter_mapped(all_even, halve) == - all_even.map(halve_for_sure)); - assert_eq!(filter_mapped(all_odd1, halve), ~[]); - assert_eq!(filter_mapped(all_odd2, halve), ~[]); - assert_eq!(filter_mapped(mix, halve), mix_dest); - } - - #[test] - fn test_filter_map() { - // Test on-stack filter-map. - let mut v = ~[1u, 2u, 3u]; - let mut w = filter_map(v, square_if_odd_v); - assert_eq!(w.len(), 2u); - assert_eq!(w[0], 1u); - assert_eq!(w[1], 9u); - - // Test on-heap filter-map. - v = ~[1u, 2u, 3u, 4u, 5u]; - w = filter_map(v, square_if_odd_v); - assert_eq!(w.len(), 3u); - assert_eq!(w[0], 1u); - assert_eq!(w[1], 9u); - assert_eq!(w[2], 25u); - - fn halve(i: int) -> Option<int> { - if i % 2 == 0 { - Some::<int>(i / 2) - } else { - None::<int> - } - } - fn halve_for_sure(i: &int) -> int { *i / 2 } - let all_even: ~[int] = ~[0, 2, 8, 6]; - let all_even0: ~[int] = copy all_even; - let all_odd1: ~[int] = ~[1, 7, 3]; - let all_odd2: ~[int] = ~[]; - let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3]; - let mix_dest: ~[int] = ~[1, 3, 0, 0]; - assert!(filter_map(all_even, halve) == - all_even0.map(halve_for_sure)); - assert_eq!(filter_map(all_odd1, halve), ~[]); - assert_eq!(filter_map(all_odd2, halve), ~[]); - assert_eq!(filter_map(mix, halve), mix_dest); - } - - #[test] - fn test_filter() { - assert_eq!(filter(~[1u, 2u, 3u], is_odd), ~[1u, 3u]); - assert_eq!(filter(~[1u, 2u, 4u, 8u, 16u], is_three), ~[]); - } - - #[test] fn test_retain() { let mut v = ~[1, 2, 3, 4, 5]; v.retain(is_odd); @@ -2821,75 +2702,17 @@ mod tests { } #[test] - fn reverse_and_reversed() { + fn test_reverse() { let mut v: ~[int] = ~[10, 20]; assert_eq!(v[0], 10); assert_eq!(v[1], 20); v.reverse(); assert_eq!(v[0], 20); assert_eq!(v[1], 10); - let v2 = reversed::<int>([10, 20]); - assert_eq!(v2[0], 20); - assert_eq!(v2[1], 10); - v[0] = 30; - assert_eq!(v2[0], 20); - // Make sure they work with 0-length vectors too. - - let v4 = reversed::<int>([]); - assert_eq!(v4, ~[]); + let mut v3: ~[int] = ~[]; v3.reverse(); - } - - #[test] - fn reversed_mut() { - let v2 = reversed::<int>([10, 20]); - assert_eq!(v2[0], 20); - assert_eq!(v2[1], 10); - } - - #[test] - fn test_split() { - fn f(x: &int) -> bool { *x == 3 } - - assert_eq!(split([], f), ~[]); - assert_eq!(split([1, 2], f), ~[~[1, 2]]); - assert_eq!(split([3, 1, 2], f), ~[~[], ~[1, 2]]); - assert_eq!(split([1, 2, 3], f), ~[~[1, 2], ~[]]); - assert_eq!(split([1, 2, 3, 4, 3, 5], f), ~[~[1, 2], ~[4], ~[5]]); - } - - #[test] - fn test_splitn() { - fn f(x: &int) -> bool { *x == 3 } - - assert_eq!(splitn([], 1u, f), ~[]); - assert_eq!(splitn([1, 2], 1u, f), ~[~[1, 2]]); - assert_eq!(splitn([3, 1, 2], 1u, f), ~[~[], ~[1, 2]]); - assert_eq!(splitn([1, 2, 3], 1u, f), ~[~[1, 2], ~[]]); - assert!(splitn([1, 2, 3, 4, 3, 5], 1u, f) == - ~[~[1, 2], ~[4, 3, 5]]); - } - - #[test] - fn test_rsplit() { - fn f(x: &int) -> bool { *x == 3 } - - assert_eq!(rsplit([], f), ~[]); - assert_eq!(rsplit([1, 2], f), ~[~[1, 2]]); - assert_eq!(rsplit([1, 2, 3], f), ~[~[1, 2], ~[]]); - assert!(rsplit([1, 2, 3, 4, 3, 5], f) == - ~[~[1, 2], ~[4], ~[5]]); - } - - #[test] - fn test_rsplitn() { - fn f(x: &int) -> bool { *x == 3 } - - assert_eq!(rsplitn([], 1u, f), ~[]); - assert_eq!(rsplitn([1, 2], 1u, f), ~[~[1, 2]]); - assert_eq!(rsplitn([1, 2, 3], 1u, f), ~[~[1, 2], ~[]]); - assert_eq!(rsplitn([1, 2, 3, 4, 3, 5], 1u, f), ~[~[1, 2, 3, 4], ~[5]]); + assert!(v3.is_empty()); } #[test] @@ -2933,28 +2756,24 @@ mod tests { } #[test] - fn test_windowed () { - fn t(n: uint, expected: &[&[int]]) { - let mut i = 0; - for windowed(n, [1,2,3,4,5,6]) |v| { - assert_eq!(v, expected[i]); - i += 1; - } - - // check that we actually iterated the right number of times - assert_eq!(i, expected.len()); - } - t(3, &[&[1,2,3],&[2,3,4],&[3,4,5],&[4,5,6]]); - t(4, &[&[1,2,3,4],&[2,3,4,5],&[3,4,5,6]]); - t(7, &[]); - t(8, &[]); + fn test_shift() { + let mut x = ~[1, 2, 3]; + assert_eq!(x.shift(), 1); + assert_eq!(&x, &~[2, 3]); + assert_eq!(x.shift(), 2); + assert_eq!(x.shift(), 3); + assert_eq!(x.len(), 0); } #[test] - #[should_fail] - #[ignore(cfg(windows))] - fn test_windowed_() { - for windowed (0u, [1u,2u,3u,4u,5u,6u]) |_v| {} + fn test_shift_opt() { + let mut x = ~[1, 2, 3]; + assert_eq!(x.shift_opt(), Some(1)); + assert_eq!(&x, &~[2, 3]); + assert_eq!(x.shift_opt(), Some(2)); + assert_eq!(x.shift_opt(), Some(3)); + assert_eq!(x.shift_opt(), None); + assert_eq!(x.len(), 0); } #[test] @@ -3061,156 +2880,6 @@ mod tests { #[ignore(windows)] #[should_fail] #[allow(non_implicitly_copyable_typarams)] - fn test_split_fail_ret_true() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do split(v) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - true - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_split_fail_ret_false() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do split(v) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_splitn_fail_ret_true() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do splitn(v, 100) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - true - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_splitn_fail_ret_false() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do split(v) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_rsplit_fail_ret_true() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do rsplit(v) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - true - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_rsplit_fail_ret_false() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do rsplit(v) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_rsplitn_fail_ret_true() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do rsplitn(v, 100) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - true - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_rsplitn_fail_ret_false() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do rsplitn(v, 100) |_elt| { - if i == 2 { - fail!() - } - i += 1; - - false - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - fn test_consume_fail() { - let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do consume(v) |_i, _elt| { - if i == 2 { - fail!() - } - i += 1; - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] fn test_grow_fn_fail() { let mut v = ~[]; do v.grow_fn(100) |i| { @@ -3239,21 +2908,6 @@ mod tests { #[test] #[ignore(windows)] #[should_fail] - fn test_map_consume_fail() { - let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do map_consume(v) |_elt| { - if i == 2 { - fail!() - } - i += 0; - ~[(~0, @0)] - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] fn test_flat_map_fail() { let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; @@ -3269,38 +2923,6 @@ mod tests { #[test] #[ignore(windows)] #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_filter_mapped_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do filter_mapped(v) |_elt| { - if i == 2 { - fail!() - } - i += 0; - Some((~0, @0)) - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] - #[allow(non_implicitly_copyable_typarams)] - fn test_filter_fail() { - let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - let mut i = 0; - do v.filtered |_elt| { - if i == 2 { - fail!() - } - i += 0; - true - }; - } - - #[test] - #[ignore(windows)] - #[should_fail] fn test_rposition_fail() { let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; @@ -3333,7 +2955,7 @@ mod tests { #[should_fail] fn test_as_imm_buf_fail() { let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - do as_imm_buf(v) |_buf, _i| { + do v.as_imm_buf |_buf, _i| { fail!() } } @@ -3343,7 +2965,7 @@ mod tests { #[should_fail] fn test_as_mut_buf_fail() { let mut v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; - do as_mut_buf(v) |_buf, _i| { + do v.as_mut_buf |_buf, _i| { fail!() } } @@ -3373,21 +2995,31 @@ mod tests { use iterator::*; let xs = [1, 2, 5, 10, 11]; let mut it = xs.iter(); - assert_eq!(it.size_hint(), (Some(5), Some(5))); + assert_eq!(it.size_hint(), (5, Some(5))); assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.size_hint(), (Some(4), Some(4))); + assert_eq!(it.size_hint(), (4, Some(4))); assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.size_hint(), (Some(3), Some(3))); + assert_eq!(it.size_hint(), (3, Some(3))); assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.size_hint(), (Some(2), Some(2))); + assert_eq!(it.size_hint(), (2, Some(2))); assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.size_hint(), (Some(1), Some(1))); + assert_eq!(it.size_hint(), (1, Some(1))); assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.size_hint(), (Some(0), Some(0))); + assert_eq!(it.size_hint(), (0, Some(0))); assert!(it.next().is_none()); } #[test] + fn test_iter_size_hints() { + use iterator::*; + let mut xs = [1, 2, 5, 10, 11]; + assert_eq!(xs.iter().size_hint(), (5, Some(5))); + assert_eq!(xs.rev_iter().size_hint(), (5, Some(5))); + assert_eq!(xs.mut_iter().size_hint(), (5, Some(5))); + assert_eq!(xs.mut_rev_iter().size_hint(), (5, Some(5))); + } + + #[test] fn test_mut_iterator() { use iterator::*; let mut xs = [1, 2, 3, 4, 5]; @@ -3422,6 +3054,120 @@ mod tests { } #[test] + fn test_consume_iterator() { + use iterator::*; + let xs = ~[1u,2,3,4,5]; + assert_eq!(xs.consume_iter().fold(0, |a: uint, b: uint| 10*a + b), 12345); + } + + #[test] + fn test_consume_rev_iterator() { + use iterator::*; + let xs = ~[1u,2,3,4,5]; + assert_eq!(xs.consume_rev_iter().fold(0, |a: uint, b: uint| 10*a + b), 54321); + } + + #[test] + fn test_split_iterator() { + let xs = &[1i,2,3,4,5]; + + assert_eq!(xs.split_iter(|x| *x % 2 == 0).collect::<~[&[int]]>(), + ~[&[1], &[3], &[5]]); + assert_eq!(xs.split_iter(|x| *x == 1).collect::<~[&[int]]>(), + ~[&[], &[2,3,4,5]]); + assert_eq!(xs.split_iter(|x| *x == 5).collect::<~[&[int]]>(), + ~[&[1,2,3,4], &[]]); + assert_eq!(xs.split_iter(|x| *x == 10).collect::<~[&[int]]>(), + ~[&[1,2,3,4,5]]); + assert_eq!(xs.split_iter(|_| true).collect::<~[&[int]]>(), + ~[&[], &[], &[], &[], &[], &[]]); + + let xs: &[int] = &[]; + assert_eq!(xs.split_iter(|x| *x == 5).collect::<~[&[int]]>(), ~[&[]]); + } + + #[test] + fn test_splitn_iterator() { + let xs = &[1i,2,3,4,5]; + + assert_eq!(xs.splitn_iter(0, |x| *x % 2 == 0).collect::<~[&[int]]>(), + ~[&[1,2,3,4,5]]); + assert_eq!(xs.splitn_iter(1, |x| *x % 2 == 0).collect::<~[&[int]]>(), + ~[&[1], &[3,4,5]]); + assert_eq!(xs.splitn_iter(3, |_| true).collect::<~[&[int]]>(), + ~[&[], &[], &[], &[4,5]]); + + let xs: &[int] = &[]; + assert_eq!(xs.splitn_iter(1, |x| *x == 5).collect::<~[&[int]]>(), ~[&[]]); + } + + #[test] + fn test_rsplit_iterator() { + let xs = &[1i,2,3,4,5]; + + assert_eq!(xs.rsplit_iter(|x| *x % 2 == 0).collect::<~[&[int]]>(), + ~[&[5], &[3], &[1]]); + assert_eq!(xs.rsplit_iter(|x| *x == 1).collect::<~[&[int]]>(), + ~[&[2,3,4,5], &[]]); + assert_eq!(xs.rsplit_iter(|x| *x == 5).collect::<~[&[int]]>(), + ~[&[], &[1,2,3,4]]); + assert_eq!(xs.rsplit_iter(|x| *x == 10).collect::<~[&[int]]>(), + ~[&[1,2,3,4,5]]); + + let xs: &[int] = &[]; + assert_eq!(xs.rsplit_iter(|x| *x == 5).collect::<~[&[int]]>(), ~[&[]]); + } + + #[test] + fn test_rsplitn_iterator() { + let xs = &[1,2,3,4,5]; + + assert_eq!(xs.rsplitn_iter(0, |x| *x % 2 == 0).collect::<~[&[int]]>(), + ~[&[1,2,3,4,5]]); + assert_eq!(xs.rsplitn_iter(1, |x| *x % 2 == 0).collect::<~[&[int]]>(), + ~[&[5], &[1,2,3]]); + assert_eq!(xs.rsplitn_iter(3, |_| true).collect::<~[&[int]]>(), + ~[&[], &[], &[], &[1,2]]); + + let xs: &[int] = &[]; + assert_eq!(xs.rsplitn_iter(1, |x| *x == 5).collect::<~[&[int]]>(), ~[&[]]); + } + + #[test] + fn test_window_iterator() { + let v = &[1i,2,3,4]; + + assert_eq!(v.window_iter(2).collect::<~[&[int]]>(), ~[&[1,2], &[2,3], &[3,4]]); + assert_eq!(v.window_iter(3).collect::<~[&[int]]>(), ~[&[1i,2,3], &[2,3,4]]); + assert!(v.window_iter(6).next().is_none()); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_window_iterator_0() { + let v = &[1i,2,3,4]; + let _it = v.window_iter(0); + } + + #[test] + fn test_chunk_iterator() { + let v = &[1i,2,3,4,5]; + + 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]]); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_chunk_iterator_0() { + let v = &[1i,2,3,4]; + let _it = v.chunk_iter(0); + } + + #[test] fn test_move_from() { let mut a = [1,2,3,4,5]; let b = ~[6,7,8]; |
