diff options
204 files changed, 18502 insertions, 11431 deletions
diff --git a/configure b/configure index 73e09158539..fdc28eee8c8 100755 --- a/configure +++ b/configure @@ -461,7 +461,10 @@ case $CFG_CPUTYPE in CFG_CPUTYPE=aarch64 ;; - powerpc) + # At some point, when ppc64[le] support happens, this will need to do + # something clever. For now it's safe to assume that we're only ever + # interested in building 32 bit. + powerpc | ppc | ppc64) CFG_CPUTYPE=powerpc ;; @@ -823,11 +826,11 @@ then LLVM_VERSION=$($LLVM_CONFIG --version) case $LLVM_VERSION in - (3.[2-6]*) + (3.[5-6]*) msg "found ok version of LLVM: $LLVM_VERSION" ;; (*) - err "bad LLVM version: $LLVM_VERSION, need >=3.0svn" + err "bad LLVM version: $LLVM_VERSION, need >=3.5" ;; esac fi diff --git a/mk/dist.mk b/mk/dist.mk index 831225556f3..57adaee5198 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -53,6 +53,7 @@ PKG_FILES := \ driver \ etc \ $(foreach crate,$(CRATES),lib$(crate)) \ + libcollectionstest \ libcoretest \ libbacktrace \ rt \ diff --git a/mk/main.mk b/mk/main.mk index ad9d0d0ca5e..b9f2cf1cce8 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -290,6 +290,7 @@ LLVM_VERSION_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --version) LLVM_BINDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --bindir) LLVM_INCDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --includedir) LLVM_LIBDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libdir) +LLVM_LIBDIR_RUSTFLAGS_$(1)=-L "$$(LLVM_LIBDIR_$(1))" LLVM_LIBS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libs $$(LLVM_COMPONENTS)) LLVM_LDFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --ldflags) # On FreeBSD, it may search wrong headers (that are for pre-installed LLVM), diff --git a/mk/target.mk b/mk/target.mk index 4182ec81a7e..da18a9a4392 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -72,6 +72,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): CFG_COMPILER_HOST_TRIPLE = $(2) $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ $$(CRATEFILE_$(4)) \ $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ + $$(LLVM_CONFIG_$(2)) \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ | $$(TLIB$(1)_T_$(2)_H_$(3))/ @$$(call E, rustc: $$(@D)/lib$(4)) @@ -84,7 +85,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) \ $$(RUST_LIB_FLAGS_ST$(1)) \ -L "$$(RT_OUTPUT_DIR_$(2))" \ - -L "$$(LLVM_LIBDIR_$(2))" \ + $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ $$(LLVM_STDCPP_RUSTFLAGS_$(2)) \ $$(RUSTFLAGS_$(4)) \ --out-dir $$(@D) \ diff --git a/mk/tests.mk b/mk/tests.mk index 78f5ac11f06..2fb33eb7db8 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -19,7 +19,10 @@ DEPS_coretest := $(eval $(call RUST_CRATE,coretest)) -TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) coretest +DEPS_collectionstest := +$(eval $(call RUST_CRATE,collectionstest)) + +TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) collectionstest coretest TEST_DOC_CRATES = $(DOC_CRATES) TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\ $(HOST_CRATES)) @@ -372,7 +375,7 @@ $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): \ $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(3)) \ $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) -o $$@ $$< --test \ -L "$$(RT_OUTPUT_DIR_$(2))" \ - -L "$$(LLVM_LIBDIR_$(2))" \ + $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ $$(RUSTFLAGS_$(4)) endef diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 50e74a13ee2..5ef93cb569e 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -20,7 +20,6 @@ #![feature(std_misc)] #![feature(test)] #![feature(core)] -#![feature(net)] #![feature(path_ext)] #![deny(warnings)] diff --git a/src/doc/intro.md b/src/doc/intro.md index 9e575abeee2..51280e58854 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -140,7 +140,7 @@ right at home if you've used tools like [Bundler](http://bundler.io/), [npm](https://www.npmjs.org/), or [pip](https://pip.pypa.io/en/latest/). There's no `Makefile`s or endless `autotools` output here. (Rust's tooling does [play nice with external libraries written in those -tools](http://crates.io/native-build.html), if you need to.) +tools](http://doc.crates.io/build-script.html), if you need to.) Enough about tools, let's talk code! diff --git a/src/doc/reference.md b/src/doc/reference.md index c4c122463a7..3fae49bfc6d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1961,16 +1961,18 @@ module through the rules above. It essentially allows public access into the re-exported item. For example, this program is valid: ``` -pub use self::implementation as api; +pub use self::implementation::api; mod implementation { - pub fn f() {} + pub mod api { + pub fn f() {} + } } # fn main() {} ``` -This means that any external crate referencing `implementation::f` would +This means that any external crate referencing `implementation::api::f` would receive a privacy violation, while the path `api::f` would be allowed. When re-exporting a private item, it can be thought of as allowing the "privacy diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index 8cc6be7387c..bf4c2d90357 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -68,7 +68,7 @@ is that a moving closure always takes ownership of all variables that it uses. Ordinary closures, in contrast, just create a reference into the enclosing stack frame. Moving closures are most useful with Rust's concurrency features, and so we'll just leave it at this for -now. We'll talk about them more in the "Threads" section of the guide. +now. We'll talk about them more in the "Concurrency" chapter of the book. ## Accepting closures as arguments diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 9b6d6ca67f6..4a16db63950 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -339,7 +339,7 @@ fn main() { }); } - rx.recv().ok().expect("Could not recieve answer"); + rx.recv().ok().expect("Could not receive answer"); } ``` diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index 0625d649e30..59be8c6704f 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -187,13 +187,13 @@ impl CircleBuilder { } fn coordinate(&mut self, coordinate: f64) -> &mut CircleBuilder { - self.coordinate = coordinate; - self + self.coordinate = coordinate; + self } fn radius(&mut self, radius: f64) -> &mut CircleBuilder { - self.radius = radius; - self + self.radius = radius; + self } fn finalize(&self) -> Circle { diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index f9936b7a16a..25c6bda5f39 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[cfg(stage0)] #[cfg(not(test))] use core::ptr::PtrExt; @@ -387,7 +388,6 @@ mod imp { mod test { extern crate test; use self::test::Bencher; - use core::ptr::PtrExt; use boxed::Box; use heap; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 115acd4a0ef..3692149db44 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -159,7 +159,10 @@ use core::nonzero::NonZero; use core::ops::{Deref, Drop}; use core::option::Option; use core::option::Option::{Some, None}; +#[cfg(stage0)] use core::ptr::{self, PtrExt}; +#[cfg(not(stage0))] +use core::ptr; use core::result::Result; use core::result::Result::{Ok, Err}; use core::intrinsics::assume; diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index d08c9b3257a..029d9d03835 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -46,6 +46,7 @@ use std::intrinsics::{TyDesc, get_tydesc}; use std::intrinsics; use std::marker; use std::mem; +#[cfg(stage0)] use std::num::{Int, UnsignedInt}; use std::ptr; use std::rc::Rc; diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 2e575ddb00a..11c8656c994 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -163,6 +163,11 @@ use vec::{self, Vec}; /// A priority queue implemented with a binary heap. /// /// This will be a max-heap. +/// +/// It is a logic error for an item to be modified in such a way that the +/// item's ordering relative to any other item, as determined by the `Ord` +/// trait, changes while it is in the heap. This is normally only possible +/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BinaryHeap<T> { @@ -688,218 +693,3 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - - use super::BinaryHeap; - - #[test] - fn test_iterator() { - let data = vec![5, 9, 3]; - let iterout = [9, 5, 3]; - let heap = BinaryHeap::from_vec(data); - let mut i = 0; - for el in &heap { - assert_eq!(*el, iterout[i]); - i += 1; - } - } - - #[test] - fn test_iterator_reverse() { - let data = vec![5, 9, 3]; - let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from_vec(data); - - let v: Vec<_> = pq.iter().rev().cloned().collect(); - assert_eq!(v, iterout); - } - - #[test] - fn test_move_iter() { - let data = vec![5, 9, 3]; - let iterout = vec![9, 5, 3]; - let pq = BinaryHeap::from_vec(data); - - let v: Vec<_> = pq.into_iter().collect(); - assert_eq!(v, iterout); - } - - #[test] - fn test_move_iter_size_hint() { - let data = vec![5, 9]; - let pq = BinaryHeap::from_vec(data); - - let mut it = pq.into_iter(); - - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next(), Some(9)); - - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next(), Some(5)); - - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_move_iter_reverse() { - let data = vec![5, 9, 3]; - let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from_vec(data); - - let v: Vec<_> = pq.into_iter().rev().collect(); - assert_eq!(v, iterout); - } - - #[test] - fn test_peek_and_pop() { - let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; - let mut sorted = data.clone(); - sorted.sort(); - let mut heap = BinaryHeap::from_vec(data); - while !heap.is_empty() { - assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); - assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); - } - } - - #[test] - fn test_push() { - let mut heap = BinaryHeap::from_vec(vec![2, 4, 9]); - assert_eq!(heap.len(), 3); - assert!(*heap.peek().unwrap() == 9); - heap.push(11); - assert_eq!(heap.len(), 4); - assert!(*heap.peek().unwrap() == 11); - heap.push(5); - assert_eq!(heap.len(), 5); - assert!(*heap.peek().unwrap() == 11); - heap.push(27); - assert_eq!(heap.len(), 6); - assert!(*heap.peek().unwrap() == 27); - heap.push(3); - assert_eq!(heap.len(), 7); - assert!(*heap.peek().unwrap() == 27); - heap.push(103); - assert_eq!(heap.len(), 8); - assert!(*heap.peek().unwrap() == 103); - } - - #[test] - fn test_push_unique() { - let mut heap = BinaryHeap::<Box<_>>::from_vec(vec![box 2, box 4, box 9]); - assert_eq!(heap.len(), 3); - assert!(*heap.peek().unwrap() == box 9); - heap.push(box 11); - assert_eq!(heap.len(), 4); - assert!(*heap.peek().unwrap() == box 11); - heap.push(box 5); - assert_eq!(heap.len(), 5); - assert!(*heap.peek().unwrap() == box 11); - heap.push(box 27); - assert_eq!(heap.len(), 6); - assert!(*heap.peek().unwrap() == box 27); - heap.push(box 3); - assert_eq!(heap.len(), 7); - assert!(*heap.peek().unwrap() == box 27); - heap.push(box 103); - assert_eq!(heap.len(), 8); - assert!(*heap.peek().unwrap() == box 103); - } - - #[test] - fn test_push_pop() { - let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(6), 6); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(0), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(4), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(1), 4); - assert_eq!(heap.len(), 5); - } - - #[test] - fn test_replace() { - let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(6).unwrap(), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(0).unwrap(), 6); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(4).unwrap(), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(1).unwrap(), 4); - assert_eq!(heap.len(), 5); - } - - fn check_to_vec(mut data: Vec<i32>) { - let heap = BinaryHeap::from_vec(data.clone()); - let mut v = heap.clone().into_vec(); - v.sort(); - data.sort(); - - assert_eq!(v, data); - assert_eq!(heap.into_sorted_vec(), data); - } - - #[test] - fn test_to_vec() { - check_to_vec(vec![]); - check_to_vec(vec![5]); - check_to_vec(vec![3, 2]); - check_to_vec(vec![2, 3]); - check_to_vec(vec![5, 1, 2]); - check_to_vec(vec![1, 100, 2, 3]); - check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); - check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); - check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); - check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); - check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); - check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); - } - - #[test] - fn test_empty_pop() { - let mut heap = BinaryHeap::<i32>::new(); - assert!(heap.pop().is_none()); - } - - #[test] - fn test_empty_peek() { - let empty = BinaryHeap::<i32>::new(); - assert!(empty.peek().is_none()); - } - - #[test] - fn test_empty_replace() { - let mut heap = BinaryHeap::new(); - assert!(heap.replace(5).is_none()); - } - - #[test] - fn test_from_iter() { - let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; - - let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); - - for &x in &xs { - assert_eq!(q.pop().unwrap(), x); - } - } - - #[test] - fn test_drain() { - let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); - - assert_eq!(q.drain().take(5).count(), 5); - - assert!(q.is_empty()); - } -} diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 500322ab243..90fbe04d348 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -1903,1183 +1903,3 @@ impl<'a> IntoIterator for &'a BitSet { self.iter() } } - -#[cfg(test)] -mod tests { - use prelude::*; - use core::u32; - - use super::BitVec; - - #[test] - fn test_to_str() { - let zerolen = BitVec::new(); - assert_eq!(format!("{:?}", zerolen), ""); - - let eightbits = BitVec::from_elem(8, false); - assert_eq!(format!("{:?}", eightbits), "00000000") - } - - #[test] - fn test_0_elements() { - let act = BitVec::new(); - let exp = Vec::new(); - assert!(act.eq_vec(&exp)); - assert!(act.none() && act.all()); - } - - #[test] - fn test_1_element() { - let mut act = BitVec::from_elem(1, false); - assert!(act.eq_vec(&[false])); - assert!(act.none() && !act.all()); - act = BitVec::from_elem(1, true); - assert!(act.eq_vec(&[true])); - assert!(!act.none() && act.all()); - } - - #[test] - fn test_2_elements() { - let mut b = BitVec::from_elem(2, false); - b.set(0, true); - b.set(1, false); - assert_eq!(format!("{:?}", b), "10"); - assert!(!b.none() && !b.all()); - } - - #[test] - fn test_10_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(10, false); - assert!((act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false]))); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(10, true); - assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(5, true); - act.set(6, true); - act.set(7, true); - act.set(8, true); - act.set(9, true); - assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(0, true); - act.set(3, true); - act.set(6, true); - act.set(9, true); - assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true]))); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_31_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(31, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(31, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_32_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(32, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(32, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true, true])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_33_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(33, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(33, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true, true, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - act.set(31, true); - act.set(32, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_equal_differing_sizes() { - let v0 = BitVec::from_elem(10, false); - let v1 = BitVec::from_elem(11, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_greatly_differing_sizes() { - let v0 = BitVec::from_elem(10, false); - let v1 = BitVec::from_elem(110, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_sneaky_small() { - let mut a = BitVec::from_elem(1, false); - a.set(0, true); - - let mut b = BitVec::from_elem(1, true); - b.set(0, true); - - assert_eq!(a, b); - } - - #[test] - fn test_equal_sneaky_big() { - let mut a = BitVec::from_elem(100, false); - for i in 0..100 { - a.set(i, true); - } - - let mut b = BitVec::from_elem(100, true); - for i in 0..100 { - b.set(i, true); - } - - assert_eq!(a, b); - } - - #[test] - fn test_from_bytes() { - let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); - let str = concat!("10110110", "00000000", "11111111"); - assert_eq!(format!("{:?}", bit_vec), str); - } - - #[test] - fn test_to_bytes() { - let mut bv = BitVec::from_elem(3, true); - bv.set(1, false); - assert_eq!(bv.to_bytes(), [0b10100000]); - - let mut bv = BitVec::from_elem(9, false); - bv.set(2, true); - bv.set(8, true); - assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); - } - - #[test] - fn test_from_bools() { - let bools = vec![true, false, true, true]; - let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); - assert_eq!(format!("{:?}", bit_vec), "1011"); - } - - #[test] - fn test_to_bools() { - let bools = vec![false, false, true, false, false, true, true, false]; - assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::<Vec<bool>>(), bools); - } - - #[test] - fn test_bit_vec_iterator() { - let bools = vec![true, false, true, true]; - let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); - - assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), bools); - - let long: Vec<_> = (0..10000).map(|i| i % 2 == 0).collect(); - let bit_vec: BitVec = long.iter().map(|n| *n).collect(); - assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), long) - } - - #[test] - fn test_small_difference() { - let mut b1 = BitVec::from_elem(3, false); - let mut b2 = BitVec::from_elem(3, false); - b1.set(0, true); - b1.set(1, true); - b2.set(1, true); - b2.set(2, true); - assert!(b1.difference(&b2)); - assert!(b1[0]); - assert!(!b1[1]); - assert!(!b1[2]); - } - - #[test] - fn test_big_difference() { - let mut b1 = BitVec::from_elem(100, false); - let mut b2 = BitVec::from_elem(100, false); - b1.set(0, true); - b1.set(40, true); - b2.set(40, true); - b2.set(80, true); - assert!(b1.difference(&b2)); - assert!(b1[0]); - assert!(!b1[40]); - assert!(!b1[80]); - } - - #[test] - fn test_small_clear() { - let mut b = BitVec::from_elem(14, true); - assert!(!b.none() && b.all()); - b.clear(); - assert!(b.none() && !b.all()); - } - - #[test] - fn test_big_clear() { - let mut b = BitVec::from_elem(140, true); - assert!(!b.none() && b.all()); - b.clear(); - assert!(b.none() && !b.all()); - } - - #[test] - fn test_bit_vec_lt() { - let mut a = BitVec::from_elem(5, false); - let mut b = BitVec::from_elem(5, false); - - assert!(!(a < b) && !(b < a)); - b.set(2, true); - assert!(a < b); - a.set(3, true); - assert!(a < b); - a.set(2, true); - assert!(!(a < b) && b < a); - b.set(0, true); - assert!(a < b); - } - - #[test] - fn test_ord() { - let mut a = BitVec::from_elem(5, false); - let mut b = BitVec::from_elem(5, false); - - assert!(a <= b && a >= b); - a.set(1, true); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - b.set(1, true); - b.set(2, true); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - - #[test] - fn test_small_bit_vec_tests() { - let v = BitVec::from_bytes(&[0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = BitVec::from_bytes(&[0b00010100]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = BitVec::from_bytes(&[0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_big_bit_vec_tests() { - let v = BitVec::from_bytes(&[ // 88 bits - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = BitVec::from_bytes(&[ // 88 bits - 0, 0, 0b00010100, 0, - 0, 0, 0, 0b00110100, - 0, 0, 0]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = BitVec::from_bytes(&[ // 88 bits - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_bit_vec_push_pop() { - let mut s = BitVec::from_elem(5 * u32::BITS as usize - 2, false); - assert_eq!(s.len(), 5 * u32::BITS as usize - 2); - assert_eq!(s[5 * u32::BITS as usize - 3], false); - s.push(true); - s.push(true); - assert_eq!(s[5 * u32::BITS as usize - 2], true); - assert_eq!(s[5 * u32::BITS as usize - 1], true); - // Here the internal vector will need to be extended - s.push(false); - assert_eq!(s[5 * u32::BITS as usize], false); - s.push(false); - assert_eq!(s[5 * u32::BITS as usize + 1], false); - assert_eq!(s.len(), 5 * u32::BITS as usize + 2); - // Pop it all off - assert_eq!(s.pop(), Some(false)); - assert_eq!(s.pop(), Some(false)); - assert_eq!(s.pop(), Some(true)); - assert_eq!(s.pop(), Some(true)); - assert_eq!(s.len(), 5 * u32::BITS as usize - 2); - } - - #[test] - fn test_bit_vec_truncate() { - let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); - - assert_eq!(s, BitVec::from_elem(5 * u32::BITS as usize, true)); - assert_eq!(s.len(), 5 * u32::BITS as usize); - s.truncate(4 * u32::BITS as usize); - assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); - assert_eq!(s.len(), 4 * u32::BITS as usize); - // Truncating to a size > s.len() should be a noop - s.truncate(5 * u32::BITS as usize); - assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); - assert_eq!(s.len(), 4 * u32::BITS as usize); - s.truncate(3 * u32::BITS as usize - 10); - assert_eq!(s, BitVec::from_elem(3 * u32::BITS as usize - 10, true)); - assert_eq!(s.len(), 3 * u32::BITS as usize - 10); - s.truncate(0); - assert_eq!(s, BitVec::from_elem(0, true)); - assert_eq!(s.len(), 0); - } - - #[test] - fn test_bit_vec_reserve() { - let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); - // Check capacity - assert!(s.capacity() >= 5 * u32::BITS as usize); - s.reserve(2 * u32::BITS as usize); - assert!(s.capacity() >= 7 * u32::BITS as usize); - s.reserve(7 * u32::BITS as usize); - assert!(s.capacity() >= 12 * u32::BITS as usize); - s.reserve_exact(7 * u32::BITS as usize); - assert!(s.capacity() >= 12 * u32::BITS as usize); - s.reserve(7 * u32::BITS as usize + 1); - assert!(s.capacity() >= 12 * u32::BITS as usize + 1); - // Check that length hasn't changed - assert_eq!(s.len(), 5 * u32::BITS as usize); - s.push(true); - s.push(false); - s.push(true); - assert_eq!(s[5 * u32::BITS as usize - 1], true); - assert_eq!(s[5 * u32::BITS as usize - 0], true); - assert_eq!(s[5 * u32::BITS as usize + 1], false); - assert_eq!(s[5 * u32::BITS as usize + 2], true); - } - - #[test] - fn test_bit_vec_grow() { - let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]); - bit_vec.grow(32, true); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF])); - bit_vec.grow(64, false); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); - bit_vec.grow(16, true); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); - } - - #[test] - fn test_bit_vec_extend() { - let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); - let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]); - bit_vec.extend(ext.iter()); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111, - 0b01001001, 0b10010010, 0b10111101])); - } -} - - - - -#[cfg(test)] -mod bit_vec_bench { - use std::prelude::v1::*; - use std::rand; - use std::rand::Rng; - use std::u32; - use test::{Bencher, black_box}; - - use super::BitVec; - - const BENCH_BITS : usize = 1 << 14; - - fn rng() -> rand::IsaacRng { - let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::SeedableRng::from_seed(seed) - } - - #[bench] - fn bench_usize_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = 0 as usize; - b.iter(|| { - for _ in 0..100 { - bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS as usize); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_big_fixed(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_big_variable(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen()); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(u32::BITS as usize, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % u32::BITS as usize, true); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vec_big_union(b: &mut Bencher) { - let mut b1 = BitVec::from_elem(BENCH_BITS, false); - let b2 = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - b1.union(&b2) - }) - } - - #[bench] - fn bench_bit_vec_small_iter(b: &mut Bencher) { - let bit_vec = BitVec::from_elem(u32::BITS as usize, false); - b.iter(|| { - let mut sum = 0; - for _ in 0..10 { - for pres in &bit_vec { - sum += pres as usize; - } - } - sum - }) - } - - #[bench] - fn bench_bit_vec_big_iter(b: &mut Bencher) { - let bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - let mut sum = 0; - for pres in &bit_vec { - sum += pres as usize; - } - sum - }) - } -} - - - - - - - -#[cfg(test)] -mod bit_set_test { - use prelude::*; - use std::iter::range_step; - - use super::{BitVec, BitSet}; - - #[test] - fn test_bit_set_show() { - let mut s = BitSet::new(); - s.insert(1); - s.insert(10); - s.insert(50); - s.insert(2); - assert_eq!("{1, 2, 10, 50}", format!("{:?}", s)); - } - - #[test] - fn test_bit_set_from_usizes() { - let usizes = vec![0, 2, 2, 3]; - let a: BitSet = usizes.into_iter().collect(); - let mut b = BitSet::new(); - b.insert(0); - b.insert(2); - b.insert(3); - assert_eq!(a, b); - } - - #[test] - fn test_bit_set_iterator() { - let usizes = vec![0, 2, 2, 3]; - let bit_vec: BitSet = usizes.into_iter().collect(); - - let idxs: Vec<_> = bit_vec.iter().collect(); - assert_eq!(idxs, [0, 2, 3]); - - let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); - let real: Vec<_> = range_step(0, 10000, 2).collect(); - - let idxs: Vec<_> = long.iter().collect(); - assert_eq!(idxs, real); - } - - #[test] - fn test_bit_set_frombit_vec_init() { - let bools = [true, false]; - let lengths = [10, 64, 100]; - for &b in &bools { - for &l in &lengths { - let bitset = BitSet::from_bit_vec(BitVec::from_elem(l, b)); - assert_eq!(bitset.contains(&1), b); - assert_eq!(bitset.contains(&(l-1)), b); - assert!(!bitset.contains(&l)); - } - } - } - - #[test] - fn test_bit_vec_masking() { - let b = BitVec::from_elem(140, true); - let mut bs = BitSet::from_bit_vec(b); - assert!(bs.contains(&139)); - assert!(!bs.contains(&140)); - assert!(bs.insert(150)); - assert!(!bs.contains(&140)); - assert!(!bs.contains(&149)); - assert!(bs.contains(&150)); - assert!(!bs.contains(&151)); - } - - #[test] - fn test_bit_set_basic() { - let mut b = BitSet::new(); - assert!(b.insert(3)); - assert!(!b.insert(3)); - assert!(b.contains(&3)); - assert!(b.insert(4)); - assert!(!b.insert(4)); - assert!(b.contains(&3)); - assert!(b.insert(400)); - assert!(!b.insert(400)); - assert!(b.contains(&400)); - assert_eq!(b.len(), 3); - } - - #[test] - fn test_bit_set_intersection() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let expected = [3, 5, 11, 77]; - let actual: Vec<_> = a.intersection(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_difference() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(200)); - assert!(a.insert(500)); - - assert!(b.insert(3)); - assert!(b.insert(200)); - - let expected = [1, 5, 500]; - let actual: Vec<_> = a.difference(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_symmetric_difference() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(220)); - - let expected = [1, 5, 11, 14, 220]; - let actual: Vec<_> = a.symmetric_difference(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_union() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(160)); - assert!(a.insert(19)); - assert!(a.insert(24)); - assert!(a.insert(200)); - - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; - let actual: Vec<_> = a.union(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_subset() { - let mut set1 = BitSet::new(); - let mut set2 = BitSet::new(); - - assert!(set1.is_subset(&set2)); // {} {} - set2.insert(100); - assert!(set1.is_subset(&set2)); // {} { 1 } - set2.insert(200); - assert!(set1.is_subset(&set2)); // {} { 1, 2 } - set1.insert(200); - assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } - set1.insert(300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } - set2.insert(300); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } - set2.insert(400); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } - set2.remove(&100); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } - set2.remove(&300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } - set1.remove(&300); - assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } - } - - #[test] - fn test_bit_set_is_disjoint() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01000000])); - let c = BitSet::new(); - let d = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00110000])); - - assert!(!a.is_disjoint(&d)); - assert!(!d.is_disjoint(&a)); - - assert!(a.is_disjoint(&b)); - assert!(a.is_disjoint(&c)); - assert!(b.is_disjoint(&a)); - assert!(b.is_disjoint(&c)); - assert!(c.is_disjoint(&a)); - assert!(c.is_disjoint(&b)); - } - - #[test] - fn test_bit_set_union_with() { - //a should grow to include larger elements - let mut a = BitSet::new(); - a.insert(0); - let mut b = BitSet::new(); - b.insert(5); - let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); - a.union_with(&b); - assert_eq!(a, expected); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.union_with(&b); - b.union_with(&c); - assert_eq!(a.len(), 4); - assert_eq!(b.len(), 4); - } - - #[test] - fn test_bit_set_intersect_with() { - // Explicitly 0'ed bits - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::new(); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bit_set_difference_with() { - // Explicitly 0'ed bits - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitSet::new(); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11111111])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.difference_with(&b); - b.difference_with(&c); - assert_eq!(a.len(), 1); - assert_eq!(b.len(), 1); - } - - #[test] - fn test_bit_set_symmetric_difference_with() { - //a should grow to include larger elements - let mut a = BitSet::new(); - a.insert(0); - a.insert(1); - let mut b = BitSet::new(); - b.insert(1); - b.insert(5); - let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); - a.symmetric_difference_with(&b); - assert_eq!(a, expected); - - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::new(); - let c = a.clone(); - a.symmetric_difference_with(&b); - assert_eq!(a, c); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101010])); - let c = a.clone(); - a.symmetric_difference_with(&b); - b.symmetric_difference_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bit_set_eq() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = BitSet::new(); - - assert!(a == a); - assert!(a != b); - assert!(a != c); - assert!(b == b); - assert!(b == c); - assert!(c == c); - } - - #[test] - fn test_bit_set_cmp() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = BitSet::new(); - - assert_eq!(a.cmp(&b), Greater); - assert_eq!(a.cmp(&c), Greater); - assert_eq!(b.cmp(&a), Less); - assert_eq!(b.cmp(&c), Equal); - assert_eq!(c.cmp(&a), Less); - assert_eq!(c.cmp(&b), Equal); - } - - #[test] - fn test_bit_vec_remove() { - let mut a = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.remove(&1)); - - assert!(a.insert(100)); - assert!(a.remove(&100)); - - assert!(a.insert(1000)); - assert!(a.remove(&1000)); - a.shrink_to_fit(); - } - - #[test] - fn test_bit_vec_clone() { - let mut a = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(100)); - assert!(a.insert(1000)); - - let mut b = a.clone(); - - assert!(a == b); - - assert!(b.remove(&1)); - assert!(a.contains(&1)); - - assert!(a.remove(&1000)); - assert!(b.contains(&1000)); - } -} - - - - - -#[cfg(test)] -mod bit_set_bench { - use std::prelude::v1::*; - use std::rand; - use std::rand::Rng; - use std::u32; - use test::{Bencher, black_box}; - - use super::{BitVec, BitSet}; - - const BENCH_BITS : usize = 1 << 14; - - fn rng() -> rand::IsaacRng { - let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::SeedableRng::from_seed(seed) - } - - #[bench] - fn bench_bit_vecset_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitSet::new(); - b.iter(|| { - for _ in 0..100 { - bit_vec.insert((r.next_u32() as usize) % u32::BITS as usize); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vecset_big(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitSet::new(); - b.iter(|| { - for _ in 0..100 { - bit_vec.insert((r.next_u32() as usize) % BENCH_BITS); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vecset_iter(b: &mut Bencher) { - let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, - |idx| {idx % 3 == 0})); - b.iter(|| { - let mut sum = 0; - for idx in &bit_vec { - sum += idx as usize; - } - sum - }) - } -} diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 5de6cbe61e9..c7e1e3c9176 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -64,6 +64,10 @@ use super::node::{self, Node, Found, GoDown}; /// and possibly other factors. Using linear search, searching for a random element is expected /// to take O(B log<sub>B</sub>n) comparisons, which is generally worse than a BST. In practice, /// however, performance is excellent. +/// +/// It is a logic error for a key to be modified in such a way that the key's ordering relative to +/// any other key, as determined by the `Ord` trait, changes while it is in the map. This is +/// normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BTreeMap<K, V> { @@ -1595,309 +1599,3 @@ impl<K: Ord, V> BTreeMap<K, V> { } } } - - - - - -#[cfg(test)] -mod test { - use prelude::*; - use std::iter::range_inclusive; - - use super::BTreeMap; - use super::Entry::{Occupied, Vacant}; - use Bound::{self, Included, Excluded, Unbounded}; - - #[test] - fn test_basic_large() { - let mut map = BTreeMap::new(); - let size = 10000; - assert_eq!(map.len(), 0); - - for i in 0..size { - assert_eq!(map.insert(i, 10*i), None); - assert_eq!(map.len(), i + 1); - } - - for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i*10)); - } - - for i in size..size*2 { - assert_eq!(map.get(&i), None); - } - - for i in 0..size { - assert_eq!(map.insert(i, 100*i), Some(10*i)); - assert_eq!(map.len(), size); - } - - for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i*100)); - } - - for i in 0..size/2 { - assert_eq!(map.remove(&(i*2)), Some(i*200)); - assert_eq!(map.len(), size - i - 1); - } - - for i in 0..size/2 { - assert_eq!(map.get(&(2*i)), None); - assert_eq!(map.get(&(2*i+1)).unwrap(), &(i*200 + 100)); - } - - for i in 0..size/2 { - assert_eq!(map.remove(&(2*i)), None); - assert_eq!(map.remove(&(2*i+1)), Some(i*200 + 100)); - assert_eq!(map.len(), size/2 - i - 1); - } - } - - #[test] - fn test_basic_small() { - let mut map = BTreeMap::new(); - assert_eq!(map.remove(&1), None); - assert_eq!(map.get(&1), None); - assert_eq!(map.insert(1, 1), None); - assert_eq!(map.get(&1), Some(&1)); - assert_eq!(map.insert(1, 2), Some(1)); - assert_eq!(map.get(&1), Some(&2)); - assert_eq!(map.insert(2, 4), None); - assert_eq!(map.get(&2), Some(&4)); - assert_eq!(map.remove(&1), Some(2)); - assert_eq!(map.remove(&2), Some(4)); - assert_eq!(map.remove(&1), None); - } - - #[test] - fn test_iter() { - let size = 10000; - - // Forwards - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test<T>(size: usize, mut iter: T) where T: Iterator<Item=(usize, usize)> { - for i in 0..size { - assert_eq!(iter.size_hint(), (size - i, Some(size - i))); - assert_eq!(iter.next().unwrap(), (i, i)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter()); - } - - #[test] - fn test_iter_rev() { - let size = 10000; - - // Forwards - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test<T>(size: usize, mut iter: T) where T: Iterator<Item=(usize, usize)> { - for i in 0..size { - assert_eq!(iter.size_hint(), (size - i, Some(size - i))); - assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().rev().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter().rev()); - } - - #[test] - fn test_iter_mixed() { - let size = 10000; - - // Forwards - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test<T>(size: usize, mut iter: T) - where T: Iterator<Item=(usize, usize)> + DoubleEndedIterator { - for i in 0..size / 4 { - assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); - assert_eq!(iter.next().unwrap(), (i, i)); - assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1)); - } - for i in size / 4..size * 3 / 4 { - assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i))); - assert_eq!(iter.next().unwrap(), (i, i)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter()); - } - - #[test] - fn test_range_small() { - let size = 5; - - // Forwards - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - let mut j = 0; - for ((&k, &v), i) in map.range(Included(&2), Unbounded).zip(2..size) { - assert_eq!(k, i); - assert_eq!(v, i); - j += 1; - } - assert_eq!(j, size - 2); - } - - #[test] - fn test_range_1000() { - let size = 1000; - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) { - let mut kvs = map.range(min, max).map(|(&k, &v)| (k, v)); - let mut pairs = (0..size).map(|i| (i, i)); - - for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { - assert_eq!(kv, pair); - } - assert_eq!(kvs.next(), None); - assert_eq!(pairs.next(), None); - } - test(&map, size, Included(&0), Excluded(&size)); - test(&map, size, Unbounded, Excluded(&size)); - test(&map, size, Included(&0), Included(&(size - 1))); - test(&map, size, Unbounded, Included(&(size - 1))); - test(&map, size, Included(&0), Unbounded); - test(&map, size, Unbounded, Unbounded); - } - - #[test] - fn test_range() { - let size = 200; - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - for i in 0..size { - for j in i..size { - let mut kvs = map.range(Included(&i), Included(&j)).map(|(&k, &v)| (k, v)); - let mut pairs = range_inclusive(i, j).map(|i| (i, i)); - - for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { - assert_eq!(kv, pair); - } - assert_eq!(kvs.next(), None); - assert_eq!(pairs.next(), None); - } - } - } - - #[test] - fn test_entry(){ - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: BTreeMap<_, _> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - *v *= 10; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } -} - - - - - - -#[cfg(test)] -mod bench { - use prelude::*; - use std::rand::{weak_rng, Rng}; - use test::{Bencher, black_box}; - - use super::BTreeMap; - - map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} - map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} - - map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} - map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} - - map_find_rand_bench!{find_rand_100, 100, BTreeMap} - map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} - - map_find_seq_bench!{find_seq_100, 100, BTreeMap} - map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} - - fn bench_iter(b: &mut Bencher, size: i32) { - let mut map = BTreeMap::<i32, i32>::new(); - let mut rng = weak_rng(); - - for _ in 0..size { - map.insert(rng.gen(), rng.gen()); - } - - b.iter(|| { - for entry in &map { - black_box(entry); - } - }); - } - - #[bench] - pub fn iter_20(b: &mut Bencher) { - bench_iter(b, 20); - } - - #[bench] - pub fn iter_1000(b: &mut Bencher) { - bench_iter(b, 1000); - } - - #[bench] - pub fn iter_100000(b: &mut Bencher) { - bench_iter(b, 100000); - } -} diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index f2a6910a302..006d6bb040e 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -23,7 +23,7 @@ use core::iter::Zip; use core::marker::PhantomData; use core::ops::{Deref, DerefMut, Index, IndexMut}; use core::ptr::Unique; -use core::{slice, mem, ptr, cmp, num, raw}; +use core::{slice, mem, ptr, cmp, raw}; use alloc::heap::{self, EMPTY}; use borrow::Borrow; @@ -105,7 +105,10 @@ struct MutNodeSlice<'a, K: 'a, V: 'a> { /// Fails if `target_alignment` is not a power of two. #[inline] fn round_up_to_next(unrounded: usize, target_alignment: usize) -> usize { - assert!(num::UnsignedInt::is_power_of_two(target_alignment)); + #[cfg(stage0)] + use core::num::UnsignedInt; + + assert!(target_alignment.is_power_of_two()); (unrounded + target_alignment - 1) & !(target_alignment - 1) } @@ -348,14 +351,8 @@ impl<K, V> Node<K, V> { #[inline] pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) { unsafe {( - mem::transmute(raw::Slice { - data: *self.keys as *const K, - len: self.len() - }), - mem::transmute(raw::Slice { - data: *self.vals as *const V, - len: self.len() - }) + slice::from_raw_parts(*self.keys, self.len()), + slice::from_raw_parts(*self.vals, self.len()), )} } diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index bc2e68b999a..5616d36ce0b 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -30,6 +30,10 @@ use Bound; /// /// See BTreeMap's documentation for a detailed discussion of this collection's performance /// benefits and drawbacks. +/// +/// It is a logic error for an item to be modified in such a way that the item's ordering relative +/// to any other item, as determined by the `Ord` trait, changes while it is in the set. This is +/// normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. #[derive(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BTreeSet<T>{ @@ -738,180 +742,3 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { } } } - - -#[cfg(test)] -mod test { - use prelude::*; - - use super::BTreeSet; - use std::hash::{self, SipHasher}; - - #[test] - fn test_clone_eq() { - let mut m = BTreeSet::new(); - - m.insert(1); - m.insert(2); - - assert!(m.clone() == m); - } - - #[test] - fn test_hash() { - let mut x = BTreeSet::new(); - let mut y = BTreeSet::new(); - - x.insert(1); - x.insert(2); - x.insert(3); - - y.insert(3); - y.insert(2); - y.insert(1); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - struct Counter<'a, 'b> { - i: &'a mut usize, - expected: &'b [i32], - } - - impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> { - type Output = bool; - - extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool { - assert_eq!(x, self.expected[*self.i]); - *self.i += 1; - true - } - } - - fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where - // FIXME Replace Counter with `Box<FnMut(_) -> _>` - F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool, - { - let mut set_a = BTreeSet::new(); - let mut set_b = BTreeSet::new(); - - for x in a { assert!(set_a.insert(*x)) } - for y in b { assert!(set_b.insert(*y)) } - - let mut i = 0; - f(&set_a, &set_b, Counter { i: &mut i, expected: expected }); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_intersection() { - fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.intersection(y).all(f)) - } - - check_intersection(&[], &[], &[]); - check_intersection(&[1, 2, 3], &[], &[]); - check_intersection(&[], &[1, 2, 3], &[]); - check_intersection(&[2], &[1, 2, 3], &[2]); - check_intersection(&[1, 2, 3], &[2], &[2]); - check_intersection(&[11, 1, 3, 77, 103, 5, -5], - &[2, 11, 77, -9, -42, 5, 3], - &[3, 5, 11, 77]); - } - - #[test] - fn test_difference() { - fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.difference(y).all(f)) - } - - check_difference(&[], &[], &[]); - check_difference(&[1, 12], &[], &[1, 12]); - check_difference(&[], &[1, 2, 3, 9], &[]); - check_difference(&[1, 3, 5, 9, 11], - &[3, 9], - &[1, 5, 11]); - check_difference(&[-5, 11, 22, 33, 40, 42], - &[-12, -5, 14, 23, 34, 38, 39, 50], - &[11, 22, 33, 40, 42]); - } - - #[test] - fn test_symmetric_difference() { - fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) - } - - check_symmetric_difference(&[], &[], &[]); - check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); - check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); - check_symmetric_difference(&[1, 3, 5, 9, 11], - &[-2, 3, 9, 14, 22], - &[-2, 1, 5, 11, 14, 22]); - } - - #[test] - fn test_union() { - fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.union(y).all(f)) - } - - check_union(&[], &[], &[]); - check_union(&[1, 2, 3], &[2], &[1, 2, 3]); - check_union(&[2], &[1, 2, 3], &[1, 2, 3]); - check_union(&[1, 3, 5, 9, 11, 16, 19, 24], - &[-2, 1, 5, 9, 13, 19], - &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); - } - - #[test] - fn test_zip() { - let mut x = BTreeSet::new(); - x.insert(5); - x.insert(12); - x.insert(11); - - let mut y = BTreeSet::new(); - y.insert("foo"); - y.insert("bar"); - - let x = x; - let y = y; - let mut z = x.iter().zip(y.iter()); - - // FIXME: #5801: this needs a type hint to compile... - let result: Option<(&usize, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&5, &("bar"))); - - let result: Option<(&usize, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&11, &("foo"))); - - let result: Option<(&usize, & &'static str)> = z.next(); - assert!(result.is_none()); - } - - #[test] - fn test_from_iter() { - let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: BTreeSet<_> = xs.iter().cloned().collect(); - - for x in &xs { - assert!(set.contains(x)); - } - } - - #[test] - fn test_show() { - let mut set = BTreeSet::new(); - let empty = BTreeSet::<i32>::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{:?}", set); - - assert_eq!(set_str, "{1, 2}"); - assert_eq!(format!("{:?}", empty), "{}"); - } -} diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 68ff94cfbfb..fe2efc7164d 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -24,6 +24,11 @@ use core::ops::{Sub, BitOr, BitAnd, BitXor}; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] /// A specialized set implementation to use enum types. +/// +/// It is a logic error for an item to be modified in such a way that the transformation of the +/// item to or from a `usize`, as determined by the `CLike` trait, changes while the item is in the +/// set. This is normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe +/// code. pub struct EnumSet<E> { // We must maintain the invariant that no bits are set // for which no variant exists @@ -280,241 +285,3 @@ impl<E:CLike> Extend<E> for EnumSet<E> { } } } - -#[cfg(test)] -mod test { - use self::Foo::*; - use prelude::*; - use core::mem; - - use super::{EnumSet, CLike}; - - #[derive(Copy, PartialEq, Debug)] - #[repr(usize)] - enum Foo { - A, B, C - } - - impl CLike for Foo { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Foo { - unsafe { mem::transmute(v) } - } - } - - #[test] - fn test_new() { - let e: EnumSet<Foo> = EnumSet::new(); - assert!(e.is_empty()); - } - - #[test] - fn test_show() { - let mut e = EnumSet::new(); - assert!(format!("{:?}", e) == "{}"); - e.insert(A); - assert!(format!("{:?}", e) == "{A}"); - e.insert(C); - assert!(format!("{:?}", e) == "{A, C}"); - } - - #[test] - fn test_len() { - let mut e = EnumSet::new(); - assert_eq!(e.len(), 0); - e.insert(A); - e.insert(B); - e.insert(C); - assert_eq!(e.len(), 3); - e.remove(&A); - assert_eq!(e.len(), 2); - e.clear(); - assert_eq!(e.len(), 0); - } - - /////////////////////////////////////////////////////////////////////////// - // intersect - - #[test] - fn test_two_empties_do_not_intersect() { - let e1: EnumSet<Foo> = EnumSet::new(); - let e2: EnumSet<Foo> = EnumSet::new(); - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_empty_does_not_intersect_with_full() { - let e1: EnumSet<Foo> = EnumSet::new(); - - let mut e2: EnumSet<Foo> = EnumSet::new(); - e2.insert(A); - e2.insert(B); - e2.insert(C); - - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_disjoint_intersects() { - let mut e1: EnumSet<Foo> = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet<Foo> = EnumSet::new(); - e2.insert(B); - - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_overlapping_intersects() { - let mut e1: EnumSet<Foo> = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet<Foo> = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - assert!(!e1.is_disjoint(&e2)); - } - - /////////////////////////////////////////////////////////////////////////// - // contains and contains_elem - - #[test] - fn test_superset() { - let mut e1: EnumSet<Foo> = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet<Foo> = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - let mut e3: EnumSet<Foo> = EnumSet::new(); - e3.insert(C); - - assert!(e1.is_subset(&e2)); - assert!(e2.is_superset(&e1)); - assert!(!e3.is_superset(&e2)); - assert!(!e2.is_superset(&e3)) - } - - #[test] - fn test_contains() { - let mut e1: EnumSet<Foo> = EnumSet::new(); - e1.insert(A); - assert!(e1.contains(&A)); - assert!(!e1.contains(&B)); - assert!(!e1.contains(&C)); - - e1.insert(A); - e1.insert(B); - assert!(e1.contains(&A)); - assert!(e1.contains(&B)); - assert!(!e1.contains(&C)); - } - - /////////////////////////////////////////////////////////////////////////// - // iter - - #[test] - fn test_iterator() { - let mut e1: EnumSet<Foo> = EnumSet::new(); - - let elems: ::vec::Vec<Foo> = e1.iter().collect(); - assert!(elems.is_empty()); - - e1.insert(A); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A], elems); - - e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A,C], elems); - - e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A,C], elems); - - e1.insert(B); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A,B,C], elems); - } - - /////////////////////////////////////////////////////////////////////////// - // operators - - #[test] - fn test_operators() { - let mut e1: EnumSet<Foo> = EnumSet::new(); - e1.insert(A); - e1.insert(C); - - let mut e2: EnumSet<Foo> = EnumSet::new(); - e2.insert(B); - e2.insert(C); - - let e_union = e1 | e2; - let elems: ::vec::Vec<_> = e_union.iter().collect(); - assert_eq!([A,B,C], elems); - - let e_intersection = e1 & e2; - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!([C], elems); - - // Another way to express intersection - let e_intersection = e1 - (e1 - e2); - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!([C], elems); - - let e_subtract = e1 - e2; - let elems: ::vec::Vec<_> = e_subtract.iter().collect(); - assert_eq!([A], elems); - - // Bitwise XOR of two sets, aka symmetric difference - let e_symmetric_diff = e1 ^ e2; - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); - - // Another way to express symmetric difference - let e_symmetric_diff = (e1 - e2) | (e2 - e1); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); - - // Yet another way to express symmetric difference - let e_symmetric_diff = (e1 | e2) - (e1 & e2); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); - } - - #[test] - #[should_panic] - fn test_overflow() { - #[allow(dead_code)] - #[derive(Copy)] - #[repr(usize)] - enum Bar { - V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, - V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, - V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, - V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, - V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, - V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, - V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, - } - - impl CLike for Bar { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Bar { - unsafe { mem::transmute(v) } - } - } - let mut set = EnumSet::new(); - set.insert(Bar::V64); - } -} diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index ae439b06a5b..1deb08ad0d1 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -434,15 +434,3 @@ pub fn format(args: Arguments) -> string::String { let _ = write!(&mut output, "{}", args); output } - -#[cfg(test)] -mod tests { - use prelude::*; - use fmt; - - #[test] - fn test_format() { - let s = fmt::format(format_args!("Hello, {}!", "world")); - assert_eq!(s.as_slice(), "Hello, world!"); - } -} diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index f7943c0bb91..b75f346c188 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,12 +27,14 @@ #![feature(box_syntax)] #![feature(box_patterns)] #![feature(core)] +#![feature(lang_items)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unsafe_destructor)] #![feature(unique)] #![feature(unsafe_no_drop_flag)] +#![feature(step_by)] #![cfg_attr(test, feature(rand, rustc_private, test))] #![cfg_attr(test, allow(deprecated))] // rand @@ -45,9 +47,8 @@ extern crate core; extern crate unicode; extern crate alloc; -#[cfg(test)] extern crate test; #[cfg(test)] #[macro_use] extern crate std; -#[cfg(test)] #[macro_use] extern crate log; +#[cfg(test)] extern crate test; pub use binary_heap::BinaryHeap; pub use bit_vec::BitVec; @@ -83,8 +84,6 @@ pub use alloc::boxed; #[macro_use] mod macros; -#[cfg(test)] #[macro_use] mod bench; - pub mod binary_heap; mod bit; mod btree; @@ -140,40 +139,6 @@ mod std { pub use core::ops; // RangeFull } -#[cfg(test)] -mod prelude { - // from core. - pub use core::clone::Clone; - pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord}; - pub use core::cmp::Ordering::{Less, Equal, Greater}; - pub use core::iter::range; - pub use core::iter::{FromIterator, Extend, IteratorExt}; - pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator}; - pub use core::iter::{ExactSizeIterator}; - pub use core::marker::{Copy, Send, Sized, Sync}; - pub use core::mem::drop; - pub use core::ops::{Drop, Fn, FnMut, FnOnce}; - pub use core::option::Option; - pub use core::option::Option::{Some, None}; - pub use core::ptr::PtrExt; - pub use core::result::Result; - pub use core::result::Result::{Ok, Err}; - - // in core and collections (may differ). - pub use slice::{AsSlice, SliceExt}; - pub use str::{Str, StrExt}; - - // from other crates. - pub use alloc::boxed::Box; - pub use unicode::char::CharExt; - - // from collections. - pub use borrow::IntoCow; - pub use slice::SliceConcatExt; - pub use string::{String, ToString}; - pub use vec::Vec; -} - /// An endpoint of a range of keys. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum Bound<T> { diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 5ca3cb38058..9e0a6d04381 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -940,16 +940,21 @@ impl<A: Hash> Hash for LinkedList<A> { } #[cfg(test)] -mod tests { - use prelude::*; +mod test { + use std::clone::Clone; + use std::iter::{Iterator, IteratorExt}; + use std::option::Option::{Some, None, self}; use std::rand; - use std::hash::{self, SipHasher}; use std::thread; - use test::Bencher; - use test; + use std::vec::Vec; use super::{LinkedList, Node}; + #[cfg(test)] + fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { + v.iter().cloned().collect() + } + pub fn check_links<T>(list: &LinkedList<T>) { let mut len = 0; let mut last_ptr: Option<&Node<T>> = None; @@ -983,56 +988,6 @@ mod tests { } #[test] - fn test_basic() { - let mut m = LinkedList::<Box<_>>::new(); - assert_eq!(m.pop_front(), None); - assert_eq!(m.pop_back(), None); - assert_eq!(m.pop_front(), None); - m.push_front(box 1); - assert_eq!(m.pop_front(), Some(box 1)); - m.push_back(box 2); - m.push_back(box 3); - assert_eq!(m.len(), 2); - assert_eq!(m.pop_front(), Some(box 2)); - assert_eq!(m.pop_front(), Some(box 3)); - assert_eq!(m.len(), 0); - assert_eq!(m.pop_front(), None); - m.push_back(box 1); - m.push_back(box 3); - m.push_back(box 5); - m.push_back(box 7); - assert_eq!(m.pop_front(), Some(box 1)); - - let mut n = LinkedList::new(); - n.push_front(2); - n.push_front(3); - { - assert_eq!(n.front().unwrap(), &3); - let x = n.front_mut().unwrap(); - assert_eq!(*x, 3); - *x = 0; - } - { - assert_eq!(n.back().unwrap(), &2); - let y = n.back_mut().unwrap(); - assert_eq!(*y, 2); - *y = 1; - } - assert_eq!(n.pop_front(), Some(0)); - assert_eq!(n.pop_front(), Some(1)); - } - - #[cfg(test)] - fn generate_test() -> LinkedList<i32> { - list_from(&[0,1,2,3,4,5,6]) - } - - #[cfg(test)] - fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { - v.iter().cloned().collect() - } - - #[test] fn test_append() { // Empty to empty { @@ -1090,166 +1045,6 @@ mod tests { } #[test] - fn test_split_off() { - // singleton - { - let mut m = LinkedList::new(); - m.push_back(1); - - let p = m.split_off(0); - assert_eq!(m.len(), 0); - assert_eq!(p.len(), 1); - assert_eq!(p.back(), Some(&1)); - assert_eq!(p.front(), Some(&1)); - } - - // not singleton, forwards - { - let u = vec![1,2,3,4,5]; - let mut m = list_from(&u); - let mut n = m.split_off(2); - assert_eq!(m.len(), 2); - assert_eq!(n.len(), 3); - for elt in 1..3 { - assert_eq!(m.pop_front(), Some(elt)); - } - for elt in 3..6 { - assert_eq!(n.pop_front(), Some(elt)); - } - } - // not singleton, backwards - { - let u = vec![1,2,3,4,5]; - let mut m = list_from(&u); - let mut n = m.split_off(4); - assert_eq!(m.len(), 4); - assert_eq!(n.len(), 1); - for elt in 1..5 { - assert_eq!(m.pop_front(), Some(elt)); - } - for elt in 5..6 { - assert_eq!(n.pop_front(), Some(elt)); - } - } - - // no-op on the last index - { - let mut m = LinkedList::new(); - m.push_back(1); - - let p = m.split_off(1); - assert_eq!(m.len(), 1); - assert_eq!(p.len(), 0); - assert_eq!(m.back(), Some(&1)); - assert_eq!(m.front(), Some(&1)); - } - - } - - #[test] - fn test_iterator() { - let m = generate_test(); - for (i, elt) in m.iter().enumerate() { - assert_eq!(i as i32, *elt); - } - let mut n = LinkedList::new(); - assert_eq!(n.iter().next(), None); - n.push_front(4); - let mut it = n.iter(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_iterator_clone() { - let mut n = LinkedList::new(); - n.push_back(2); - n.push_back(3); - n.push_back(4); - let mut it = n.iter(); - it.next(); - let mut jt = it.clone(); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next_back(), jt.next_back()); - assert_eq!(it.next(), jt.next()); - } - - #[test] - fn test_iterator_double_end() { - let mut n = LinkedList::new(); - assert_eq!(n.iter().next(), None); - n.push_front(4); - n.push_front(5); - n.push_front(6); - let mut it = n.iter(); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(it.next().unwrap(), &6); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next_back().unwrap(), &4); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next_back().unwrap(), &5); - assert_eq!(it.next_back(), None); - assert_eq!(it.next(), None); - } - - #[test] - fn test_rev_iter() { - let m = generate_test(); - for (i, elt) in m.iter().rev().enumerate() { - assert_eq!((6 - i) as i32, *elt); - } - let mut n = LinkedList::new(); - assert_eq!(n.iter().rev().next(), None); - n.push_front(4); - let mut it = n.iter().rev(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_mut_iter() { - let mut m = generate_test(); - let mut len = m.len(); - for (i, elt) in m.iter_mut().enumerate() { - assert_eq!(i as i32, *elt); - len -= 1; - } - assert_eq!(len, 0); - let mut n = LinkedList::new(); - assert!(n.iter_mut().next().is_none()); - n.push_front(4); - n.push_back(5); - let mut it = n.iter_mut(); - assert_eq!(it.size_hint(), (2, Some(2))); - assert!(it.next().is_some()); - assert!(it.next().is_some()); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_mut_double_end() { - let mut n = LinkedList::new(); - assert!(n.iter_mut().next_back().is_none()); - n.push_front(4); - n.push_front(5); - n.push_front(6); - let mut it = n.iter_mut(); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(*it.next().unwrap(), 6); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(*it.next_back().unwrap(), 4); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(*it.next_back().unwrap(), 5); - assert!(it.next_back().is_none()); - assert!(it.next().is_none()); - } - - #[test] fn test_insert_prev() { let mut m = list_from(&[0,2,4,6,8]); let len = m.len(); @@ -1277,20 +1072,6 @@ mod tests { } #[test] - fn test_mut_rev_iter() { - let mut m = generate_test(); - for (i, elt) in m.iter_mut().rev().enumerate() { - assert_eq!((6 - i) as i32, *elt); - } - let mut n = LinkedList::new(); - assert!(n.iter_mut().rev().next().is_none()); - n.push_front(4); - let mut it = n.iter_mut().rev(); - assert!(it.next().is_some()); - assert!(it.next().is_none()); - } - - #[test] fn test_send() { let n = list_from(&[1,2,3]); thread::spawn(move || { @@ -1301,81 +1082,6 @@ mod tests { } #[test] - fn test_eq() { - let mut n = list_from(&[]); - let mut m = list_from(&[]); - assert!(n == m); - n.push_front(1); - assert!(n != m); - m.push_back(1); - assert!(n == m); - - let n = list_from(&[2,3,4]); - let m = list_from(&[1,2,3]); - assert!(n != m); - } - - #[test] - fn test_hash() { - let mut x = LinkedList::new(); - let mut y = LinkedList::new(); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - - x.push_back(1); - x.push_back(2); - x.push_back(3); - - y.push_front(3); - y.push_front(2); - y.push_front(1); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - #[test] - fn test_ord() { - let n = list_from(&[]); - let m = list_from(&[1,2,3]); - assert!(n < m); - assert!(m > n); - assert!(n <= n); - assert!(n >= n); - } - - #[test] - fn test_ord_nan() { - let nan = 0.0f64/0.0; - let n = list_from(&[nan]); - let m = list_from(&[nan]); - assert!(!(n < m)); - assert!(!(n > m)); - assert!(!(n <= m)); - assert!(!(n >= m)); - - let n = list_from(&[nan]); - let one = list_from(&[1.0f64]); - assert!(!(n < one)); - assert!(!(n > one)); - assert!(!(n <= one)); - assert!(!(n >= one)); - - let u = list_from(&[1.0f64,2.0,nan]); - let v = list_from(&[1.0f64,2.0,3.0]); - assert!(!(u < v)); - assert!(!(u > v)); - assert!(!(u <= v)); - assert!(!(u >= v)); - - let s = list_from(&[1.0f64,2.0,4.0,2.0]); - let t = list_from(&[1.0f64,2.0,3.0,2.0]); - assert!(!(s < t)); - assert!(s > one); - assert!(!(s <= one)); - assert!(s >= one); - } - - #[test] fn test_fuzz() { for _ in 0..25 { fuzz_test(3); @@ -1384,15 +1090,6 @@ mod tests { } } - #[test] - fn test_show() { - let list: LinkedList<_> = (0..10).collect(); - assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - - let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); - assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); - } - #[cfg(test)] fn fuzz_test(sz: i32) { let mut m: LinkedList<_> = LinkedList::new(); @@ -1431,79 +1128,4 @@ mod tests { } assert_eq!(i, v.len()); } - - #[bench] - fn bench_collect_into(b: &mut test::Bencher) { - let v = &[0; 64]; - b.iter(|| { - let _: LinkedList<_> = v.iter().cloned().collect(); - }) - } - - #[bench] - fn bench_push_front(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - }) - } - - #[bench] - fn bench_push_back(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - }) - } - - #[bench] - fn bench_push_back_pop_back(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - m.pop_back(); - }) - } - - #[bench] - fn bench_push_front_pop_front(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - m.pop_front(); - }) - } - - #[bench] - fn bench_iter(b: &mut test::Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().count() == 128); - }) - } - #[bench] - fn bench_iter_mut(b: &mut test::Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().count() == 128); - }) - } - #[bench] - fn bench_iter_rev(b: &mut test::Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().rev().count() == 128); - }) - } - #[bench] - fn bench_iter_mut_rev(b: &mut test::Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().rev().count() == 128); - }) - } } diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index 0f6a85d75da..3c7326dbd8f 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[cfg(stage0)] /// Creates a `Vec` containing the arguments. /// /// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. @@ -45,6 +46,60 @@ macro_rules! vec { ($($x:expr,)*) => (vec![$($x),*]) } +#[cfg(not(stage0))] +/// Creates a `Vec` containing the arguments. +/// +/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a `Vec` containing a given list of elements: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v[1], 2); +/// assert_eq!(v[2], 3); +/// ``` +/// +/// - Create a `Vec` from a given element and size: +/// +/// ``` +/// let v = vec![1; 3]; +/// assert_eq!(v, [1, 1, 1]); +/// ``` +/// +/// Note that unlike array expressions this syntax supports all elements +/// which implement `Clone` and the number of elements doesn't have to be +/// a constant. +#[cfg(not(test))] +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + <[_]>::into_vec($crate::boxed::Box::new([$($x),*])) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is required for this +// macro definition, is not available. Instead use the `slice::into_vec` function which is only +// available with cfg(test) +// NB see the slice::hack module in slice.rs for more information +#[cfg(not(stage0))] +#[cfg(test)] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + $crate::slice::into_vec($crate::boxed::Box::new([$($x),*])) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 76fda8485ab..4993994d46b 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -92,13 +92,14 @@ use core::clone::Clone; use core::cmp::Ordering::{self, Greater, Less}; use core::cmp::{self, Ord, PartialEq}; use core::iter::{Iterator, IteratorExt}; -use core::iter::{range_step, MultiplicativeIterator}; +use core::iter::MultiplicativeIterator; use core::marker::Sized; use core::mem::size_of; use core::mem; use core::num::wrapping::WrappingOps; use core::ops::FnMut; use core::option::Option::{self, Some, None}; +#[cfg(stage0)] use core::ptr::PtrExt; use core::ptr; use core::result::Result; @@ -120,6 +121,7 @@ pub use core::slice::{from_raw_buf, from_raw_mut_buf}; // Basic slice extension methods //////////////////////////////////////////////////////////////////////////////// +#[cfg(stage0)] /// Allocating extension methods for slices. #[stable(feature = "rust1", since = "1.0.0")] pub trait SliceExt { @@ -795,6 +797,7 @@ pub trait SliceExt { fn into_vec(self: Box<Self>) -> Vec<Self::Item>; } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl<T> SliceExt for [T] { type Item = T; @@ -1080,6 +1083,942 @@ impl<T> SliceExt for [T] { } } +// HACK(japaric) needed for the implementation of `vec!` macro during testing +// NB see the hack module in this file for more details +#[cfg(not(stage0))] +#[cfg(test)] +pub use self::hack::into_vec; + +// HACK(japaric) needed for the implementation of `Vec::clone` during testing +// NB see the hack module in this file for more details +#[cfg(not(stage0))] +#[cfg(test)] +pub use self::hack::to_vec; + +// HACK(japaric): With cfg(test) `impl [T]` is not available, these three functions are actually +// methods that are in `impl [T]` but not in `core::slice::SliceExt` - we need to supply these +// functions for the `test_permutations` test +#[cfg(not(stage0))] +mod hack { + use alloc::boxed::Box; + use core::clone::Clone; + #[cfg(test)] + use core::iter::{Iterator, IteratorExt}; + use core::mem; + #[cfg(test)] + use core::option::Option::{Some, None}; + + #[cfg(test)] + use string::ToString; + use vec::Vec; + + use super::{ElementSwaps, Permutations}; + + pub fn into_vec<T>(mut b: Box<[T]>) -> Vec<T> { + unsafe { + let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len()); + mem::forget(b); + xs + } + } + + pub fn permutations<T>(s: &[T]) -> Permutations<T> where T: Clone { + Permutations{ + swaps: ElementSwaps::new(s.len()), + v: to_vec(s), + } + } + + #[inline] + pub fn to_vec<T>(s: &[T]) -> Vec<T> where T: Clone { + let mut vector = Vec::with_capacity(s.len()); + vector.push_all(s); + vector + } + + // NB we can remove this hack if we move this test to libcollectionstest - but that can't be + // done right now because the test needs access to the private fields of Permutations + #[test] + fn test_permutations() { + { + let v: [i32; 0] = []; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = ["Hello".to_string()]; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = [1, 2, 3]; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3*2); + assert_eq!(max_opt.unwrap(), 3*2); + assert_eq!(it.next().unwrap(), [1,2,3]); + assert_eq!(it.next().unwrap(), [1,3,2]); + assert_eq!(it.next().unwrap(), [3,1,2]); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3); + assert_eq!(max_opt.unwrap(), 3); + assert_eq!(it.next().unwrap(), [3,2,1]); + assert_eq!(it.next().unwrap(), [2,3,1]); + assert_eq!(it.next().unwrap(), [2,1,3]); + assert_eq!(it.next(), None); + } + { + // check that we have N! permutations + let v = ['A', 'B', 'C', 'D', 'E', 'F']; + let mut amt = 0; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + for _perm in it.by_ref() { + amt += 1; + } + assert_eq!(amt, it.swaps.swaps_made); + assert_eq!(amt, min_size); + assert_eq!(amt, 2 * 3 * 4 * 5 * 6); + assert_eq!(amt, max_opt.unwrap()); + } + } +} + +#[cfg(not(stage0))] +/// Allocating extension methods for slices. +#[lang = "slice"] +#[cfg(not(test))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<T> [T] { + /// Sorts the slice, in place, using `compare` to compare + /// elements. + /// + /// This sort is `O(n log n)` worst-case and stable, but allocates + /// approximately `2 * n`, where `n` is the length of `self`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [5, 4, 1, 3, 2]; + /// v.sort_by(|a, b| a.cmp(b)); + /// assert!(v == [1, 2, 3, 4, 5]); + /// + /// // reverse sorting + /// v.sort_by(|a, b| b.cmp(a)); + /// assert!(v == [5, 4, 3, 2, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { + merge_sort(self, compare) + } + + /// Consumes `src` and moves as many elements as it can into `self` + /// from the range [start,end). + /// + /// Returns the number of elements copied (the shorter of `self.len()` + /// and `end - start`). + /// + /// # Arguments + /// + /// * src - A mutable vector of `T` + /// * start - The index into `src` to start copying from + /// * end - The index into `src` to stop copying from + /// + /// # Examples + /// + /// ```rust + /// let mut a = [1, 2, 3, 4, 5]; + /// let b = vec![6, 7, 8]; + /// let num_moved = a.move_from(b, 0, 3); + /// assert_eq!(num_moved, 3); + /// assert!(a == [6, 7, 8, 4, 5]); + /// ``` + #[unstable(feature = "collections", + reason = "uncertain about this API approach")] + #[inline] + pub fn move_from(&mut self, mut src: Vec<T>, start: usize, end: usize) -> usize { + for (a, b) in self.iter_mut().zip(src[start .. end].iter_mut()) { + mem::swap(a, b); + } + cmp::min(self.len(), end-start) + } + + /// Deprecated: use `&s[start .. end]` notation instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")] + #[inline] + pub fn slice(&self, start: usize, end: usize) -> &[T] { + &self[start .. end] + } + + /// Deprecated: use `&s[start..]` notation instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[start..] instead")] + #[inline] + pub fn slice_from(&self, start: usize) -> &[T] { + &self[start ..] + } + + /// Deprecated: use `&s[..end]` notation instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[..end] instead")] + #[inline] + pub fn slice_to(&self, end: usize) -> &[T] { + &self[.. end] + } + + /// Divides one slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// Panics if `mid > len`. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30, 20, 50]; + /// let (v1, v2) = v.split_at(2); + /// assert_eq!([10, 40], v1); + /// assert_eq!([30, 20, 50], v2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { + core_slice::SliceExt::split_at(self, mid) + } + + /// Returns an iterator over the slice. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn iter(&self) -> Iter<T> { + core_slice::SliceExt::iter(self) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// Print the slice split by numbers divisible by 3 (i.e. `[10, 40]`, + /// `[20]`, `[50]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// for group in v.split(|num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split<F>(&self, pred: F) -> Split<T, F> where F: FnMut(&T) -> bool { + core_slice::SliceExt::split(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to splitting at most `n` times. The matched element is + /// not contained in the subslices. + /// + /// # Examples + /// + /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`, + /// `[20, 60, 50]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// for group in v.splitn(1, |num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn(self, n, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to splitting at most `n` times. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + /// + /// # Examples + /// + /// Print the slice split once, starting from the end, by numbers divisible + /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// for group in v.rsplitn(1, |num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F> where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn(self, n, pred) + } + + /// Returns an iterator over all contiguous windows of length + /// `size`. The windows overlap. If the slice is shorter than + /// `size`, the iterator returns no values. + /// + /// # Panics + /// + /// Panics if `size` is 0. + /// + /// # Example + /// + /// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`, + /// `[3,4]`): + /// + /// ```rust + /// let v = &[1, 2, 3, 4]; + /// for win in v.windows(2) { + /// println!("{:?}", win); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn windows(&self, size: usize) -> Windows<T> { + core_slice::SliceExt::windows(self, size) + } + + /// Returns an iterator over `size` elements of the slice at a + /// time. The chunks do not overlap. If `size` does not divide the + /// length of the slice, then the last chunk will not have length + /// `size`. + /// + /// # Panics + /// + /// Panics if `size` is 0. + /// + /// # Example + /// + /// Print the slice two elements at a time (i.e. `[1,2]`, + /// `[3,4]`, `[5]`): + /// + /// ```rust + /// let v = &[1, 2, 3, 4, 5]; + /// for win in v.chunks(2) { + /// println!("{:?}", win); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chunks(&self, size: usize) -> Chunks<T> { + core_slice::SliceExt::chunks(self, size) + } + + /// Returns the element of a slice at the given index, or `None` if the + /// index is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&40), v.get(1)); + /// assert_eq!(None, v.get(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn get(&self, index: usize) -> Option<&T> { + core_slice::SliceExt::get(self, index) + } + + /// Returns the first element of a slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&10), v.first()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.first()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn first(&self) -> Option<&T> { + core_slice::SliceExt::first(self) + } + + /// Returns all but the first element of a slice. + #[unstable(feature = "collections", reason = "likely to be renamed")] + #[inline] + pub fn tail(&self) -> &[T] { + core_slice::SliceExt::tail(self) + } + + /// Returns all but the last element of a slice. + #[unstable(feature = "collections", reason = "likely to be renamed")] + #[inline] + pub fn init(&self) -> &[T] { + core_slice::SliceExt::init(self) + } + + /// Returns the last element of a slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&30), v.last()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.last()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn last(&self) -> Option<&T> { + core_slice::SliceExt::last(self) + } + + /// Returns a pointer to the element at the given index, without doing + /// bounds checking. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn get_unchecked(&self, index: usize) -> &T { + core_slice::SliceExt::get_unchecked(self, index) + } + + /// Returns an unsafe pointer to the slice's buffer + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the slice may cause its buffer to be reallocated, which + /// would also make any pointers to it invalid. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + core_slice::SliceExt::as_ptr(self) + } + + /// Binary search a sorted slice with a comparator function. + /// + /// The comparator function should implement an order consistent + /// with the sort order of the underlying slice, returning an + /// order code that indicates whether its argument is `Less`, + /// `Equal` or `Greater` the desired target. + /// + /// If a matching value is found then returns `Ok`, containing + /// the index for the matched element; if no match is found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// let seek = 13; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); + /// let seek = 4; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); + /// let seek = 100; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); + /// let seek = 1; + /// let r = s.binary_search_by(|probe| probe.cmp(&seek)); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn binary_search_by<F>(&self, f: F) -> Result<usize, usize> where F: FnMut(&T) -> Ordering { + core_slice::SliceExt::binary_search_by(self, f) + } + + /// Return the number of elements in the slice + /// + /// # Example + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + core_slice::SliceExt::len(self) + } + + /// Returns true if the slice has a length of 0 + /// + /// # Example + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert!(!a.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_empty(&self) -> bool { + core_slice::SliceExt::is_empty(self) + } + + /// Returns a mutable reference to the element at the given index, + /// or `None` if the index is out of bounds + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + core_slice::SliceExt::get_mut(self, index) + } + + /// Work with `self` as a mut slice. + /// Primarily intended for getting a &mut [T] from a [T; N]. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + core_slice::SliceExt::as_mut_slice(self) + } + + /// Deprecated: use `&mut s[start .. end]` instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")] + #[inline] + pub fn slice_mut(&mut self, start: usize, end: usize) -> &mut [T] { + &mut self[start .. end] + } + + /// Deprecated: use `&mut s[start ..]` instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")] + #[inline] + pub fn slice_from_mut(&mut self, start: usize) -> &mut [T] { + &mut self[start ..] + } + + /// Deprecated: use `&mut s[.. end]` instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")] + #[inline] + pub fn slice_to_mut(&mut self, end: usize) -> &mut [T] { + &mut self[.. end] + } + + /// Returns an iterator that allows modifying each value + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn iter_mut(&mut self) -> IterMut<T> { + core_slice::SliceExt::iter_mut(self) + } + + /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn first_mut(&mut self) -> Option<&mut T> { + core_slice::SliceExt::first_mut(self) + } + + /// Returns all but the first element of a mutable slice + #[unstable(feature = "collections", + reason = "likely to be renamed or removed")] + #[inline] + pub fn tail_mut(&mut self) -> &mut [T] { + core_slice::SliceExt::tail_mut(self) + } + + /// Returns all but the last element of a mutable slice + #[unstable(feature = "collections", + reason = "likely to be renamed or removed")] + #[inline] + pub fn init_mut(&mut self) -> &mut [T] { + core_slice::SliceExt::init_mut(self) + } + + /// Returns a mutable pointer to the last item in the slice. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn last_mut(&mut self) -> Option<&mut T> { + core_slice::SliceExt::last_mut(self) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`. The matched element is not contained in the subslices. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> where F: FnMut(&T) -> bool { + core_slice::SliceExt::split_mut(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to splitting at most `n` times. The matched element is + /// not contained in the subslices. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F> + where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn_mut(self, n, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to splitting at most `n` times. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F> + where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn_mut(self, n, pred) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time. + /// The chunks are mutable and do not overlap. If `chunk_size` does + /// not divide the length of the slice, then the last chunk will not + /// have length `chunk_size`. + /// + /// # Panics + /// + /// Panics if `chunk_size` is 0. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> { + core_slice::SliceExt::chunks_mut(self, chunk_size) + } + + /// Swaps two elements in a slice. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Panics + /// + /// Panics if `a` or `b` are out of bounds. + /// + /// # Example + /// + /// ```rust + /// let mut v = ["a", "b", "c", "d"]; + /// v.swap(1, 3); + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap(&mut self, a: usize, b: usize) { + core_slice::SliceExt::swap(self, a, b) + } + + /// Divides one `&mut` into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1, 2, 3, 4, 5, 6]; + /// + /// // scoped to restrict the lifetime of the borrows + /// { + /// let (left, right) = v.split_at_mut(0); + /// assert!(left == []); + /// assert!(right == [1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_mut(2); + /// assert!(left == [1, 2]); + /// assert!(right == [3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_mut(6); + /// assert!(left == [1, 2, 3, 4, 5, 6]); + /// assert!(right == []); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + core_slice::SliceExt::split_at_mut(self, mid) + } + + /// Reverse the order of elements in a slice, in place. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1, 2, 3]; + /// v.reverse(); + /// assert!(v == [3, 2, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn reverse(&mut self) { + core_slice::SliceExt::reverse(self) + } + + /// Returns an unsafe mutable pointer to the element in index + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { + core_slice::SliceExt::get_unchecked_mut(self, index) + } + + /// Return an unsafe mutable pointer to the slice's buffer. + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the slice may cause its buffer to be reallocated, which + /// would also make any pointers to it invalid. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + core_slice::SliceExt::as_mut_ptr(self) + } + + /// Copies `self` into a new `Vec`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_vec(&self) -> Vec<T> where T: Clone { + // NB see hack module in this file + hack::to_vec(self) + } + + /// Creates an iterator that yields every possible permutation of the + /// vector in succession. + /// + /// # Examples + /// + /// ```rust + /// let v = [1, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// for p in perms { + /// println!("{:?}", p); + /// } + /// ``` + /// + /// Iterating through permutations one by one. + /// + /// ```rust + /// let v = [1, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// assert_eq!(Some(vec![1, 2, 3]), perms.next()); + /// assert_eq!(Some(vec![1, 3, 2]), perms.next()); + /// assert_eq!(Some(vec![3, 1, 2]), perms.next()); + /// ``` + #[unstable(feature = "collections")] + #[inline] + pub fn permutations(&self) -> Permutations<T> where T: Clone { + // NB see hack module in this file + hack::permutations(self) + } + + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. + /// + /// # Example + /// + /// ```rust + /// let mut dst = [0, 0, 0]; + /// let src = [1, 2]; + /// + /// assert!(dst.clone_from_slice(&src) == 2); + /// assert!(dst == [1, 2, 0]); + /// + /// let src2 = [3, 4, 5, 6]; + /// assert!(dst.clone_from_slice(&src2) == 3); + /// assert!(dst == [3, 4, 5]); + /// ``` + #[unstable(feature = "collections")] + pub fn clone_from_slice(&mut self, src: &[T]) -> usize where T: Clone { + core_slice::SliceExt::clone_from_slice(self, src) + } + + /// Sorts the slice, in place. + /// + /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [-5, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5, -3, 1, 2, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort(&mut self) where T: Ord { + self.sort_by(|a, b| a.cmp(b)) + } + + /// Binary search a sorted slice for a given element. + /// + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord { + core_slice::SliceExt::binary_search(self, x) + } + + /// Deprecated: use `binary_search` instead. + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use binary_search instead")] + pub fn binary_search_elem(&self, x: &T) -> Result<usize, usize> where T: Ord { + self.binary_search(x) + } + + /// Mutates the slice to the next lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// last-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [0, 1, 2]; + /// v.next_permutation(); + /// let b: &mut [_] = &mut [0, 2, 1]; + /// assert!(v == b); + /// v.next_permutation(); + /// let b: &mut [_] = &mut [1, 0, 2]; + /// assert!(v == b); + /// ``` + #[unstable(feature = "collections", + reason = "uncertain if this merits inclusion in std")] + pub fn next_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::next_permutation(self) + } + + /// Mutates the slice to the previous lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// first-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [1, 0, 2]; + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0, 2, 1]; + /// assert!(v == b); + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0, 1, 2]; + /// assert!(v == b); + /// ``` + #[unstable(feature = "collections", + reason = "uncertain if this merits inclusion in std")] + pub fn prev_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::prev_permutation(self) + } + + /// Find the first index containing a matching value. + #[unstable(feature = "collections")] + pub fn position_elem(&self, t: &T) -> Option<usize> where T: PartialEq { + core_slice::SliceExt::position_elem(self, t) + } + + /// Find the last index containing a matching value. + #[unstable(feature = "collections")] + pub fn rposition_elem(&self, t: &T) -> Option<usize> where T: PartialEq { + core_slice::SliceExt::rposition_elem(self, t) + } + + /// Returns true if the slice contains an element with the given value. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.contains(&30)); + /// assert!(!v.contains(&50)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains(&self, x: &T) -> bool where T: PartialEq { + core_slice::SliceExt::contains(self, x) + } + + /// Returns true if `needle` is a prefix of the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.starts_with(&[10])); + /// assert!(v.starts_with(&[10, 40])); + /// assert!(!v.starts_with(&[50])); + /// assert!(!v.starts_with(&[10, 50])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::starts_with(self, needle) + } + + /// Returns true if `needle` is a suffix of the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.ends_with(&[30])); + /// assert!(v.ends_with(&[40, 30])); + /// assert!(!v.ends_with(&[50])); + /// assert!(!v.ends_with(&[50, 30])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::ends_with(self, needle) + } + + /// Convert `self` into a vector without clones or allocation. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn into_vec(self: Box<Self>) -> Vec<T> { + // NB see hack module in this file + hack::into_vec(self) + } +} + //////////////////////////////////////////////////////////////////////////////// // Extension traits for slices over specific kinds of data //////////////////////////////////////////////////////////////////////////////// @@ -1189,7 +2128,15 @@ impl<T> BorrowMut<[T]> for Vec<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: Clone> ToOwned for [T] { type Owned = Vec<T>; + #[cfg(not(test))] fn to_owned(&self) -> Vec<T> { self.to_vec() } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec`, which is required for this method + // definition, is not available. Since we don't require this method for testing purposes, I'll + // just stub it + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn to_owned(&self) -> Vec<T> { panic!("not available with cfg(test)") } } //////////////////////////////////////////////////////////////////////////////// @@ -1387,7 +2334,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order // We could hardcode the sorting comparisons here, and we could // manipulate/step the pointers themselves, rather than repeatedly // .offset-ing. - for start in range_step(0, len, insertion) { + for start in (0.. len).step_by(insertion) { // start <= i < len; for i in start..cmp::min(start + insertion, len) { // j satisfies: start <= j <= i; @@ -1427,7 +2374,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order // a time, placing the result in `buf_tmp`. // 0 <= start <= len. - for start in range_step(0, len, 2 * width) { + for start in (0..len).step_by(2 * width) { // manipulate pointers directly for speed (rather than // using a `for` loop with `range` and `.offset` inside // that loop). @@ -1506,1633 +2453,3 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order old } } - -#[cfg(test)] -mod tests { - use alloc::boxed::Box; - use core::cmp::Ordering::{Greater, Less, Equal}; - use core::prelude::{Some, None, Clone}; - use core::prelude::{Iterator, IteratorExt}; - use core::prelude::{AsSlice}; - use core::prelude::Ord; - use core::default::Default; - use core::mem; - use std::iter::RandomAccessIterator; - use std::rand::{Rng, thread_rng}; - use std::rc::Rc; - use string::ToString; - use vec::Vec; - use super::{ElementSwaps, SliceConcatExt, SliceExt}; - - fn square(n: usize) -> usize { n * n } - - fn is_odd(n: &usize) -> bool { *n % 2 == 1 } - - #[test] - fn test_from_fn() { - // Test on-stack from_fn. - let mut v: Vec<_> = (0..3).map(square).collect(); - { - let v = v; - assert_eq!(v.len(), 3); - assert_eq!(v[0], 0); - assert_eq!(v[1], 1); - assert_eq!(v[2], 4); - } - - // Test on-heap from_fn. - v = (0..5).map(square).collect(); - { - let v = v; - assert_eq!(v.len(), 5); - assert_eq!(v[0], 0); - assert_eq!(v[1], 1); - assert_eq!(v[2], 4); - assert_eq!(v[3], 9); - assert_eq!(v[4], 16); - } - } - - #[test] - fn test_from_elem() { - // Test on-stack from_elem. - let mut v = vec![10, 10]; - { - let v = v; - assert_eq!(v.len(), 2); - assert_eq!(v[0], 10); - assert_eq!(v[1], 10); - } - - // Test on-heap from_elem. - v = vec![20; 6]; - { - let v = v.as_slice(); - assert_eq!(v[0], 20); - assert_eq!(v[1], 20); - assert_eq!(v[2], 20); - assert_eq!(v[3], 20); - assert_eq!(v[4], 20); - assert_eq!(v[5], 20); - } - } - - #[test] - fn test_is_empty() { - let xs: [i32; 0] = []; - assert!(xs.is_empty()); - assert!(![0].is_empty()); - } - - #[test] - fn test_len_divzero() { - type Z = [i8; 0]; - let v0 : &[Z] = &[]; - let v1 : &[Z] = &[[]]; - let v2 : &[Z] = &[[], []]; - assert_eq!(mem::size_of::<Z>(), 0); - assert_eq!(v0.len(), 0); - assert_eq!(v1.len(), 1); - assert_eq!(v2.len(), 2); - } - - #[test] - fn test_get() { - let mut a = vec![11]; - assert_eq!(a.get(1), None); - a = vec![11, 12]; - assert_eq!(a.get(1).unwrap(), &12); - a = vec![11, 12, 13]; - assert_eq!(a.get(1).unwrap(), &12); - } - - #[test] - fn test_first() { - let mut a = vec![]; - assert_eq!(a.first(), None); - a = vec![11]; - assert_eq!(a.first().unwrap(), &11); - a = vec![11, 12]; - assert_eq!(a.first().unwrap(), &11); - } - - #[test] - fn test_first_mut() { - let mut a = vec![]; - assert_eq!(a.first_mut(), None); - a = vec![11]; - assert_eq!(*a.first_mut().unwrap(), 11); - a = vec![11, 12]; - assert_eq!(*a.first_mut().unwrap(), 11); - } - - #[test] - fn test_tail() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.tail(), b); - a = vec![11, 12]; - let b: &[i32] = &[12]; - assert_eq!(a.tail(), b); - } - - #[test] - fn test_tail_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.tail_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [12]; - assert!(a.tail_mut() == b); - } - - #[test] - #[should_panic] - fn test_tail_empty() { - let a = Vec::<i32>::new(); - a.tail(); - } - - #[test] - #[should_panic] - fn test_tail_mut_empty() { - let mut a = Vec::<i32>::new(); - a.tail_mut(); - } - - #[test] - fn test_init() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.init(), b); - a = vec![11, 12]; - let b: &[_] = &[11]; - assert_eq!(a.init(), b); - } - - #[test] - fn test_init_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.init_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [11]; - assert!(a.init_mut() == b); - } - - #[test] - #[should_panic] - fn test_init_empty() { - let a = Vec::<i32>::new(); - a.init(); - } - - #[test] - #[should_panic] - fn test_init_mut_empty() { - let mut a = Vec::<i32>::new(); - a.init_mut(); - } - - #[test] - fn test_last() { - let mut a = vec![]; - assert_eq!(a.last(), None); - a = vec![11]; - assert_eq!(a.last().unwrap(), &11); - a = vec![11, 12]; - assert_eq!(a.last().unwrap(), &12); - } - - #[test] - fn test_last_mut() { - let mut a = vec![]; - assert_eq!(a.last_mut(), None); - a = vec![11]; - assert_eq!(*a.last_mut().unwrap(), 11); - a = vec![11, 12]; - assert_eq!(*a.last_mut().unwrap(), 12); - } - - #[test] - fn test_slice() { - // Test fixed length vector. - let vec_fixed = [1, 2, 3, 4]; - let v_a = vec_fixed[1..vec_fixed.len()].to_vec(); - assert_eq!(v_a.len(), 3); - - assert_eq!(v_a[0], 2); - assert_eq!(v_a[1], 3); - assert_eq!(v_a[2], 4); - - // Test on stack. - let vec_stack: &[_] = &[1, 2, 3]; - let v_b = vec_stack[1..3].to_vec(); - assert_eq!(v_b.len(), 2); - - assert_eq!(v_b[0], 2); - assert_eq!(v_b[1], 3); - - // Test `Box<[T]>` - let vec_unique = vec![1, 2, 3, 4, 5, 6]; - let v_d = vec_unique[1..6].to_vec(); - assert_eq!(v_d.len(), 5); - - assert_eq!(v_d[0], 2); - assert_eq!(v_d[1], 3); - assert_eq!(v_d[2], 4); - assert_eq!(v_d[3], 5); - assert_eq!(v_d[4], 6); - } - - #[test] - fn test_slice_from() { - let vec: &[_] = &[1, 2, 3, 4]; - assert_eq!(&vec[..], vec); - let b: &[_] = &[3, 4]; - assert_eq!(&vec[2..], b); - let b: &[_] = &[]; - assert_eq!(&vec[4..], b); - } - - #[test] - fn test_slice_to() { - let vec: &[_] = &[1, 2, 3, 4]; - assert_eq!(&vec[..4], vec); - let b: &[_] = &[1, 2]; - assert_eq!(&vec[..2], b); - let b: &[_] = &[]; - assert_eq!(&vec[..0], b); - } - - - #[test] - fn test_pop() { - let mut v = vec![5]; - let e = v.pop(); - assert_eq!(v.len(), 0); - assert_eq!(e, Some(5)); - let f = v.pop(); - assert_eq!(f, None); - let g = v.pop(); - assert_eq!(g, None); - } - - #[test] - fn test_swap_remove() { - let mut v = vec![1, 2, 3, 4, 5]; - let mut e = v.swap_remove(0); - assert_eq!(e, 1); - assert_eq!(v, [5, 2, 3, 4]); - e = v.swap_remove(3); - assert_eq!(e, 4); - assert_eq!(v, [5, 2, 3]); - } - - #[test] - #[should_panic] - fn test_swap_remove_fail() { - let mut v = vec![1]; - let _ = v.swap_remove(0); - let _ = v.swap_remove(0); - } - - #[test] - fn test_swap_remove_noncopyable() { - // Tests that we don't accidentally run destructors twice. - let mut v: Vec<Box<_>> = Vec::new(); - v.push(box 0u8); - v.push(box 0u8); - v.push(box 0u8); - let mut _e = v.swap_remove(0); - assert_eq!(v.len(), 2); - _e = v.swap_remove(1); - assert_eq!(v.len(), 1); - _e = v.swap_remove(0); - assert_eq!(v.len(), 0); - } - - #[test] - fn test_push() { - // Test on-stack push(). - let mut v = vec![]; - v.push(1); - assert_eq!(v.len(), 1); - assert_eq!(v[0], 1); - - // Test on-heap push(). - v.push(2); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); - } - - #[test] - fn test_truncate() { - let mut v: Vec<Box<_>> = vec![box 6,box 5,box 4]; - v.truncate(1); - let v = v; - assert_eq!(v.len(), 1); - assert_eq!(*(v[0]), 6); - // If the unsafe block didn't drop things properly, we blow up here. - } - - #[test] - fn test_clear() { - let mut v: Vec<Box<_>> = vec![box 6,box 5,box 4]; - v.clear(); - assert_eq!(v.len(), 0); - // If the unsafe block didn't drop things properly, we blow up here. - } - - #[test] - fn test_dedup() { - fn case(a: Vec<i32>, b: Vec<i32>) { - let mut v = a; - v.dedup(); - assert_eq!(v, b); - } - case(vec![], vec![]); - case(vec![1], vec![1]); - case(vec![1,1], vec![1]); - case(vec![1,2,3], vec![1,2,3]); - case(vec![1,1,2,3], vec![1,2,3]); - case(vec![1,2,2,3], vec![1,2,3]); - case(vec![1,2,3,3], vec![1,2,3]); - case(vec![1,1,2,2,2,3,3], vec![1,2,3]); - } - - #[test] - fn test_dedup_unique() { - let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3]; - v0.dedup(); - let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3]; - v1.dedup(); - let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3]; - v2.dedup(); - /* - * If the boxed pointers were leaked or otherwise misused, valgrind - * and/or rt should raise errors. - */ - } - - #[test] - fn test_dedup_shared() { - let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3]; - v0.dedup(); - let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3]; - v1.dedup(); - let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3]; - v2.dedup(); - /* - * If the pointers were leaked or otherwise misused, valgrind and/or - * rt should raise errors. - */ - } - - #[test] - fn test_retain() { - let mut v = vec![1, 2, 3, 4, 5]; - v.retain(is_odd); - assert_eq!(v, [1, 3, 5]); - } - - #[test] - fn test_element_swaps() { - let mut v = [1, 2, 3]; - for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { - v.swap(a, b); - match i { - 0 => assert!(v == [1, 3, 2]), - 1 => assert!(v == [3, 1, 2]), - 2 => assert!(v == [3, 2, 1]), - 3 => assert!(v == [2, 3, 1]), - 4 => assert!(v == [2, 1, 3]), - 5 => assert!(v == [1, 2, 3]), - _ => panic!(), - } - } - } - - #[test] - fn test_permutations() { - { - let v: [i32; 0] = []; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = ["Hello".to_string()]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = [1, 2, 3]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3*2); - assert_eq!(max_opt.unwrap(), 3*2); - assert_eq!(it.next(), Some(vec![1,2,3])); - assert_eq!(it.next(), Some(vec![1,3,2])); - assert_eq!(it.next(), Some(vec![3,1,2])); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3); - assert_eq!(max_opt.unwrap(), 3); - assert_eq!(it.next(), Some(vec![3,2,1])); - assert_eq!(it.next(), Some(vec![2,3,1])); - assert_eq!(it.next(), Some(vec![2,1,3])); - assert_eq!(it.next(), None); - } - { - // check that we have N! permutations - let v = ['A', 'B', 'C', 'D', 'E', 'F']; - let mut amt = 0; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - for _perm in it.by_ref() { - amt += 1; - } - assert_eq!(amt, it.swaps.swaps_made); - assert_eq!(amt, min_size); - assert_eq!(amt, 2 * 3 * 4 * 5 * 6); - assert_eq!(amt, max_opt.unwrap()); - } - } - - #[test] - fn test_lexicographic_permutations() { - let v : &mut[_] = &mut[1, 2, 3, 4, 5]; - assert!(v.prev_permutation() == false); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 3, 5, 4]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[1, 2, 3, 4, 5]; - assert!(v == b); - assert!(v.next_permutation()); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 4, 3, 5]; - assert!(v == b); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 4, 5, 3]; - assert!(v == b); - - let v : &mut[_] = &mut[1, 0, 0, 0]; - assert!(v.next_permutation() == false); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 1, 0, 0]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 0, 1, 0]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 0, 0, 1]; - assert!(v == b); - assert!(v.prev_permutation() == false); - } - - #[test] - fn test_lexicographic_permutations_empty_and_short() { - let empty : &mut[i32] = &mut[]; - assert!(empty.next_permutation() == false); - let b: &mut[i32] = &mut[]; - assert!(empty == b); - assert!(empty.prev_permutation() == false); - assert!(empty == b); - - let one_elem : &mut[_] = &mut[4]; - assert!(one_elem.prev_permutation() == false); - let b: &mut[_] = &mut[4]; - assert!(one_elem == b); - assert!(one_elem.next_permutation() == false); - assert!(one_elem == b); - - let two_elem : &mut[_] = &mut[1, 2]; - assert!(two_elem.prev_permutation() == false); - let b : &mut[_] = &mut[1, 2]; - let c : &mut[_] = &mut[2, 1]; - assert!(two_elem == b); - assert!(two_elem.next_permutation()); - assert!(two_elem == c); - assert!(two_elem.next_permutation() == false); - assert!(two_elem == c); - assert!(two_elem.prev_permutation()); - assert!(two_elem == b); - assert!(two_elem.prev_permutation() == false); - assert!(two_elem == b); - } - - #[test] - fn test_position_elem() { - assert!([].position_elem(&1).is_none()); - - let v1 = vec![1, 2, 3, 3, 2, 5]; - assert_eq!(v1.position_elem(&1), Some(0)); - assert_eq!(v1.position_elem(&2), Some(1)); - assert_eq!(v1.position_elem(&5), Some(5)); - assert!(v1.position_elem(&4).is_none()); - } - - #[test] - fn test_binary_search() { - assert_eq!([1,2,3,4,5].binary_search(&5).ok(), Some(4)); - assert_eq!([1,2,3,4,5].binary_search(&4).ok(), Some(3)); - assert_eq!([1,2,3,4,5].binary_search(&3).ok(), Some(2)); - assert_eq!([1,2,3,4,5].binary_search(&2).ok(), Some(1)); - assert_eq!([1,2,3,4,5].binary_search(&1).ok(), Some(0)); - - assert_eq!([2,4,6,8,10].binary_search(&1).ok(), None); - assert_eq!([2,4,6,8,10].binary_search(&5).ok(), None); - assert_eq!([2,4,6,8,10].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6,8,10].binary_search(&10).ok(), Some(4)); - - assert_eq!([2,4,6,8].binary_search(&1).ok(), None); - assert_eq!([2,4,6,8].binary_search(&5).ok(), None); - assert_eq!([2,4,6,8].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6,8].binary_search(&8).ok(), Some(3)); - - assert_eq!([2,4,6].binary_search(&1).ok(), None); - assert_eq!([2,4,6].binary_search(&5).ok(), None); - assert_eq!([2,4,6].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6].binary_search(&6).ok(), Some(2)); - - assert_eq!([2,4].binary_search(&1).ok(), None); - assert_eq!([2,4].binary_search(&5).ok(), None); - assert_eq!([2,4].binary_search(&2).ok(), Some(0)); - assert_eq!([2,4].binary_search(&4).ok(), Some(1)); - - assert_eq!([2].binary_search(&1).ok(), None); - assert_eq!([2].binary_search(&5).ok(), None); - assert_eq!([2].binary_search(&2).ok(), Some(0)); - - assert_eq!([].binary_search(&1).ok(), None); - assert_eq!([].binary_search(&5).ok(), None); - - assert!([1,1,1,1,1].binary_search(&1).ok() != None); - assert!([1,1,1,1,2].binary_search(&1).ok() != None); - assert!([1,1,1,2,2].binary_search(&1).ok() != None); - assert!([1,1,2,2,2].binary_search(&1).ok() != None); - assert_eq!([1,2,2,2,2].binary_search(&1).ok(), Some(0)); - - assert_eq!([1,2,3,4,5].binary_search(&6).ok(), None); - assert_eq!([1,2,3,4,5].binary_search(&0).ok(), None); - } - - #[test] - fn test_reverse() { - let mut v = vec![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 mut v3 = Vec::<i32>::new(); - v3.reverse(); - assert!(v3.is_empty()); - } - - #[test] - fn test_sort() { - for len in 4..25 { - for _ in 0..100 { - let mut v: Vec<_> = thread_rng().gen_iter::<i32>().take(len).collect(); - let mut v1 = v.clone(); - - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| a.cmp(b)); - assert!(v1.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| b.cmp(a)); - assert!(v1.windows(2).all(|w| w[0] >= w[1])); - } - } - - // shouldn't panic - let mut v: [i32; 0] = []; - v.sort(); - - let mut v = [0xDEADBEEFu64]; - v.sort(); - assert!(v == [0xDEADBEEF]); - } - - #[test] - fn test_sort_stability() { - for len in 4..25 { - for _ in 0..10 { - let mut counts = [0; 10]; - - // create a vector like [(6, 1), (5, 1), (6, 2), ...], - // where the first item of each tuple is random, but - // the second item represents which occurrence of that - // number this element is, i.e. the second elements - // will occur in sorted order. - let mut v: Vec<_> = (0..len).map(|_| { - let n = thread_rng().gen::<usize>() % 10; - counts[n] += 1; - (n, counts[n]) - }).collect(); - - // only sort on the first element, so an unstable sort - // may mix up the counts. - v.sort_by(|&(a,_), &(b,_)| a.cmp(&b)); - - // this comparison includes the count (the second item - // of the tuple), so elements with equal first items - // will need to be ordered with increasing - // counts... i.e. exactly asserting that this sort is - // stable. - assert!(v.windows(2).all(|w| w[0] <= w[1])); - } - } - } - - #[test] - fn test_concat() { - let v: [Vec<i32>; 0] = []; - let c = v.concat(); - assert_eq!(c, []); - let d = [vec![1], vec![2, 3]].concat(); - assert_eq!(d, [1, 2, 3]); - - let v: &[&[_]] = &[&[1], &[2, 3]]; - assert_eq!(v.connect(&0), [1, 0, 2, 3]); - let v: &[&[_]] = &[&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); - } - - #[test] - fn test_connect() { - let v: [Vec<i32>; 0] = []; - assert_eq!(v.connect(&0), []); - assert_eq!([vec![1], vec![2, 3]].connect(&0), [1, 0, 2, 3]); - assert_eq!([vec![1], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]); - - let v: [&[_]; 2] = [&[1], &[2, 3]]; - assert_eq!(v.connect(&0), [1, 0, 2, 3]); - let v: [&[_]; 3] = [&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); - } - - #[test] - fn test_insert() { - let mut a = vec![1, 2, 4]; - a.insert(2, 3); - assert_eq!(a, [1, 2, 3, 4]); - - let mut a = vec![1, 2, 3]; - a.insert(0, 0); - assert_eq!(a, [0, 1, 2, 3]); - - let mut a = vec![1, 2, 3]; - a.insert(3, 4); - assert_eq!(a, [1, 2, 3, 4]); - - let mut a = vec![]; - a.insert(0, 1); - assert_eq!(a, [1]); - } - - #[test] - #[should_panic] - fn test_insert_oob() { - let mut a = vec![1, 2, 3]; - a.insert(4, 5); - } - - #[test] - fn test_remove() { - let mut a = vec![1, 2, 3, 4]; - - assert_eq!(a.remove(2), 3); - assert_eq!(a, [1, 2, 4]); - - assert_eq!(a.remove(2), 4); - assert_eq!(a, [1, 2]); - - assert_eq!(a.remove(0), 1); - assert_eq!(a, [2]); - - assert_eq!(a.remove(0), 2); - assert_eq!(a, []); - } - - #[test] - #[should_panic] - fn test_remove_fail() { - let mut a = vec![1]; - let _ = a.remove(0); - let _ = a.remove(0); - } - - #[test] - fn test_capacity() { - let mut v = vec![0]; - v.reserve_exact(10); - assert!(v.capacity() >= 11); - } - - #[test] - fn test_slice_2() { - let v = vec![1, 2, 3, 4, 5]; - let v = v.slice(1, 3); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 2); - assert_eq!(v[1], 3); - } - - #[test] - #[should_panic] - fn test_permute_fail() { - let v: [(Box<_>, Rc<_>); 4] = - [(box 0, Rc::new(0)), (box 0, Rc::new(0)), - (box 0, Rc::new(0)), (box 0, Rc::new(0))]; - let mut i = 0; - for _ in v.permutations() { - if i == 2 { - panic!() - } - i += 1; - } - } - - #[test] - fn test_total_ord() { - let c = &[1, 2, 3]; - [1, 2, 3, 4][..].cmp(c) == Greater; - let c = &[1, 2, 3, 4]; - [1, 2, 3][..].cmp(c) == Less; - let c = &[1, 2, 3, 6]; - [1, 2, 3, 4][..].cmp(c) == Equal; - let c = &[1, 2, 3, 4, 5, 6]; - [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less; - let c = &[1, 2, 3, 4]; - [2, 2][..].cmp(c) == Greater; - } - - #[test] - fn test_iterator() { - let xs = [1, 2, 5, 10, 11]; - let mut it = xs.iter(); - assert_eq!(it.size_hint(), (5, Some(5))); - assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.size_hint(), (4, Some(4))); - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_random_access_iterator() { - let xs = [1, 2, 5, 10, 11]; - let mut it = xs.iter(); - - assert_eq!(it.indexable(), 5); - assert_eq!(it.idx(0).unwrap(), &1); - assert_eq!(it.idx(2).unwrap(), &5); - assert_eq!(it.idx(4).unwrap(), &11); - assert!(it.idx(5).is_none()); - - assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.indexable(), 4); - assert_eq!(it.idx(0).unwrap(), &2); - assert_eq!(it.idx(3).unwrap(), &11); - assert!(it.idx(4).is_none()); - - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.indexable(), 3); - assert_eq!(it.idx(1).unwrap(), &10); - assert!(it.idx(3).is_none()); - - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.indexable(), 2); - assert_eq!(it.idx(1).unwrap(), &11); - - assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.indexable(), 1); - assert_eq!(it.idx(0).unwrap(), &11); - assert!(it.idx(1).is_none()); - - assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.indexable(), 0); - assert!(it.idx(0).is_none()); - - assert!(it.next().is_none()); - } - - #[test] - fn test_iter_size_hints() { - let mut xs = [1, 2, 5, 10, 11]; - assert_eq!(xs.iter().size_hint(), (5, Some(5))); - assert_eq!(xs.iter_mut().size_hint(), (5, Some(5))); - } - - #[test] - fn test_iter_clone() { - let xs = [1, 2, 5]; - let mut it = xs.iter(); - it.next(); - let mut jt = it.clone(); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next(), jt.next()); - } - - #[test] - fn test_mut_iterator() { - let mut xs = [1, 2, 3, 4, 5]; - for x in &mut xs { - *x += 1; - } - assert!(xs == [2, 3, 4, 5, 6]) - } - - #[test] - fn test_rev_iterator() { - - let xs = [1, 2, 5, 10, 11]; - let ys = [11, 10, 5, 2, 1]; - let mut i = 0; - for &x in xs.iter().rev() { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, 5); - } - - #[test] - fn test_mut_rev_iterator() { - let mut xs = [1, 2, 3, 4, 5]; - for (i,x) in xs.iter_mut().rev().enumerate() { - *x += i; - } - assert!(xs == [5, 5, 5, 5, 5]) - } - - #[test] - fn test_move_iterator() { - let xs = vec![1,2,3,4,5]; - assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10*a + b), 12345); - } - - #[test] - fn test_move_rev_iterator() { - let xs = vec![1,2,3,4,5]; - assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10*a + b), 54321); - } - - #[test] - fn test_splitator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1], &[3], &[5]]; - assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[], &[2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 1).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4], &[]]; - assert_eq!(xs.split(|x| *x == 5).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; - assert_eq!(xs.split(|_| true).collect::<Vec<&[i32]>>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[i32]>>(), splits); - } - - #[test] - fn test_splitnator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[1], &[3,4,5]]; - assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[4,5]]; - assert_eq!(xs.splitn(3, |_| true).collect::<Vec<_>>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.splitn(1, |x| *x == 5).collect::<Vec<_>>(), splits); - } - - #[test] - fn test_splitnator_mut() { - let xs = &mut [1,2,3,4,5]; - - let splits: &[&mut[_]] = &[&mut [1,2,3,4,5]]; - assert_eq!(xs.splitn_mut(0, |x| *x % 2 == 0).collect::<Vec<_>>(), - splits); - let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]]; - assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(), - splits); - let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]]; - assert_eq!(xs.splitn_mut(3, |_| true).collect::<Vec<_>>(), - splits); - - let xs: &mut [i32] = &mut []; - let splits: &[&mut[i32]] = &[&mut []]; - assert_eq!(xs.splitn_mut(1, |x| *x == 5).collect::<Vec<_>>(), - splits); - } - - #[test] - fn test_rsplitator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[5], &[3], &[1]]; - assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[2,3,4,5], &[]]; - assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[], &[1,2,3,4]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<_>>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[i32]>>(), splits); - } - - #[test] - fn test_rsplitnator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[5], &[1,2,3]]; - assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[1,2]]; - assert_eq!(xs.rsplitn(3, |_| true).collect::<Vec<_>>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<Vec<&[i32]>>(), splits); - } - - #[test] - fn test_windowsator() { - let v = &[1,2,3,4]; - - let wins: &[&[_]] = &[&[1,2], &[2,3], &[3,4]]; - assert_eq!(v.windows(2).collect::<Vec<_>>(), wins); - - let wins: &[&[_]] = &[&[1,2,3], &[2,3,4]]; - assert_eq!(v.windows(3).collect::<Vec<_>>(), wins); - assert!(v.windows(6).next().is_none()); - - let wins: &[&[_]] = &[&[3,4], &[2,3], &[1,2]]; - assert_eq!(v.windows(2).rev().collect::<Vec<&[_]>>(), wins); - let mut it = v.windows(2); - assert_eq!(it.indexable(), 3); - let win: &[_] = &[1,2]; - assert_eq!(it.idx(0).unwrap(), win); - let win: &[_] = &[2,3]; - assert_eq!(it.idx(1).unwrap(), win); - let win: &[_] = &[3,4]; - assert_eq!(it.idx(2).unwrap(), win); - assert_eq!(it.idx(3), None); - } - - #[test] - #[should_panic] - fn test_windowsator_0() { - let v = &[1,2,3,4]; - let _it = v.windows(0); - } - - #[test] - fn test_chunksator() { - use core::iter::ExactSizeIterator; - - let v = &[1,2,3,4,5]; - - assert_eq!(v.chunks(2).len(), 3); - - let chunks: &[&[_]] = &[&[1,2], &[3,4], &[5]]; - assert_eq!(v.chunks(2).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3], &[4,5]]; - assert_eq!(v.chunks(3).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(v.chunks(6).collect::<Vec<_>>(), chunks); - - let chunks: &[&[_]] = &[&[5], &[3,4], &[1,2]]; - assert_eq!(v.chunks(2).rev().collect::<Vec<_>>(), chunks); - let mut it = v.chunks(2); - assert_eq!(it.indexable(), 3); - - let chunk: &[_] = &[1,2]; - assert_eq!(it.idx(0).unwrap(), chunk); - let chunk: &[_] = &[3,4]; - assert_eq!(it.idx(1).unwrap(), chunk); - let chunk: &[_] = &[5]; - assert_eq!(it.idx(2).unwrap(), chunk); - assert_eq!(it.idx(3), None); - } - - #[test] - #[should_panic] - fn test_chunksator_0() { - let v = &[1,2,3,4]; - let _it = v.chunks(0); - } - - #[test] - fn test_move_from() { - let mut a = [1,2,3,4,5]; - let b = vec![6,7,8]; - assert_eq!(a.move_from(b, 0, 3), 3); - assert!(a == [6,7,8,4,5]); - let mut a = [7,2,8,1]; - let b = vec![3,1,4,1,5,9]; - assert_eq!(a.move_from(b, 0, 6), 4); - assert!(a == [3,1,4,1]); - let mut a = [1,2,3,4]; - let b = vec![5,6,7,8,9,0]; - assert_eq!(a.move_from(b, 2, 3), 1); - assert!(a == [7,2,3,4]); - let mut a = [1,2,3,4,5]; - let b = vec![5,6,7,8,9,0]; - assert_eq!(a[2..4].move_from(b,1,6), 2); - assert!(a == [1,2,6,7,5]); - } - - #[test] - fn test_reverse_part() { - let mut values = [1,2,3,4,5]; - values[1..4].reverse(); - assert!(values == [1,4,3,2,5]); - } - - #[test] - fn test_show() { - macro_rules! test_show_vec { - ($x:expr, $x_str:expr) => ({ - let (x, x_str) = ($x, $x_str); - assert_eq!(format!("{:?}", x), x_str); - assert_eq!(format!("{:?}", x), x_str); - }) - } - let empty = Vec::<i32>::new(); - test_show_vec!(empty, "[]"); - test_show_vec!(vec![1], "[1]"); - test_show_vec!(vec![1, 2, 3], "[1, 2, 3]"); - test_show_vec!(vec![vec![], vec![1], vec![1, 1]], - "[[], [1], [1, 1]]"); - - let empty_mut: &mut [i32] = &mut[]; - test_show_vec!(empty_mut, "[]"); - let v = &mut[1]; - test_show_vec!(v, "[1]"); - let v = &mut[1, 2, 3]; - test_show_vec!(v, "[1, 2, 3]"); - let v: &mut[&mut[_]] = &mut[&mut[], &mut[1], &mut[1, 1]]; - test_show_vec!(v, "[[], [1], [1, 1]]"); - } - - #[test] - fn test_vec_default() { - macro_rules! t { - ($ty:ty) => {{ - let v: $ty = Default::default(); - assert!(v.is_empty()); - }} - } - - t!(&[i32]); - t!(Vec<i32>); - } - - #[test] - fn test_bytes_set_memory() { - use slice::bytes::MutableByteVector; - let mut values = [1,2,3,4,5]; - values[0..5].set_memory(0xAB); - assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); - values[2..4].set_memory(0xFF); - assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); - } - - #[test] - #[should_panic] - fn test_overflow_does_not_cause_segfault() { - let mut v = vec![]; - v.reserve_exact(-1); - v.push(1); - v.push(2); - } - - #[test] - #[should_panic] - fn test_overflow_does_not_cause_segfault_managed() { - let mut v = vec![Rc::new(1)]; - v.reserve_exact(-1); - v.push(Rc::new(2)); - } - - #[test] - fn test_mut_split_at() { - let mut values = [1u8,2,3,4,5]; - { - let (left, right) = values.split_at_mut(2); - { - let left: &[_] = left; - assert!(left[..left.len()] == [1, 2]); - } - for p in left { - *p += 1; - } - - { - let right: &[_] = right; - assert!(right[..right.len()] == [3, 4, 5]); - } - for p in right { - *p += 2; - } - } - - assert!(values == [2, 3, 5, 6, 7]); - } - - #[derive(Clone, PartialEq)] - struct Foo; - - #[test] - fn test_iter_zero_sized() { - let mut v = vec![Foo, Foo, Foo]; - assert_eq!(v.len(), 3); - let mut cnt = 0; - - for f in &v { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 3); - - for f in &v[1..3] { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 5); - - for f in &mut v { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 8); - - for f in v { - assert!(f == Foo); - cnt += 1; - } - assert_eq!(cnt, 11); - - let xs: [Foo; 3] = [Foo, Foo, Foo]; - cnt = 0; - for f in &xs { - assert!(*f == Foo); - cnt += 1; - } - assert!(cnt == 3); - } - - #[test] - fn test_shrink_to_fit() { - let mut xs = vec![0, 1, 2, 3]; - for i in 4..100 { - xs.push(i) - } - assert_eq!(xs.capacity(), 128); - xs.shrink_to_fit(); - assert_eq!(xs.capacity(), 100); - assert_eq!(xs, (0..100).collect::<Vec<_>>()); - } - - #[test] - fn test_starts_with() { - assert!(b"foobar".starts_with(b"foo")); - assert!(!b"foobar".starts_with(b"oob")); - assert!(!b"foobar".starts_with(b"bar")); - assert!(!b"foo".starts_with(b"foobar")); - assert!(!b"bar".starts_with(b"foobar")); - assert!(b"foobar".starts_with(b"foobar")); - let empty: &[u8] = &[]; - assert!(empty.starts_with(empty)); - assert!(!empty.starts_with(b"foo")); - assert!(b"foobar".starts_with(empty)); - } - - #[test] - fn test_ends_with() { - assert!(b"foobar".ends_with(b"bar")); - assert!(!b"foobar".ends_with(b"oba")); - assert!(!b"foobar".ends_with(b"foo")); - assert!(!b"foo".ends_with(b"foobar")); - assert!(!b"bar".ends_with(b"foobar")); - assert!(b"foobar".ends_with(b"foobar")); - let empty: &[u8] = &[]; - assert!(empty.ends_with(empty)); - assert!(!empty.ends_with(b"foo")); - assert!(b"foobar".ends_with(empty)); - } - - #[test] - fn test_mut_splitator() { - let mut xs = [0,1,0,2,3,0,0,4,5,0]; - assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); - for slice in xs.split_mut(|x| *x == 0) { - slice.reverse(); - } - assert!(xs == [0,1,0,3,2,0,0,5,4,0]); - - let mut xs = [0,1,0,2,3,0,0,4,5,0,6,7]; - for slice in xs.split_mut(|x| *x == 0).take(5) { - slice.reverse(); - } - assert!(xs == [0,1,0,3,2,0,0,5,4,0,6,7]); - } - - #[test] - fn test_mut_splitator_rev() { - let mut xs = [1,2,0,3,4,0,0,5,6,0]; - for slice in xs.split_mut(|x| *x == 0).rev().take(4) { - slice.reverse(); - } - assert!(xs == [1,2,0,4,3,0,0,6,5,0]); - } - - #[test] - fn test_get_mut() { - let mut v = [0,1,2]; - assert_eq!(v.get_mut(3), None); - v.get_mut(1).map(|e| *e = 7); - assert_eq!(v[1], 7); - let mut x = 2; - assert_eq!(v.get_mut(2), Some(&mut x)); - } - - #[test] - fn test_mut_chunks() { - use core::iter::ExactSizeIterator; - - let mut v = [0, 1, 2, 3, 4, 5, 6]; - assert_eq!(v.chunks_mut(2).len(), 4); - for (i, chunk) in v.chunks_mut(3).enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [0, 0, 0, 1, 1, 1, 2]; - assert!(v == result); - } - - #[test] - fn test_mut_chunks_rev() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - for (i, chunk) in v.chunks_mut(3).rev().enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [2, 2, 2, 1, 1, 1, 0]; - assert!(v == result); - } - - #[test] - #[should_panic] - fn test_mut_chunks_0() { - let mut v = [1, 2, 3, 4]; - let _it = v.chunks_mut(0); - } - - #[test] - fn test_mut_last() { - let mut x = [1, 2, 3, 4, 5]; - let h = x.last_mut(); - assert_eq!(*h.unwrap(), 5); - - let y: &mut [i32] = &mut []; - assert!(y.last_mut().is_none()); - } - - #[test] - fn test_to_vec() { - let xs: Box<_> = box [1, 2, 3]; - let ys = xs.to_vec(); - assert_eq!(ys, [1, 2, 3]); - } -} - -#[cfg(test)] -mod bench { - use prelude::*; - use core::mem; - use core::ptr; - use core::iter::repeat; - use std::rand::{weak_rng, Rng}; - use test::{Bencher, black_box}; - - #[bench] - fn iterator(b: &mut Bencher) { - // peculiar numbers to stop LLVM from optimising the summation - // out. - let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); - - b.iter(|| { - let mut sum = 0; - for x in &v { - sum += *x; - } - // sum == 11806, to stop dead code elimination. - if sum == 0 {panic!()} - }) - } - - #[bench] - fn mut_iterator(b: &mut Bencher) { - let mut v: Vec<_> = repeat(0).take(100).collect(); - - b.iter(|| { - let mut i = 0; - for x in &mut v { - *x = i; - i += 1; - } - }) - } - - #[bench] - fn concat(b: &mut Bencher) { - let xss: Vec<Vec<i32>> = - (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.concat(); - }); - } - - #[bench] - fn connect(b: &mut Bencher) { - let xss: Vec<Vec<i32>> = - (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.connect(&0) - }); - } - - #[bench] - fn push(b: &mut Bencher) { - let mut vec = Vec::<i32>::new(); - b.iter(|| { - vec.push(0); - black_box(&vec); - }); - } - - #[bench] - fn starts_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.starts_with(&vec) - }) - } - - #[bench] - fn starts_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.starts_with(&vec) - }) - } - - #[bench] - fn starts_with_diff_one_element_at_end(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..99).collect(); - match_vec.push(0); - b.iter(|| { - vec.starts_with(&match_vec) - }) - } - - #[bench] - fn ends_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.ends_with(&vec) - }) - } - - #[bench] - fn ends_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.ends_with(&vec) - }) - } - - #[bench] - fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..100).collect(); - match_vec[0] = 200; - b.iter(|| { - vec.starts_with(&match_vec) - }) - } - - #[bench] - fn contains_last_element(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.contains(&99) - }) - } - - #[bench] - fn zero_1kb_from_elem(b: &mut Bencher) { - b.iter(|| { - repeat(0u8).take(1024).collect::<Vec<_>>() - }); - } - - #[bench] - fn zero_1kb_set_memory(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::<u8>::with_capacity(1024); - unsafe { - let vp = v.as_mut_ptr(); - ptr::set_memory(vp, 0, 1024); - v.set_len(1024); - } - v - }); - } - - #[bench] - fn zero_1kb_loop_set(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::<u8>::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for i in 0..1024 { - v[i] = 0; - } - }); - } - - #[bench] - fn zero_1kb_mut_iter(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::<u8>::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for x in &mut v { - *x = 0; - } - v - }); - } - - #[bench] - fn random_inserts(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = repeat((0, 0)).take(30).collect(); - for _ in 0..100 { - let l = v.len(); - v.insert(rng.gen::<usize>() % (l + 1), - (1, 1)); - } - }) - } - #[bench] - fn random_removes(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = repeat((0, 0)).take(130).collect(); - for _ in 0..100 { - let l = v.len(); - v.remove(rng.gen::<usize>() % l); - } - }) - } - - #[bench] - fn sort_random_small(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::<u64>().take(5).collect(); - v.sort(); - }); - b.bytes = 5 * mem::size_of::<u64>() as u64; - } - - #[bench] - fn sort_random_medium(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::<u64>().take(100).collect(); - v.sort(); - }); - b.bytes = 100 * mem::size_of::<u64>() as u64; - } - - #[bench] - fn sort_random_large(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::<u64>().take(10000).collect(); - v.sort(); - }); - b.bytes = 10000 * mem::size_of::<u64>() as u64; - } - - #[bench] - fn sort_sorted(b: &mut Bencher) { - let mut v: Vec<_> = (0..10000).collect(); - b.iter(|| { - v.sort(); - }); - b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; - } - - type BigSortable = (u64, u64, u64, u64); - - #[bench] - fn sort_big_random_small(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::<BigSortable>().take(5) - .collect::<Vec<BigSortable>>(); - v.sort(); - }); - b.bytes = 5 * mem::size_of::<BigSortable>() as u64; - } - - #[bench] - fn sort_big_random_medium(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::<BigSortable>().take(100) - .collect::<Vec<BigSortable>>(); - v.sort(); - }); - b.bytes = 100 * mem::size_of::<BigSortable>() as u64; - } - - #[bench] - fn sort_big_random_large(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::<BigSortable>().take(10000) - .collect::<Vec<BigSortable>>(); - v.sort(); - }); - b.bytes = 10000 * mem::size_of::<BigSortable>() as u64; - } - - #[bench] - fn sort_big_sorted(b: &mut Bencher) { - let mut v: Vec<BigSortable> = (0..10000).map(|i| (i, i, i, i)).collect(); - b.iter(|| { - v.sort(); - }); - b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; - } -} diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index f749f54f2e4..b2273646b95 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -59,17 +59,21 @@ use self::DecompositionType::*; use core::clone::Clone; use core::iter::AdditiveIterator; use core::iter::{Iterator, IteratorExt, Extend}; +#[cfg(stage0)] use core::ops::Index; +#[cfg(stage0)] use core::ops::RangeFull; use core::option::Option::{self, Some, None}; use core::result::Result; use core::slice::AsSlice; use core::str as core_str; +#[cfg(stage0)] use unicode::char::CharExt; use unicode::str::{UnicodeStr, Utf16Encoder}; use vec_deque::VecDeque; use borrow::{Borrow, ToOwned}; +#[cfg(stage0)] use slice::SliceExt; use string::String; use unicode; @@ -415,6 +419,7 @@ Section: CowString Section: Trait implementations */ +#[cfg(stage0)] /// Any string that can be represented as a slice. #[stable(feature = "rust1", since = "1.0.0")] pub trait StrExt: Index<RangeFull, Output = str> { @@ -1539,6 +1544,7 @@ pub trait StrExt: Index<RangeFull, Output = str> { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl StrExt for str { fn slice(&self, begin: usize, end: usize) -> &str { @@ -1554,1667 +1560,1135 @@ impl StrExt for str { } } -#[cfg(test)] -mod tests { - use prelude::*; - - use core::iter::AdditiveIterator; - use super::from_utf8; - use super::Utf8Error; - - #[test] - fn test_le() { - assert!("" <= ""); - assert!("" <= "foo"); - assert!("foo" <= "foo"); - assert!("foo" != "bar"); - } - - #[test] - fn test_len() { - assert_eq!("".len(), 0); - assert_eq!("hello world".len(), 11); - assert_eq!("\x63".len(), 1); - assert_eq!("\u{a2}".len(), 2); - assert_eq!("\u{3c0}".len(), 2); - assert_eq!("\u{2620}".len(), 3); - assert_eq!("\u{1d11e}".len(), 4); - - assert_eq!("".chars().count(), 0); - assert_eq!("hello world".chars().count(), 11); - assert_eq!("\x63".chars().count(), 1); - assert_eq!("\u{a2}".chars().count(), 1); - assert_eq!("\u{3c0}".chars().count(), 1); - assert_eq!("\u{2620}".chars().count(), 1); - assert_eq!("\u{1d11e}".chars().count(), 1); - assert_eq!("ประเทศไทย中华Việt Nam".chars().count(), 19); - - assert_eq!("hello".width(false), 10); - assert_eq!("hello".width(true), 10); - assert_eq!("\0\0\0\0\0".width(false), 0); - assert_eq!("\0\0\0\0\0".width(true), 0); - assert_eq!("".width(false), 0); - assert_eq!("".width(true), 0); - assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(false), 4); - assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(true), 8); - } - - #[test] - fn test_find() { - assert_eq!("hello".find('l'), Some(2)); - assert_eq!("hello".find(|c:char| c == 'o'), Some(4)); - assert!("hello".find('x').is_none()); - assert!("hello".find(|c:char| c == 'x').is_none()); - assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30)); - assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30)); - } - - #[test] - fn test_rfind() { - assert_eq!("hello".rfind('l'), Some(3)); - assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4)); - assert!("hello".rfind('x').is_none()); - assert!("hello".rfind(|c:char| c == 'x').is_none()); - assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30)); - assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30)); - } - - #[test] - fn test_collect() { - let empty = String::from_str(""); - let s: String = empty.chars().collect(); - assert_eq!(empty, s); - let data = String::from_str("ประเทศไทย中"); - let s: String = data.chars().collect(); - assert_eq!(data, s); - } - - #[test] - fn test_into_bytes() { - let data = String::from_str("asdf"); - let buf = data.into_bytes(); - assert_eq!(b"asdf", buf); - } - - #[test] - fn test_find_str() { - // byte positions - assert_eq!("".find_str(""), Some(0)); - assert!("banana".find_str("apple pie").is_none()); - - let data = "abcabc"; - assert_eq!(data[0..6].find_str("ab"), Some(0)); - assert_eq!(data[2..6].find_str("ab"), Some(3 - 2)); - assert!(data[2..4].find_str("ab").is_none()); - - let string = "ประเทศไทย中华Việt Nam"; - let mut data = String::from_str(string); - data.push_str(string); - assert!(data.find_str("ไท华").is_none()); - assert_eq!(data[0..43].find_str(""), Some(0)); - assert_eq!(data[6..43].find_str(""), Some(6 - 6)); - - assert_eq!(data[0..43].find_str("ประ"), Some( 0)); - assert_eq!(data[0..43].find_str("ทศไ"), Some(12)); - assert_eq!(data[0..43].find_str("ย中"), Some(24)); - assert_eq!(data[0..43].find_str("iệt"), Some(34)); - assert_eq!(data[0..43].find_str("Nam"), Some(40)); - - assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43)); - assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43)); - assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43)); - assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43)); - assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43)); - } - - #[test] - fn test_slice_chars() { - fn t(a: &str, b: &str, start: usize) { - assert_eq!(a.slice_chars(start, start + b.chars().count()), b); - } - t("", "", 0); - t("hello", "llo", 2); - t("hello", "el", 1); - t("αβλ", "β", 1); - t("αβλ", "", 3); - assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8)); - } - - fn s(x: &str) -> String { x.to_string() } - - macro_rules! test_concat { - ($expected: expr, $string: expr) => { - { - let s: String = $string.concat(); - assert_eq!($expected, s); - } - } - } - - #[test] - fn test_concat_for_different_types() { - test_concat!("ab", vec![s("a"), s("b")]); - test_concat!("ab", vec!["a", "b"]); - test_concat!("ab", vec!["a", "b"]); - test_concat!("ab", vec![s("a"), s("b")]); +#[cfg(not(stage0))] +/// Any string that can be represented as a slice. +#[lang = "str"] +#[cfg(not(test))] +#[stable(feature = "rust1", since = "1.0.0")] +impl str { + /// Escapes each char in `s` with `char::escape_default`. + #[unstable(feature = "collections", + reason = "return type may change to be an iterator")] + pub fn escape_default(&self) -> String { + self.chars().flat_map(|c| c.escape_default()).collect() } - #[test] - fn test_concat_for_different_lengths() { - let empty: &[&str] = &[]; - test_concat!("", empty); - test_concat!("a", ["a"]); - test_concat!("ab", ["a", "b"]); - test_concat!("abc", ["", "a", "bc"]); + /// Escapes each char in `s` with `char::escape_unicode`. + #[unstable(feature = "collections", + reason = "return type may change to be an iterator")] + pub fn escape_unicode(&self) -> String { + self.chars().flat_map(|c| c.escape_unicode()).collect() } - macro_rules! test_connect { - ($expected: expr, $string: expr, $delim: expr) => { - { - let s = $string.connect($delim); - assert_eq!($expected, s); - } + /// Replaces all occurrences of one string with another. + /// + /// `replace` takes two arguments, a sub-`&str` to find in `self`, and a second `&str` to + /// replace it with. If the original `&str` isn't found, no change occurs. + /// + /// # Examples + /// + /// ``` + /// let s = "this is old"; + /// + /// assert_eq!(s.replace("old", "new"), "this is new"); + /// ``` + /// + /// When a `&str` isn't found: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s.replace("cookie monster", "little lamb"), s); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn replace(&self, from: &str, to: &str) -> String { + let mut result = String::new(); + let mut last_end = 0; + for (start, end) in self.match_indices(from) { + result.push_str(unsafe { self.slice_unchecked(last_end, start) }); + result.push_str(to); + last_end = end; } + result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); + result } - #[test] - fn test_connect_for_different_types() { - test_connect!("a-b", ["a", "b"], "-"); - let hyphen = "-".to_string(); - test_connect!("a-b", [s("a"), s("b")], &*hyphen); - test_connect!("a-b", vec!["a", "b"], &*hyphen); - test_connect!("a-b", &*vec!["a", "b"], "-"); - test_connect!("a-b", vec![s("a"), s("b")], "-"); - } - - #[test] - fn test_connect_for_different_lengths() { - let empty: &[&str] = &[]; - test_connect!("", empty, "-"); - test_connect!("a", ["a"], "-"); - test_connect!("a-b", ["a", "b"], "-"); - test_connect!("-a-bc", ["", "a", "bc"], "-"); - } - - #[test] - fn test_unsafe_slice() { - assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)}); - assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)}); - assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)}); - fn a_million_letter_a() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("aaaaaaaaaa"); - i += 1; - } - rs - } - fn half_a_million_letter_a() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("aaaaa"); - i += 1; - } - rs - } - let letters = a_million_letter_a(); - assert!(half_a_million_letter_a() == - unsafe {String::from_str(letters.slice_unchecked( - 0, - 500000))}); - } - - #[test] - fn test_starts_with() { - assert!(("".starts_with(""))); - assert!(("abc".starts_with(""))); - assert!(("abc".starts_with("a"))); - assert!((!"a".starts_with("abc"))); - assert!((!"".starts_with("abc"))); - assert!((!"ödd".starts_with("-"))); - assert!(("ödd".starts_with("öd"))); - } - - #[test] - fn test_ends_with() { - assert!(("".ends_with(""))); - assert!(("abc".ends_with(""))); - assert!(("abc".ends_with("c"))); - assert!((!"a".ends_with("abc"))); - assert!((!"".ends_with("abc"))); - assert!((!"ddö".ends_with("-"))); - assert!(("ddö".ends_with("dö"))); - } - - #[test] - fn test_is_empty() { - assert!("".is_empty()); - assert!(!"a".is_empty()); - } - - #[test] - fn test_replace() { - let a = "a"; - assert_eq!("".replace(a, "b"), String::from_str("")); - assert_eq!("a".replace(a, "b"), String::from_str("b")); - assert_eq!("ab".replace(a, "b"), String::from_str("bb")); - let test = "test"; - assert!(" test test ".replace(test, "toast") == - String::from_str(" toast toast ")); - assert_eq!(" test test ".replace(test, ""), String::from_str(" ")); - } - - #[test] - fn test_replace_2a() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let a = "ประเ"; - let a2 = "دولة الكويتทศไทย中华"; - assert_eq!(data.replace(a, repl), a2); - } - - #[test] - fn test_replace_2b() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let b = "ะเ"; - let b2 = "ปรدولة الكويتทศไทย中华"; - assert_eq!(data.replace(b, repl), b2); - } - - #[test] - fn test_replace_2c() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let c = "中华"; - let c2 = "ประเทศไทยدولة الكويت"; - assert_eq!(data.replace(c, repl), c2); - } - - #[test] - fn test_replace_2d() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let d = "ไท华"; - assert_eq!(data.replace(d, repl), data); - } - - #[test] - fn test_slice() { - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); - assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3)); - - let data = "ประเทศไทย中华"; - assert_eq!("ป", data.slice(0, 3)); - assert_eq!("ร", data.slice(3, 6)); - assert_eq!("", data.slice(3, 3)); - assert_eq!("华", data.slice(30, 33)); - - fn a_million_letter_x() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("华华华华华华华华华华"); - i += 1; - } - rs - } - fn half_a_million_letter_x() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("华华华华华"); - i += 1; - } - rs - } - let letters = a_million_letter_x(); - assert!(half_a_million_letter_x() == - String::from_str(letters.slice(0, 3 * 500000))); - } - - #[test] - fn test_slice_2() { - let ss = "中华Việt Nam"; - - assert_eq!("华", ss.slice(3, 6)); - assert_eq!("Việt Nam", ss.slice(6, 16)); - - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); - - assert_eq!("中", ss.slice(0, 3)); - assert_eq!("华V", ss.slice(3, 7)); - assert_eq!("", ss.slice(3, 3)); - /*0: 中 - 3: 华 - 6: V - 7: i - 8: ệ - 11: t - 12: - 13: N - 14: a - 15: m */ - } - - #[test] - #[should_panic] - fn test_slice_fail() { - "中华Việt Nam".slice(0, 2); - } - - #[test] - fn test_slice_from() { - assert_eq!("abcd".slice_from(0), "abcd"); - assert_eq!("abcd".slice_from(2), "cd"); - assert_eq!("abcd".slice_from(4), ""); - } - #[test] - fn test_slice_to() { - assert_eq!("abcd".slice_to(0), ""); - assert_eq!("abcd".slice_to(2), "ab"); - assert_eq!("abcd".slice_to(4), "abcd"); - } - - #[test] - fn test_trim_left_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** "); - assert_eq!(" *** *** ".trim_left_matches(chars), ""); - assert_eq!("foo *** ".trim_left_matches(chars), "foo *** "); - - assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12"); - assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); - } - - #[test] - fn test_trim_right_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo"); - assert_eq!(" *** *** ".trim_right_matches(chars), ""); - assert_eq!(" *** foo".trim_right_matches(chars), " *** foo"); - - assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar"); - assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); - } - - #[test] - fn test_trim_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_matches(chars), "foo"); - assert_eq!(" *** *** ".trim_matches(chars), ""); - assert_eq!("foo".trim_matches(chars), "foo"); - - assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar"); - assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); - } - - #[test] - fn test_trim_left() { - assert_eq!("".trim_left(), ""); - assert_eq!("a".trim_left(), "a"); - assert_eq!(" ".trim_left(), ""); - assert_eq!(" blah".trim_left(), "blah"); - assert_eq!(" \u{3000} wut".trim_left(), "wut"); - assert_eq!("hey ".trim_left(), "hey "); - } - - #[test] - fn test_trim_right() { - assert_eq!("".trim_right(), ""); - assert_eq!("a".trim_right(), "a"); - assert_eq!(" ".trim_right(), ""); - assert_eq!("blah ".trim_right(), "blah"); - assert_eq!("wut \u{3000} ".trim_right(), "wut"); - assert_eq!(" hey".trim_right(), " hey"); - } - - #[test] - fn test_trim() { - assert_eq!("".trim(), ""); - assert_eq!("a".trim(), "a"); - assert_eq!(" ".trim(), ""); - assert_eq!(" blah ".trim(), "blah"); - assert_eq!("\nwut \u{3000} ".trim(), "wut"); - assert_eq!(" hey dude ".trim(), "hey dude"); - } - - #[test] - fn test_is_whitespace() { - assert!("".chars().all(|c| c.is_whitespace())); - assert!(" ".chars().all(|c| c.is_whitespace())); - assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space - assert!(" \n\t ".chars().all(|c| c.is_whitespace())); - assert!(!" _ ".chars().all(|c| c.is_whitespace())); - } - - #[test] - fn test_slice_shift_char() { - let data = "ประเทศไทย中"; - assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中"))); - } - - #[test] - fn test_slice_shift_char_2() { - let empty = ""; - assert_eq!(empty.slice_shift_char(), None); - } - - #[test] - fn test_is_utf8() { - // deny overlong encodings - assert!(from_utf8(&[0xc0, 0x80]).is_err()); - assert!(from_utf8(&[0xc0, 0xae]).is_err()); - assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); - assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); - assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); - assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); - assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); - - // deny surrogates - assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); - assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); - - assert!(from_utf8(&[0xC2, 0x80]).is_ok()); - assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); - assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); - assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); - assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); - assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); - assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); - assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); - } - - #[test] - fn test_is_utf16() { - use unicode::str::is_utf16; - macro_rules! pos { - ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } } - } - - // non-surrogates - pos!(&[0x0000], - &[0x0001, 0x0002], - &[0xD7FF], - &[0xE000]); - - // surrogate pairs (randomly generated with Python 3's - // .encode('utf-16be')) - pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45], - &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14], - &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]); - - // mixtures (also random) - pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65], - &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006], - &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]); - - // negative tests - macro_rules! neg { - ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } } - } - - neg!( - // surrogate + regular unit - &[0xdb45, 0x0000], - // surrogate + lead surrogate - &[0xd900, 0xd900], - // unterminated surrogate - &[0xd8ff], - // trail surrogate without a lead - &[0xddb7]); - - // random byte sequences that Python 3's .decode('utf-16be') - // failed on - neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7], - &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3], - &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca], - &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278], - &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e], - &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5], - &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee], - &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7], - &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a], - &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a], - &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe], - &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf], - &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e], - &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5], - &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f], - &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b], - &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7], - &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9], - &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8], - &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282], - &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]); - } - - #[test] - fn test_as_bytes() { - // no null - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let b: &[u8] = &[]; - assert_eq!("".as_bytes(), b); - assert_eq!("abc".as_bytes(), b"abc"); - assert_eq!("ศไทย中华Việt Nam".as_bytes(), v); - } - - #[test] - #[should_panic] - fn test_as_bytes_fail() { - // Don't double free. (I'm not sure if this exercises the - // original problem code path anymore.) - let s = String::from_str(""); - let _bytes = s.as_bytes(); - panic!(); - } - - #[test] - fn test_as_ptr() { - let buf = "hello".as_ptr(); - unsafe { - assert_eq!(*buf.offset(0), b'h'); - assert_eq!(*buf.offset(1), b'e'); - assert_eq!(*buf.offset(2), b'l'); - assert_eq!(*buf.offset(3), b'l'); - assert_eq!(*buf.offset(4), b'o'); + /// Returns an iterator over the string in Unicode Normalization Form D + /// (canonical decomposition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfd_chars(&self) -> Decompositions { + Decompositions { + iter: self[..].chars(), + buffer: Vec::new(), + sorted: false, + kind: Canonical } } - #[test] - fn test_subslice_offset() { - let a = "kernelsprite"; - let b = &a[7..a.len()]; - let c = &a[0..a.len() - 6]; - assert_eq!(a.subslice_offset(b), 7); - assert_eq!(a.subslice_offset(c), 0); - - let string = "a\nb\nc"; - let lines: Vec<&str> = string.lines().collect(); - assert_eq!(string.subslice_offset(lines[0]), 0); - assert_eq!(string.subslice_offset(lines[1]), 2); - assert_eq!(string.subslice_offset(lines[2]), 4); - } - - #[test] - #[should_panic] - fn test_subslice_offset_2() { - let a = "alchemiter"; - let b = "cruxtruder"; - a.subslice_offset(b); - } - - #[test] - fn vec_str_conversions() { - let s1: String = String::from_str("All mimsy were the borogoves"); - - let v: Vec<u8> = s1.as_bytes().to_vec(); - let s2: String = String::from_str(from_utf8(&v).unwrap()); - let mut i = 0; - let n1 = s1.len(); - let n2 = v.len(); - assert_eq!(n1, n2); - while i < n1 { - let a: u8 = s1.as_bytes()[i]; - let b: u8 = s2.as_bytes()[i]; - debug!("{}", a); - debug!("{}", b); - assert_eq!(a, b); - i += 1; + /// Returns an iterator over the string in Unicode Normalization Form KD + /// (compatibility decomposition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfkd_chars(&self) -> Decompositions { + Decompositions { + iter: self[..].chars(), + buffer: Vec::new(), + sorted: false, + kind: Compatible } } - #[test] - fn test_contains() { - assert!("abcde".contains("bcd")); - assert!("abcde".contains("abcd")); - assert!("abcde".contains("bcde")); - assert!("abcde".contains("")); - assert!("".contains("")); - assert!(!"abcde".contains("def")); - assert!(!"".contains("a")); - - let data = "ประเทศไทย中华Việt Nam"; - assert!(data.contains("ประเ")); - assert!(data.contains("ะเ")); - assert!(data.contains("中华")); - assert!(!data.contains("ไท华")); - } - - #[test] - fn test_contains_char() { - assert!("abc".contains_char('b')); - assert!("a".contains_char('a')); - assert!(!"abc".contains_char('d')); - assert!(!"".contains_char('a')); - } - - #[test] - fn test_char_at() { - let s = "ศไทย中华Việt Nam"; - let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = 0; - for ch in &v { - assert!(s.char_at(pos) == *ch); - pos += ch.to_string().len(); + /// An Iterator over the string in Unicode Normalization Form C + /// (canonical decomposition followed by canonical composition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfc_chars(&self) -> Recompositions { + Recompositions { + iter: self.nfd_chars(), + state: Composing, + buffer: VecDeque::new(), + composee: None, + last_ccc: None } } - #[test] - fn test_char_at_reverse() { - let s = "ศไทย中华Việt Nam"; - let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = s.len(); - for ch in v.iter().rev() { - assert!(s.char_at_reverse(pos) == *ch); - pos -= ch.to_string().len(); + /// An Iterator over the string in Unicode Normalization Form KC + /// (compatibility decomposition followed by canonical composition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfkc_chars(&self) -> Recompositions { + Recompositions { + iter: self.nfkd_chars(), + state: Composing, + buffer: VecDeque::new(), + composee: None, + last_ccc: None } } - #[test] - fn test_escape_unicode() { - assert_eq!("abc".escape_unicode(), - String::from_str("\\u{61}\\u{62}\\u{63}")); - assert_eq!("a c".escape_unicode(), - String::from_str("\\u{61}\\u{20}\\u{63}")); - assert_eq!("\r\n\t".escape_unicode(), - String::from_str("\\u{d}\\u{a}\\u{9}")); - assert_eq!("'\"\\".escape_unicode(), - String::from_str("\\u{27}\\u{22}\\u{5c}")); - assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), - String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}")); - assert_eq!("\u{100}\u{ffff}".escape_unicode(), - String::from_str("\\u{100}\\u{ffff}")); - assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), - String::from_str("\\u{10000}\\u{10ffff}")); - assert_eq!("ab\u{fb00}".escape_unicode(), - String::from_str("\\u{61}\\u{62}\\u{fb00}")); - assert_eq!("\u{1d4ea}\r".escape_unicode(), - String::from_str("\\u{1d4ea}\\u{d}")); - } - - #[test] - fn test_escape_default() { - assert_eq!("abc".escape_default(), String::from_str("abc")); - assert_eq!("a c".escape_default(), String::from_str("a c")); - assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t")); - assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\")); - assert_eq!("\u{100}\u{ffff}".escape_default(), - String::from_str("\\u{100}\\u{ffff}")); - assert_eq!("\u{10000}\u{10ffff}".escape_default(), - String::from_str("\\u{10000}\\u{10ffff}")); - assert_eq!("ab\u{fb00}".escape_default(), - String::from_str("ab\\u{fb00}")); - assert_eq!("\u{1d4ea}\r".escape_default(), - String::from_str("\\u{1d4ea}\\r")); - } - - #[test] - fn test_total_ord() { - "1234".cmp("123") == Greater; - "123".cmp("1234") == Less; - "1234".cmp("1234") == Equal; - "12345555".cmp("123456") == Less; - "22".cmp("1234") == Greater; - } - - #[test] - fn test_char_range_at() { - let data = "b¢€𤭢𤭢€¢b"; - assert_eq!('b', data.char_range_at(0).ch); - assert_eq!('¢', data.char_range_at(1).ch); - assert_eq!('€', data.char_range_at(3).ch); - assert_eq!('𤭢', data.char_range_at(6).ch); - assert_eq!('𤭢', data.char_range_at(10).ch); - assert_eq!('€', data.char_range_at(14).ch); - assert_eq!('¢', data.char_range_at(17).ch); - assert_eq!('b', data.char_range_at(19).ch); - } - - #[test] - fn test_char_range_at_reverse_underflow() { - assert_eq!("abc".char_range_at_reverse(0).next, 0); - } - - #[test] - fn test_iterator() { - let s = "ศไทย中华Việt Nam"; - let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - - let mut pos = 0; - let it = s.chars(); - - for c in it { - assert_eq!(c, v[pos]); - pos += 1; - } - assert_eq!(pos, v.len()); + /// Returns `true` if `self` contains another `&str`. + /// + /// # Examples + /// + /// ``` + /// assert!("bananas".contains("nana")); + /// + /// assert!(!"bananas".contains("foobar")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::contains(&self[..], pat) } - #[test] - fn test_rev_iterator() { - let s = "ศไทย中华Việt Nam"; - let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; - - let mut pos = 0; - let it = s.chars().rev(); - - for c in it { - assert_eq!(c, v[pos]); - pos += 1; - } - assert_eq!(pos, v.len()); + /// Returns `true` if `self` contains a `char`. + /// + /// # Examples + /// + /// ``` + /// assert!("hello".contains_char('e')); + /// + /// assert!(!"hello".contains_char('z')); + /// ``` + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use `contains()` with a char")] + pub fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::contains_char(&self[..], pat) } - #[test] - fn test_chars_decoding() { - let mut bytes = [0; 4]; - for c in (0..0x110000).filter_map(|c| ::core::char::from_u32(c)) { - let len = c.encode_utf8(&mut bytes).unwrap_or(0); - let s = ::core::str::from_utf8(&bytes[..len]).unwrap(); - if Some(c) != s.chars().next() { - panic!("character {:x}={} does not decode correctly", c as u32, c); - } - } + /// An iterator over the codepoints of `self`. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<char> = "abc åäö".chars().collect(); + /// + /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn chars(&self) -> Chars { + core_str::StrExt::chars(&self[..]) } - #[test] - fn test_chars_rev_decoding() { - let mut bytes = [0; 4]; - for c in (0..0x110000).filter_map(|c| ::core::char::from_u32(c)) { - let len = c.encode_utf8(&mut bytes).unwrap_or(0); - let s = ::core::str::from_utf8(&bytes[..len]).unwrap(); - if Some(c) != s.chars().rev().next() { - panic!("character {:x}={} does not decode correctly", c as u32, c); - } - } + /// An iterator over the bytes of `self`. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<u8> = "bors".bytes().collect(); + /// + /// assert_eq!(v, b"bors".to_vec()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bytes(&self) -> Bytes { + core_str::StrExt::bytes(&self[..]) } - #[test] - fn test_iterator_clone() { - let s = "ศไทย中华Việt Nam"; - let mut it = s.chars(); - it.next(); - assert!(it.clone().zip(it).all(|(x,y)| x == y)); + /// An iterator over the characters of `self` and their byte offsets. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<(usize, char)> = "abc".char_indices().collect(); + /// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')]; + /// + /// assert_eq!(v, b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn char_indices(&self) -> CharIndices { + core_str::StrExt::char_indices(&self[..]) } - #[test] - fn test_bytesator() { - let s = "ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = 0; - - for b in s.bytes() { - assert_eq!(b, v[pos]); - pos += 1; - } + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern. + /// + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { + core_str::StrExt::split(&self[..], pat) } - #[test] - fn test_bytes_revator() { - let s = "ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = v.len(); - - for b in s.bytes().rev() { - pos -= 1; - assert_eq!(b, v[pos]); - } + /// An iterator over substrings of `self`, separated by characters matched by a pattern, + /// restricted to splitting at most `count` times. + /// + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect(); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); + /// + /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); + /// + /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def2ghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { + core_str::StrExt::splitn(&self[..], count, pat) } - #[test] - fn test_char_indicesator() { - let s = "ศไทย中华Việt Nam"; - let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27]; - let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - - let mut pos = 0; - let it = s.char_indices(); - - for c in it { - assert_eq!(c, (p[pos], v[pos])); - pos += 1; - } - assert_eq!(pos, v.len()); - assert_eq!(pos, p.len()); + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern. + /// + /// Equivalent to `split`, except that the trailing substring is skipped if empty. + /// + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "B"]); + /// + /// let v: Vec<&str> = "A..B..".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "", "B", ""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { + core_str::StrExt::split_terminator(&self[..], pat) } - #[test] - fn test_char_indices_revator() { - let s = "ศไทย中华Việt Nam"; - let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0]; - let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; - - let mut pos = 0; - let it = s.char_indices().rev(); - - for c in it { - assert_eq!(c, (p[pos], v[pos])); - pos += 1; - } - assert_eq!(pos, v.len()); - assert_eq!(pos, p.len()); + /// An iterator over substrings of `self`, separated by characters matched by a pattern, + /// starting from the end of the string. + /// + /// Restricted to splitting at most `count` times. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect(); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["ghi", "abc1def"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> { + core_str::StrExt::rsplitn(&self[..], count, pat) } - #[test] - fn test_splitn_char_iterator() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.splitn(3, ' ').collect(); - assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect(); - assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); - - // Unicode - let split: Vec<&str> = data.splitn(3, 'ä').collect(); - assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect(); - assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + /// An iterator over the start and end indices of the disjoint matches of a `&str` within + /// `self`. + /// + /// That is, each returned value `(start, end)` satisfies `self.slice(start, end) == sep`. For + /// matches of `sep` within `self` that overlap, only the indices corresponding to the first + /// match are returned. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0,3), (6,9), (12,15)]); + /// + /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1,4), (4,7)]); + /// + /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, 3)]); // only the first `aba` + /// ``` + #[unstable(feature = "collections", + reason = "might have its iterator type changed")] + // NB: Right now MatchIndices yields `(usize, usize)`, + // but it would be more consistent and useful to return `(usize, &str)` + pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { + core_str::StrExt::match_indices(&self[..], pat) } - #[test] - fn test_split_char_iterator_no_trailing() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.split('\n').collect(); - assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); - - let split: Vec<&str> = data.split_terminator('\n').collect(); - assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); + /// An iterator over the substrings of `self` separated by a `&str`. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect(); + /// assert_eq!(v, ["", "XXX", "YYY", ""]); + /// + /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect(); + /// assert_eq!(v, ["1", "", "2"]); + /// ``` + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")] + #[allow(deprecated) /* for SplitStr */] + pub fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> { + core_str::StrExt::split_str(&self[..], pat) } - #[test] - fn test_words() { - let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; - let words: Vec<&str> = data.words().collect(); - assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) + /// An iterator over the lines of a string, separated by `\n`. + /// + /// This does not include the empty string after a trailing `\n`. + /// + /// # Examples + /// + /// ``` + /// let four_lines = "foo\nbar\n\nbaz"; + /// let v: Vec<&str> = four_lines.lines().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + /// + /// Leaving off the trailing character: + /// + /// ``` + /// let four_lines = "foo\nbar\n\nbaz\n"; + /// let v: Vec<&str> = four_lines.lines().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn lines(&self) -> Lines { + core_str::StrExt::lines(&self[..]) } - #[test] - fn test_nfd_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfd_chars().collect::<String>(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "d\u{307}\u{1c4}"); - t!("\u{2026}", "\u{2026}"); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); - t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); - t!("a\u{301}", "a\u{301}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); - t!("\u{ac1c}", "\u{1100}\u{1162}"); - } - - #[test] - fn test_nfkd_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfkd_chars().collect::<String>(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "d\u{307}DZ\u{30c}"); - t!("\u{2026}", "..."); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); - t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); - t!("a\u{301}", "a\u{301}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); - t!("\u{ac1c}", "\u{1100}\u{1162}"); - } - - #[test] - fn test_nfc_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfc_chars().collect::<String>(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "\u{1e0b}\u{1c4}"); - t!("\u{2026}", "\u{2026}"); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); - t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); - t!("a\u{301}", "\u{e1}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{d4db}"); - t!("\u{ac1c}", "\u{ac1c}"); - t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); - } - - #[test] - fn test_nfkc_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfkc_chars().collect::<String>(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "\u{1e0b}D\u{17d}"); - t!("\u{2026}", "..."); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); - t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); - t!("a\u{301}", "\u{e1}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{d4db}"); - t!("\u{ac1c}", "\u{ac1c}"); - t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); - } - - #[test] - fn test_lines() { - let data = "\nMäry häd ä little lämb\n\nLittle lämb\n"; - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); - - let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); - } - - #[test] - fn test_graphemes() { - use core::iter::order; - // official Unicode test data - // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt - let test_same: [(_, &[_]); 325] = [ - ("\u{20}\u{20}", &["\u{20}", "\u{20}"]), - ("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]), - ("\u{20}\u{D}", &["\u{20}", "\u{D}"]), - ("\u{20}\u{308}\u{D}", &["\u{20}\u{308}", "\u{D}"]), - ("\u{20}\u{A}", &["\u{20}", "\u{A}"]), - ("\u{20}\u{308}\u{A}", &["\u{20}\u{308}", "\u{A}"]), - ("\u{20}\u{1}", &["\u{20}", "\u{1}"]), - ("\u{20}\u{308}\u{1}", &["\u{20}\u{308}", "\u{1}"]), - ("\u{20}\u{300}", &["\u{20}\u{300}"]), - ("\u{20}\u{308}\u{300}", &["\u{20}\u{308}\u{300}"]), - ("\u{20}\u{1100}", &["\u{20}", "\u{1100}"]), - ("\u{20}\u{308}\u{1100}", &["\u{20}\u{308}", "\u{1100}"]), - ("\u{20}\u{1160}", &["\u{20}", "\u{1160}"]), - ("\u{20}\u{308}\u{1160}", &["\u{20}\u{308}", "\u{1160}"]), - ("\u{20}\u{11A8}", &["\u{20}", "\u{11A8}"]), - ("\u{20}\u{308}\u{11A8}", &["\u{20}\u{308}", "\u{11A8}"]), - ("\u{20}\u{AC00}", &["\u{20}", "\u{AC00}"]), - ("\u{20}\u{308}\u{AC00}", &["\u{20}\u{308}", "\u{AC00}"]), - ("\u{20}\u{AC01}", &["\u{20}", "\u{AC01}"]), - ("\u{20}\u{308}\u{AC01}", &["\u{20}\u{308}", "\u{AC01}"]), - ("\u{20}\u{1F1E6}", &["\u{20}", "\u{1F1E6}"]), - ("\u{20}\u{308}\u{1F1E6}", &["\u{20}\u{308}", "\u{1F1E6}"]), - ("\u{20}\u{378}", &["\u{20}", "\u{378}"]), - ("\u{20}\u{308}\u{378}", &["\u{20}\u{308}", "\u{378}"]), - ("\u{D}\u{20}", &["\u{D}", "\u{20}"]), - ("\u{D}\u{308}\u{20}", &["\u{D}", "\u{308}", "\u{20}"]), - ("\u{D}\u{D}", &["\u{D}", "\u{D}"]), - ("\u{D}\u{308}\u{D}", &["\u{D}", "\u{308}", "\u{D}"]), - ("\u{D}\u{A}", &["\u{D}\u{A}"]), - ("\u{D}\u{308}\u{A}", &["\u{D}", "\u{308}", "\u{A}"]), - ("\u{D}\u{1}", &["\u{D}", "\u{1}"]), - ("\u{D}\u{308}\u{1}", &["\u{D}", "\u{308}", "\u{1}"]), - ("\u{D}\u{300}", &["\u{D}", "\u{300}"]), - ("\u{D}\u{308}\u{300}", &["\u{D}", "\u{308}\u{300}"]), - ("\u{D}\u{903}", &["\u{D}", "\u{903}"]), - ("\u{D}\u{1100}", &["\u{D}", "\u{1100}"]), - ("\u{D}\u{308}\u{1100}", &["\u{D}", "\u{308}", "\u{1100}"]), - ("\u{D}\u{1160}", &["\u{D}", "\u{1160}"]), - ("\u{D}\u{308}\u{1160}", &["\u{D}", "\u{308}", "\u{1160}"]), - ("\u{D}\u{11A8}", &["\u{D}", "\u{11A8}"]), - ("\u{D}\u{308}\u{11A8}", &["\u{D}", "\u{308}", "\u{11A8}"]), - ("\u{D}\u{AC00}", &["\u{D}", "\u{AC00}"]), - ("\u{D}\u{308}\u{AC00}", &["\u{D}", "\u{308}", "\u{AC00}"]), - ("\u{D}\u{AC01}", &["\u{D}", "\u{AC01}"]), - ("\u{D}\u{308}\u{AC01}", &["\u{D}", "\u{308}", "\u{AC01}"]), - ("\u{D}\u{1F1E6}", &["\u{D}", "\u{1F1E6}"]), - ("\u{D}\u{308}\u{1F1E6}", &["\u{D}", "\u{308}", "\u{1F1E6}"]), - ("\u{D}\u{378}", &["\u{D}", "\u{378}"]), - ("\u{D}\u{308}\u{378}", &["\u{D}", "\u{308}", "\u{378}"]), - ("\u{A}\u{20}", &["\u{A}", "\u{20}"]), - ("\u{A}\u{308}\u{20}", &["\u{A}", "\u{308}", "\u{20}"]), - ("\u{A}\u{D}", &["\u{A}", "\u{D}"]), - ("\u{A}\u{308}\u{D}", &["\u{A}", "\u{308}", "\u{D}"]), - ("\u{A}\u{A}", &["\u{A}", "\u{A}"]), - ("\u{A}\u{308}\u{A}", &["\u{A}", "\u{308}", "\u{A}"]), - ("\u{A}\u{1}", &["\u{A}", "\u{1}"]), - ("\u{A}\u{308}\u{1}", &["\u{A}", "\u{308}", "\u{1}"]), - ("\u{A}\u{300}", &["\u{A}", "\u{300}"]), - ("\u{A}\u{308}\u{300}", &["\u{A}", "\u{308}\u{300}"]), - ("\u{A}\u{903}", &["\u{A}", "\u{903}"]), - ("\u{A}\u{1100}", &["\u{A}", "\u{1100}"]), - ("\u{A}\u{308}\u{1100}", &["\u{A}", "\u{308}", "\u{1100}"]), - ("\u{A}\u{1160}", &["\u{A}", "\u{1160}"]), - ("\u{A}\u{308}\u{1160}", &["\u{A}", "\u{308}", "\u{1160}"]), - ("\u{A}\u{11A8}", &["\u{A}", "\u{11A8}"]), - ("\u{A}\u{308}\u{11A8}", &["\u{A}", "\u{308}", "\u{11A8}"]), - ("\u{A}\u{AC00}", &["\u{A}", "\u{AC00}"]), - ("\u{A}\u{308}\u{AC00}", &["\u{A}", "\u{308}", "\u{AC00}"]), - ("\u{A}\u{AC01}", &["\u{A}", "\u{AC01}"]), - ("\u{A}\u{308}\u{AC01}", &["\u{A}", "\u{308}", "\u{AC01}"]), - ("\u{A}\u{1F1E6}", &["\u{A}", "\u{1F1E6}"]), - ("\u{A}\u{308}\u{1F1E6}", &["\u{A}", "\u{308}", "\u{1F1E6}"]), - ("\u{A}\u{378}", &["\u{A}", "\u{378}"]), - ("\u{A}\u{308}\u{378}", &["\u{A}", "\u{308}", "\u{378}"]), - ("\u{1}\u{20}", &["\u{1}", "\u{20}"]), - ("\u{1}\u{308}\u{20}", &["\u{1}", "\u{308}", "\u{20}"]), - ("\u{1}\u{D}", &["\u{1}", "\u{D}"]), - ("\u{1}\u{308}\u{D}", &["\u{1}", "\u{308}", "\u{D}"]), - ("\u{1}\u{A}", &["\u{1}", "\u{A}"]), - ("\u{1}\u{308}\u{A}", &["\u{1}", "\u{308}", "\u{A}"]), - ("\u{1}\u{1}", &["\u{1}", "\u{1}"]), - ("\u{1}\u{308}\u{1}", &["\u{1}", "\u{308}", "\u{1}"]), - ("\u{1}\u{300}", &["\u{1}", "\u{300}"]), - ("\u{1}\u{308}\u{300}", &["\u{1}", "\u{308}\u{300}"]), - ("\u{1}\u{903}", &["\u{1}", "\u{903}"]), - ("\u{1}\u{1100}", &["\u{1}", "\u{1100}"]), - ("\u{1}\u{308}\u{1100}", &["\u{1}", "\u{308}", "\u{1100}"]), - ("\u{1}\u{1160}", &["\u{1}", "\u{1160}"]), - ("\u{1}\u{308}\u{1160}", &["\u{1}", "\u{308}", "\u{1160}"]), - ("\u{1}\u{11A8}", &["\u{1}", "\u{11A8}"]), - ("\u{1}\u{308}\u{11A8}", &["\u{1}", "\u{308}", "\u{11A8}"]), - ("\u{1}\u{AC00}", &["\u{1}", "\u{AC00}"]), - ("\u{1}\u{308}\u{AC00}", &["\u{1}", "\u{308}", "\u{AC00}"]), - ("\u{1}\u{AC01}", &["\u{1}", "\u{AC01}"]), - ("\u{1}\u{308}\u{AC01}", &["\u{1}", "\u{308}", "\u{AC01}"]), - ("\u{1}\u{1F1E6}", &["\u{1}", "\u{1F1E6}"]), - ("\u{1}\u{308}\u{1F1E6}", &["\u{1}", "\u{308}", "\u{1F1E6}"]), - ("\u{1}\u{378}", &["\u{1}", "\u{378}"]), - ("\u{1}\u{308}\u{378}", &["\u{1}", "\u{308}", "\u{378}"]), - ("\u{300}\u{20}", &["\u{300}", "\u{20}"]), - ("\u{300}\u{308}\u{20}", &["\u{300}\u{308}", "\u{20}"]), - ("\u{300}\u{D}", &["\u{300}", "\u{D}"]), - ("\u{300}\u{308}\u{D}", &["\u{300}\u{308}", "\u{D}"]), - ("\u{300}\u{A}", &["\u{300}", "\u{A}"]), - ("\u{300}\u{308}\u{A}", &["\u{300}\u{308}", "\u{A}"]), - ("\u{300}\u{1}", &["\u{300}", "\u{1}"]), - ("\u{300}\u{308}\u{1}", &["\u{300}\u{308}", "\u{1}"]), - ("\u{300}\u{300}", &["\u{300}\u{300}"]), - ("\u{300}\u{308}\u{300}", &["\u{300}\u{308}\u{300}"]), - ("\u{300}\u{1100}", &["\u{300}", "\u{1100}"]), - ("\u{300}\u{308}\u{1100}", &["\u{300}\u{308}", "\u{1100}"]), - ("\u{300}\u{1160}", &["\u{300}", "\u{1160}"]), - ("\u{300}\u{308}\u{1160}", &["\u{300}\u{308}", "\u{1160}"]), - ("\u{300}\u{11A8}", &["\u{300}", "\u{11A8}"]), - ("\u{300}\u{308}\u{11A8}", &["\u{300}\u{308}", "\u{11A8}"]), - ("\u{300}\u{AC00}", &["\u{300}", "\u{AC00}"]), - ("\u{300}\u{308}\u{AC00}", &["\u{300}\u{308}", "\u{AC00}"]), - ("\u{300}\u{AC01}", &["\u{300}", "\u{AC01}"]), - ("\u{300}\u{308}\u{AC01}", &["\u{300}\u{308}", "\u{AC01}"]), - ("\u{300}\u{1F1E6}", &["\u{300}", "\u{1F1E6}"]), - ("\u{300}\u{308}\u{1F1E6}", &["\u{300}\u{308}", "\u{1F1E6}"]), - ("\u{300}\u{378}", &["\u{300}", "\u{378}"]), - ("\u{300}\u{308}\u{378}", &["\u{300}\u{308}", "\u{378}"]), - ("\u{903}\u{20}", &["\u{903}", "\u{20}"]), - ("\u{903}\u{308}\u{20}", &["\u{903}\u{308}", "\u{20}"]), - ("\u{903}\u{D}", &["\u{903}", "\u{D}"]), - ("\u{903}\u{308}\u{D}", &["\u{903}\u{308}", "\u{D}"]), - ("\u{903}\u{A}", &["\u{903}", "\u{A}"]), - ("\u{903}\u{308}\u{A}", &["\u{903}\u{308}", "\u{A}"]), - ("\u{903}\u{1}", &["\u{903}", "\u{1}"]), - ("\u{903}\u{308}\u{1}", &["\u{903}\u{308}", "\u{1}"]), - ("\u{903}\u{300}", &["\u{903}\u{300}"]), - ("\u{903}\u{308}\u{300}", &["\u{903}\u{308}\u{300}"]), - ("\u{903}\u{1100}", &["\u{903}", "\u{1100}"]), - ("\u{903}\u{308}\u{1100}", &["\u{903}\u{308}", "\u{1100}"]), - ("\u{903}\u{1160}", &["\u{903}", "\u{1160}"]), - ("\u{903}\u{308}\u{1160}", &["\u{903}\u{308}", "\u{1160}"]), - ("\u{903}\u{11A8}", &["\u{903}", "\u{11A8}"]), - ("\u{903}\u{308}\u{11A8}", &["\u{903}\u{308}", "\u{11A8}"]), - ("\u{903}\u{AC00}", &["\u{903}", "\u{AC00}"]), - ("\u{903}\u{308}\u{AC00}", &["\u{903}\u{308}", "\u{AC00}"]), - ("\u{903}\u{AC01}", &["\u{903}", "\u{AC01}"]), - ("\u{903}\u{308}\u{AC01}", &["\u{903}\u{308}", "\u{AC01}"]), - ("\u{903}\u{1F1E6}", &["\u{903}", "\u{1F1E6}"]), - ("\u{903}\u{308}\u{1F1E6}", &["\u{903}\u{308}", "\u{1F1E6}"]), - ("\u{903}\u{378}", &["\u{903}", "\u{378}"]), - ("\u{903}\u{308}\u{378}", &["\u{903}\u{308}", "\u{378}"]), - ("\u{1100}\u{20}", &["\u{1100}", "\u{20}"]), - ("\u{1100}\u{308}\u{20}", &["\u{1100}\u{308}", "\u{20}"]), - ("\u{1100}\u{D}", &["\u{1100}", "\u{D}"]), - ("\u{1100}\u{308}\u{D}", &["\u{1100}\u{308}", "\u{D}"]), - ("\u{1100}\u{A}", &["\u{1100}", "\u{A}"]), - ("\u{1100}\u{308}\u{A}", &["\u{1100}\u{308}", "\u{A}"]), - ("\u{1100}\u{1}", &["\u{1100}", "\u{1}"]), - ("\u{1100}\u{308}\u{1}", &["\u{1100}\u{308}", "\u{1}"]), - ("\u{1100}\u{300}", &["\u{1100}\u{300}"]), - ("\u{1100}\u{308}\u{300}", &["\u{1100}\u{308}\u{300}"]), - ("\u{1100}\u{1100}", &["\u{1100}\u{1100}"]), - ("\u{1100}\u{308}\u{1100}", &["\u{1100}\u{308}", "\u{1100}"]), - ("\u{1100}\u{1160}", &["\u{1100}\u{1160}"]), - ("\u{1100}\u{308}\u{1160}", &["\u{1100}\u{308}", "\u{1160}"]), - ("\u{1100}\u{11A8}", &["\u{1100}", "\u{11A8}"]), - ("\u{1100}\u{308}\u{11A8}", &["\u{1100}\u{308}", "\u{11A8}"]), - ("\u{1100}\u{AC00}", &["\u{1100}\u{AC00}"]), - ("\u{1100}\u{308}\u{AC00}", &["\u{1100}\u{308}", "\u{AC00}"]), - ("\u{1100}\u{AC01}", &["\u{1100}\u{AC01}"]), - ("\u{1100}\u{308}\u{AC01}", &["\u{1100}\u{308}", "\u{AC01}"]), - ("\u{1100}\u{1F1E6}", &["\u{1100}", "\u{1F1E6}"]), - ("\u{1100}\u{308}\u{1F1E6}", &["\u{1100}\u{308}", "\u{1F1E6}"]), - ("\u{1100}\u{378}", &["\u{1100}", "\u{378}"]), - ("\u{1100}\u{308}\u{378}", &["\u{1100}\u{308}", "\u{378}"]), - ("\u{1160}\u{20}", &["\u{1160}", "\u{20}"]), - ("\u{1160}\u{308}\u{20}", &["\u{1160}\u{308}", "\u{20}"]), - ("\u{1160}\u{D}", &["\u{1160}", "\u{D}"]), - ("\u{1160}\u{308}\u{D}", &["\u{1160}\u{308}", "\u{D}"]), - ("\u{1160}\u{A}", &["\u{1160}", "\u{A}"]), - ("\u{1160}\u{308}\u{A}", &["\u{1160}\u{308}", "\u{A}"]), - ("\u{1160}\u{1}", &["\u{1160}", "\u{1}"]), - ("\u{1160}\u{308}\u{1}", &["\u{1160}\u{308}", "\u{1}"]), - ("\u{1160}\u{300}", &["\u{1160}\u{300}"]), - ("\u{1160}\u{308}\u{300}", &["\u{1160}\u{308}\u{300}"]), - ("\u{1160}\u{1100}", &["\u{1160}", "\u{1100}"]), - ("\u{1160}\u{308}\u{1100}", &["\u{1160}\u{308}", "\u{1100}"]), - ("\u{1160}\u{1160}", &["\u{1160}\u{1160}"]), - ("\u{1160}\u{308}\u{1160}", &["\u{1160}\u{308}", "\u{1160}"]), - ("\u{1160}\u{11A8}", &["\u{1160}\u{11A8}"]), - ("\u{1160}\u{308}\u{11A8}", &["\u{1160}\u{308}", "\u{11A8}"]), - ("\u{1160}\u{AC00}", &["\u{1160}", "\u{AC00}"]), - ("\u{1160}\u{308}\u{AC00}", &["\u{1160}\u{308}", "\u{AC00}"]), - ("\u{1160}\u{AC01}", &["\u{1160}", "\u{AC01}"]), - ("\u{1160}\u{308}\u{AC01}", &["\u{1160}\u{308}", "\u{AC01}"]), - ("\u{1160}\u{1F1E6}", &["\u{1160}", "\u{1F1E6}"]), - ("\u{1160}\u{308}\u{1F1E6}", &["\u{1160}\u{308}", "\u{1F1E6}"]), - ("\u{1160}\u{378}", &["\u{1160}", "\u{378}"]), - ("\u{1160}\u{308}\u{378}", &["\u{1160}\u{308}", "\u{378}"]), - ("\u{11A8}\u{20}", &["\u{11A8}", "\u{20}"]), - ("\u{11A8}\u{308}\u{20}", &["\u{11A8}\u{308}", "\u{20}"]), - ("\u{11A8}\u{D}", &["\u{11A8}", "\u{D}"]), - ("\u{11A8}\u{308}\u{D}", &["\u{11A8}\u{308}", "\u{D}"]), - ("\u{11A8}\u{A}", &["\u{11A8}", "\u{A}"]), - ("\u{11A8}\u{308}\u{A}", &["\u{11A8}\u{308}", "\u{A}"]), - ("\u{11A8}\u{1}", &["\u{11A8}", "\u{1}"]), - ("\u{11A8}\u{308}\u{1}", &["\u{11A8}\u{308}", "\u{1}"]), - ("\u{11A8}\u{300}", &["\u{11A8}\u{300}"]), - ("\u{11A8}\u{308}\u{300}", &["\u{11A8}\u{308}\u{300}"]), - ("\u{11A8}\u{1100}", &["\u{11A8}", "\u{1100}"]), - ("\u{11A8}\u{308}\u{1100}", &["\u{11A8}\u{308}", "\u{1100}"]), - ("\u{11A8}\u{1160}", &["\u{11A8}", "\u{1160}"]), - ("\u{11A8}\u{308}\u{1160}", &["\u{11A8}\u{308}", "\u{1160}"]), - ("\u{11A8}\u{11A8}", &["\u{11A8}\u{11A8}"]), - ("\u{11A8}\u{308}\u{11A8}", &["\u{11A8}\u{308}", "\u{11A8}"]), - ("\u{11A8}\u{AC00}", &["\u{11A8}", "\u{AC00}"]), - ("\u{11A8}\u{308}\u{AC00}", &["\u{11A8}\u{308}", "\u{AC00}"]), - ("\u{11A8}\u{AC01}", &["\u{11A8}", "\u{AC01}"]), - ("\u{11A8}\u{308}\u{AC01}", &["\u{11A8}\u{308}", "\u{AC01}"]), - ("\u{11A8}\u{1F1E6}", &["\u{11A8}", "\u{1F1E6}"]), - ("\u{11A8}\u{308}\u{1F1E6}", &["\u{11A8}\u{308}", "\u{1F1E6}"]), - ("\u{11A8}\u{378}", &["\u{11A8}", "\u{378}"]), - ("\u{11A8}\u{308}\u{378}", &["\u{11A8}\u{308}", "\u{378}"]), - ("\u{AC00}\u{20}", &["\u{AC00}", "\u{20}"]), - ("\u{AC00}\u{308}\u{20}", &["\u{AC00}\u{308}", "\u{20}"]), - ("\u{AC00}\u{D}", &["\u{AC00}", "\u{D}"]), - ("\u{AC00}\u{308}\u{D}", &["\u{AC00}\u{308}", "\u{D}"]), - ("\u{AC00}\u{A}", &["\u{AC00}", "\u{A}"]), - ("\u{AC00}\u{308}\u{A}", &["\u{AC00}\u{308}", "\u{A}"]), - ("\u{AC00}\u{1}", &["\u{AC00}", "\u{1}"]), - ("\u{AC00}\u{308}\u{1}", &["\u{AC00}\u{308}", "\u{1}"]), - ("\u{AC00}\u{300}", &["\u{AC00}\u{300}"]), - ("\u{AC00}\u{308}\u{300}", &["\u{AC00}\u{308}\u{300}"]), - ("\u{AC00}\u{1100}", &["\u{AC00}", "\u{1100}"]), - ("\u{AC00}\u{308}\u{1100}", &["\u{AC00}\u{308}", "\u{1100}"]), - ("\u{AC00}\u{1160}", &["\u{AC00}\u{1160}"]), - ("\u{AC00}\u{308}\u{1160}", &["\u{AC00}\u{308}", "\u{1160}"]), - ("\u{AC00}\u{11A8}", &["\u{AC00}\u{11A8}"]), - ("\u{AC00}\u{308}\u{11A8}", &["\u{AC00}\u{308}", "\u{11A8}"]), - ("\u{AC00}\u{AC00}", &["\u{AC00}", "\u{AC00}"]), - ("\u{AC00}\u{308}\u{AC00}", &["\u{AC00}\u{308}", "\u{AC00}"]), - ("\u{AC00}\u{AC01}", &["\u{AC00}", "\u{AC01}"]), - ("\u{AC00}\u{308}\u{AC01}", &["\u{AC00}\u{308}", "\u{AC01}"]), - ("\u{AC00}\u{1F1E6}", &["\u{AC00}", "\u{1F1E6}"]), - ("\u{AC00}\u{308}\u{1F1E6}", &["\u{AC00}\u{308}", "\u{1F1E6}"]), - ("\u{AC00}\u{378}", &["\u{AC00}", "\u{378}"]), - ("\u{AC00}\u{308}\u{378}", &["\u{AC00}\u{308}", "\u{378}"]), - ("\u{AC01}\u{20}", &["\u{AC01}", "\u{20}"]), - ("\u{AC01}\u{308}\u{20}", &["\u{AC01}\u{308}", "\u{20}"]), - ("\u{AC01}\u{D}", &["\u{AC01}", "\u{D}"]), - ("\u{AC01}\u{308}\u{D}", &["\u{AC01}\u{308}", "\u{D}"]), - ("\u{AC01}\u{A}", &["\u{AC01}", "\u{A}"]), - ("\u{AC01}\u{308}\u{A}", &["\u{AC01}\u{308}", "\u{A}"]), - ("\u{AC01}\u{1}", &["\u{AC01}", "\u{1}"]), - ("\u{AC01}\u{308}\u{1}", &["\u{AC01}\u{308}", "\u{1}"]), - ("\u{AC01}\u{300}", &["\u{AC01}\u{300}"]), - ("\u{AC01}\u{308}\u{300}", &["\u{AC01}\u{308}\u{300}"]), - ("\u{AC01}\u{1100}", &["\u{AC01}", "\u{1100}"]), - ("\u{AC01}\u{308}\u{1100}", &["\u{AC01}\u{308}", "\u{1100}"]), - ("\u{AC01}\u{1160}", &["\u{AC01}", "\u{1160}"]), - ("\u{AC01}\u{308}\u{1160}", &["\u{AC01}\u{308}", "\u{1160}"]), - ("\u{AC01}\u{11A8}", &["\u{AC01}\u{11A8}"]), - ("\u{AC01}\u{308}\u{11A8}", &["\u{AC01}\u{308}", "\u{11A8}"]), - ("\u{AC01}\u{AC00}", &["\u{AC01}", "\u{AC00}"]), - ("\u{AC01}\u{308}\u{AC00}", &["\u{AC01}\u{308}", "\u{AC00}"]), - ("\u{AC01}\u{AC01}", &["\u{AC01}", "\u{AC01}"]), - ("\u{AC01}\u{308}\u{AC01}", &["\u{AC01}\u{308}", "\u{AC01}"]), - ("\u{AC01}\u{1F1E6}", &["\u{AC01}", "\u{1F1E6}"]), - ("\u{AC01}\u{308}\u{1F1E6}", &["\u{AC01}\u{308}", "\u{1F1E6}"]), - ("\u{AC01}\u{378}", &["\u{AC01}", "\u{378}"]), - ("\u{AC01}\u{308}\u{378}", &["\u{AC01}\u{308}", "\u{378}"]), - ("\u{1F1E6}\u{20}", &["\u{1F1E6}", "\u{20}"]), - ("\u{1F1E6}\u{308}\u{20}", &["\u{1F1E6}\u{308}", "\u{20}"]), - ("\u{1F1E6}\u{D}", &["\u{1F1E6}", "\u{D}"]), - ("\u{1F1E6}\u{308}\u{D}", &["\u{1F1E6}\u{308}", "\u{D}"]), - ("\u{1F1E6}\u{A}", &["\u{1F1E6}", "\u{A}"]), - ("\u{1F1E6}\u{308}\u{A}", &["\u{1F1E6}\u{308}", "\u{A}"]), - ("\u{1F1E6}\u{1}", &["\u{1F1E6}", "\u{1}"]), - ("\u{1F1E6}\u{308}\u{1}", &["\u{1F1E6}\u{308}", "\u{1}"]), - ("\u{1F1E6}\u{300}", &["\u{1F1E6}\u{300}"]), - ("\u{1F1E6}\u{308}\u{300}", &["\u{1F1E6}\u{308}\u{300}"]), - ("\u{1F1E6}\u{1100}", &["\u{1F1E6}", "\u{1100}"]), - ("\u{1F1E6}\u{308}\u{1100}", &["\u{1F1E6}\u{308}", "\u{1100}"]), - ("\u{1F1E6}\u{1160}", &["\u{1F1E6}", "\u{1160}"]), - ("\u{1F1E6}\u{308}\u{1160}", &["\u{1F1E6}\u{308}", "\u{1160}"]), - ("\u{1F1E6}\u{11A8}", &["\u{1F1E6}", "\u{11A8}"]), - ("\u{1F1E6}\u{308}\u{11A8}", &["\u{1F1E6}\u{308}", "\u{11A8}"]), - ("\u{1F1E6}\u{AC00}", &["\u{1F1E6}", "\u{AC00}"]), - ("\u{1F1E6}\u{308}\u{AC00}", &["\u{1F1E6}\u{308}", "\u{AC00}"]), - ("\u{1F1E6}\u{AC01}", &["\u{1F1E6}", "\u{AC01}"]), - ("\u{1F1E6}\u{308}\u{AC01}", &["\u{1F1E6}\u{308}", "\u{AC01}"]), - ("\u{1F1E6}\u{1F1E6}", &["\u{1F1E6}\u{1F1E6}"]), - ("\u{1F1E6}\u{308}\u{1F1E6}", &["\u{1F1E6}\u{308}", "\u{1F1E6}"]), - ("\u{1F1E6}\u{378}", &["\u{1F1E6}", "\u{378}"]), - ("\u{1F1E6}\u{308}\u{378}", &["\u{1F1E6}\u{308}", "\u{378}"]), - ("\u{378}\u{20}", &["\u{378}", "\u{20}"]), - ("\u{378}\u{308}\u{20}", &["\u{378}\u{308}", "\u{20}"]), - ("\u{378}\u{D}", &["\u{378}", "\u{D}"]), - ("\u{378}\u{308}\u{D}", &["\u{378}\u{308}", "\u{D}"]), - ("\u{378}\u{A}", &["\u{378}", "\u{A}"]), - ("\u{378}\u{308}\u{A}", &["\u{378}\u{308}", "\u{A}"]), - ("\u{378}\u{1}", &["\u{378}", "\u{1}"]), - ("\u{378}\u{308}\u{1}", &["\u{378}\u{308}", "\u{1}"]), - ("\u{378}\u{300}", &["\u{378}\u{300}"]), - ("\u{378}\u{308}\u{300}", &["\u{378}\u{308}\u{300}"]), - ("\u{378}\u{1100}", &["\u{378}", "\u{1100}"]), - ("\u{378}\u{308}\u{1100}", &["\u{378}\u{308}", "\u{1100}"]), - ("\u{378}\u{1160}", &["\u{378}", "\u{1160}"]), - ("\u{378}\u{308}\u{1160}", &["\u{378}\u{308}", "\u{1160}"]), - ("\u{378}\u{11A8}", &["\u{378}", "\u{11A8}"]), - ("\u{378}\u{308}\u{11A8}", &["\u{378}\u{308}", "\u{11A8}"]), - ("\u{378}\u{AC00}", &["\u{378}", "\u{AC00}"]), - ("\u{378}\u{308}\u{AC00}", &["\u{378}\u{308}", "\u{AC00}"]), - ("\u{378}\u{AC01}", &["\u{378}", "\u{AC01}"]), - ("\u{378}\u{308}\u{AC01}", &["\u{378}\u{308}", "\u{AC01}"]), - ("\u{378}\u{1F1E6}", &["\u{378}", "\u{1F1E6}"]), - ("\u{378}\u{308}\u{1F1E6}", &["\u{378}\u{308}", "\u{1F1E6}"]), - ("\u{378}\u{378}", &["\u{378}", "\u{378}"]), - ("\u{378}\u{308}\u{378}", &["\u{378}\u{308}", "\u{378}"]), - ("\u{61}\u{1F1E6}\u{62}", &["\u{61}", "\u{1F1E6}", "\u{62}"]), - ("\u{1F1F7}\u{1F1FA}", &["\u{1F1F7}\u{1F1FA}"]), - ("\u{1F1F7}\u{1F1FA}\u{1F1F8}", &["\u{1F1F7}\u{1F1FA}\u{1F1F8}"]), - ("\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}", - &["\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}"]), - ("\u{1F1F7}\u{1F1FA}\u{200B}\u{1F1F8}\u{1F1EA}", - &["\u{1F1F7}\u{1F1FA}", "\u{200B}", "\u{1F1F8}\u{1F1EA}"]), - ("\u{1F1E6}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{1F1E7}\u{1F1E8}"]), - ("\u{1F1E6}\u{200D}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{200D}", - "\u{1F1E7}\u{1F1E8}"]), - ("\u{1F1E6}\u{1F1E7}\u{200D}\u{1F1E8}", - &["\u{1F1E6}\u{1F1E7}\u{200D}", "\u{1F1E8}"]), - ("\u{20}\u{200D}\u{646}", &["\u{20}\u{200D}", "\u{646}"]), - ("\u{646}\u{200D}\u{20}", &["\u{646}\u{200D}", "\u{20}"]), - ]; - - let test_diff: [(_, &[_], &[_]); 23] = [ - ("\u{20}\u{903}", &["\u{20}\u{903}"], &["\u{20}", "\u{903}"]), ("\u{20}\u{308}\u{903}", - &["\u{20}\u{308}\u{903}"], &["\u{20}\u{308}", "\u{903}"]), ("\u{D}\u{308}\u{903}", - &["\u{D}", "\u{308}\u{903}"], &["\u{D}", "\u{308}", "\u{903}"]), ("\u{A}\u{308}\u{903}", - &["\u{A}", "\u{308}\u{903}"], &["\u{A}", "\u{308}", "\u{903}"]), ("\u{1}\u{308}\u{903}", - &["\u{1}", "\u{308}\u{903}"], &["\u{1}", "\u{308}", "\u{903}"]), ("\u{300}\u{903}", - &["\u{300}\u{903}"], &["\u{300}", "\u{903}"]), ("\u{300}\u{308}\u{903}", - &["\u{300}\u{308}\u{903}"], &["\u{300}\u{308}", "\u{903}"]), ("\u{903}\u{903}", - &["\u{903}\u{903}"], &["\u{903}", "\u{903}"]), ("\u{903}\u{308}\u{903}", - &["\u{903}\u{308}\u{903}"], &["\u{903}\u{308}", "\u{903}"]), ("\u{1100}\u{903}", - &["\u{1100}\u{903}"], &["\u{1100}", "\u{903}"]), ("\u{1100}\u{308}\u{903}", - &["\u{1100}\u{308}\u{903}"], &["\u{1100}\u{308}", "\u{903}"]), ("\u{1160}\u{903}", - &["\u{1160}\u{903}"], &["\u{1160}", "\u{903}"]), ("\u{1160}\u{308}\u{903}", - &["\u{1160}\u{308}\u{903}"], &["\u{1160}\u{308}", "\u{903}"]), ("\u{11A8}\u{903}", - &["\u{11A8}\u{903}"], &["\u{11A8}", "\u{903}"]), ("\u{11A8}\u{308}\u{903}", - &["\u{11A8}\u{308}\u{903}"], &["\u{11A8}\u{308}", "\u{903}"]), ("\u{AC00}\u{903}", - &["\u{AC00}\u{903}"], &["\u{AC00}", "\u{903}"]), ("\u{AC00}\u{308}\u{903}", - &["\u{AC00}\u{308}\u{903}"], &["\u{AC00}\u{308}", "\u{903}"]), ("\u{AC01}\u{903}", - &["\u{AC01}\u{903}"], &["\u{AC01}", "\u{903}"]), ("\u{AC01}\u{308}\u{903}", - &["\u{AC01}\u{308}\u{903}"], &["\u{AC01}\u{308}", "\u{903}"]), ("\u{1F1E6}\u{903}", - &["\u{1F1E6}\u{903}"], &["\u{1F1E6}", "\u{903}"]), ("\u{1F1E6}\u{308}\u{903}", - &["\u{1F1E6}\u{308}\u{903}"], &["\u{1F1E6}\u{308}", "\u{903}"]), ("\u{378}\u{903}", - &["\u{378}\u{903}"], &["\u{378}", "\u{903}"]), ("\u{378}\u{308}\u{903}", - &["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]), - ]; - - for &(s, g) in &test_same[..] { - // test forward iterator - assert!(order::equals(s.graphemes(true), g.iter().cloned())); - assert!(order::equals(s.graphemes(false), g.iter().cloned())); - - // test reverse iterator - assert!(order::equals(s.graphemes(true).rev(), g.iter().rev().cloned())); - assert!(order::equals(s.graphemes(false).rev(), g.iter().rev().cloned())); - } - - for &(s, gt, gf) in &test_diff { - // test forward iterator - assert!(order::equals(s.graphemes(true), gt.iter().cloned())); - assert!(order::equals(s.graphemes(false), gf.iter().cloned())); - - // test reverse iterator - assert!(order::equals(s.graphemes(true).rev(), gt.iter().rev().cloned())); - assert!(order::equals(s.graphemes(false).rev(), gf.iter().rev().cloned())); - } - - // test the indices iterators - let s = "a̐éö̲\r\n"; - let gr_inds = s.grapheme_indices(true).collect::<Vec<(usize, &str)>>(); - let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; - assert_eq!(gr_inds, b); - let gr_inds = s.grapheme_indices(true).rev().collect::<Vec<(usize, &str)>>(); - let b: &[_] = &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0, "a̐")]; - assert_eq!(gr_inds, b); - let mut gr_inds_iter = s.grapheme_indices(true); - { - let gr_inds = gr_inds_iter.by_ref(); - let e1 = gr_inds.size_hint(); - assert_eq!(e1, (1, Some(13))); - let c = gr_inds.count(); - assert_eq!(c, 4); - } - let e2 = gr_inds_iter.size_hint(); - assert_eq!(e2, (0, Some(0))); - - // make sure the reverse iterator does the right thing with "\n" at beginning of string - let s = "\n\r\n\r"; - let gr = s.graphemes(true).rev().collect::<Vec<&str>>(); - let b: &[_] = &["\r", "\r\n", "\n"]; - assert_eq!(gr, b); + /// An iterator over the lines of a string, separated by either `\n` or `\r\n`. + /// + /// As with `.lines()`, this does not include an empty trailing line. + /// + /// # Examples + /// + /// ``` + /// let four_lines = "foo\r\nbar\n\r\nbaz"; + /// let v: Vec<&str> = four_lines.lines_any().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + /// + /// Leaving off the trailing character: + /// + /// ``` + /// let four_lines = "foo\r\nbar\n\r\nbaz\n"; + /// let v: Vec<&str> = four_lines.lines_any().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn lines_any(&self) -> LinesAny { + core_str::StrExt::lines_any(&self[..]) } - #[test] - fn test_split_strator() { - fn t(s: &str, sep: &str, u: &[&str]) { - let v: Vec<&str> = s.split_str(sep).collect(); - assert_eq!(v, u); - } - t("--1233345--", "12345", &["--1233345--"]); - t("abc::hello::there", "::", &["abc", "hello", "there"]); - t("::hello::there", "::", &["", "hello", "there"]); - t("hello::there::", "::", &["hello", "there", ""]); - t("::hello::there::", "::", &["", "hello", "there", ""]); - t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]); - t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]); - t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]); - t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]); - t("", ".", &[""]); - t("zz", "zz", &["",""]); - t("ok", "z", &["ok"]); - t("zzz", "zz", &["","z"]); - t("zzzzz", "zz", &["","","z"]); - } - - #[test] - fn test_str_default() { - use core::default::Default; - fn t<S: Default + Str>() { - let s: S = Default::default(); - assert_eq!(s.as_slice(), ""); - } - - t::<&str>(); - t::<String>(); + /// Deprecated: use `s[a .. b]` instead. + #[unstable(feature = "collections", + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")] + pub fn slice(&self, begin: usize, end: usize) -> &str { + &self[begin..end] } - #[test] - fn test_str_container() { - fn sum_len(v: &[&str]) -> usize { - v.iter().map(|x| x.len()).sum() - } - - let s = String::from_str("01234"); - assert_eq!(5, sum_len(&["012", "", "34"])); - assert_eq!(5, sum_len(&[&String::from_str("01"), - &String::from_str("2"), - &String::from_str("34"), - &String::from_str("")])); - assert_eq!(5, sum_len(&[&s])); + /// Deprecated: use `s[a..]` instead. + #[unstable(feature = "collections", + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")] + pub fn slice_from(&self, begin: usize) -> &str { + &self[begin..] } - #[test] - fn test_str_from_utf8() { - let xs = b"hello"; - assert_eq!(from_utf8(xs), Ok("hello")); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); - - let xs = b"hello\xFF"; - assert_eq!(from_utf8(xs), Err(Utf8Error::TooShort)); + /// Deprecated: use `s[..a]` instead. + #[unstable(feature = "collections", + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")] + pub fn slice_to(&self, end: usize) -> &str { + &self[..end] } -} - -#[cfg(test)] -mod bench { - use super::*; - use prelude::{SliceExt, IteratorExt, SliceConcatExt}; - use test::Bencher; - use test::black_box; - #[bench] - fn char_iterator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().count()); + /// Returns a slice of the string from the character range [`begin`..`end`). + /// + /// That is, start at the `begin`-th code point of the string and continue + /// to the `end`-th code point. This does not detect or handle edge cases + /// such as leaving a combining character as the first code point of the + /// string. + /// + /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`, + /// `slice_to` and `slice_from` for `O(1)` variants that use byte indices + /// rather than code point indices. + /// + /// # Panics + /// + /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the + /// last character of the string. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.slice_chars(0, 4), "Löwe"); + /// assert_eq!(s.slice_chars(5, 7), "老虎"); + /// ``` + #[unstable(feature = "collections", + reason = "may have yet to prove its worth")] + pub fn slice_chars(&self, begin: usize, end: usize) -> &str { + core_str::StrExt::slice_chars(&self[..], begin, end) } - #[bench] - fn char_iterator_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| { - for ch in s.chars() { black_box(ch); } - }); + /// Takes a bytewise slice from a string. + /// + /// Returns the substring from [`begin`..`end`). + /// + /// # Unsafety + /// + /// Caller must check both UTF-8 character boundaries and the boundaries of the entire slice as + /// well. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!(s.slice_unchecked(0, 21), "Löwe 老虎 Léopard"); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { + core_str::StrExt::slice_unchecked(&self[..], begin, end) } - #[bench] - fn char_iterator_ascii(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().count()); + /// Returns `true` if the given `&str` is a prefix of the string. + /// + /// # Examples + /// + /// ``` + /// assert!("banana".starts_with("ba")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::starts_with(&self[..], pat) } - #[bench] - fn char_iterator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().rev().count()); + /// Returns true if the given `&str` is a suffix of the string. + /// + /// # Examples + /// + /// ```rust + /// assert!("banana".ends_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::ends_with(&self[..], pat) } - #[bench] - fn char_iterator_rev_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + /// Returns a string with all pre- and suffixes that match a pattern repeatedly removed. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a> + { + core_str::StrExt::trim_matches(&self[..], pat) + } - b.iter(|| { - for ch in s.chars().rev() { black_box(ch); } - }); + /// Returns a string with all prefixes that match a pattern repeatedly removed. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + core_str::StrExt::trim_left_matches(&self[..], pat) } - #[bench] - fn char_indicesator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); + /// Returns a string with all suffixes that match a pattern repeatedly removed. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::trim_right_matches(&self[..], pat) + } - b.iter(|| assert_eq!(s.char_indices().count(), len)); + /// Check that `index`-th byte lies at the start and/or end of a UTF-8 code point sequence. + /// + /// The start and end of the string (when `index == self.len()`) are considered to be + /// boundaries. + /// + /// # Panics + /// + /// Panics if `index` is greater than `self.len()`. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// assert!(s.is_char_boundary(0)); + /// // start of `老` + /// assert!(s.is_char_boundary(6)); + /// assert!(s.is_char_boundary(s.len())); + /// + /// // second byte of `ö` + /// assert!(!s.is_char_boundary(2)); + /// + /// // third byte of `老` + /// assert!(!s.is_char_boundary(8)); + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn is_char_boundary(&self, index: usize) -> bool { + core_str::StrExt::is_char_boundary(&self[..], index) } - #[bench] - fn char_indicesator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); + /// Given a byte position, return the next char and its index. + /// + /// This can be used to iterate over the Unicode characters of a string. + /// + /// # Panics + /// + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. + /// + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars()` or `.char_indices()`. + /// + /// ``` + /// use std::str::CharRange; + /// + /// let s = "中华Việt Nam"; + /// let mut i = 0; + /// while i < s.len() { + /// let CharRange {ch, next} = s.char_range_at(i); + /// println!("{}: {}", i, ch); + /// i = next; + /// } + /// ``` + /// + /// This outputs: + /// + /// ```text + /// 0: 中 + /// 3: 华 + /// 6: V + /// 7: i + /// 8: ệ + /// 11: t + /// 12: + /// 13: N + /// 14: a + /// 15: m + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_range_at(&self, start: usize) -> CharRange { + core_str::StrExt::char_range_at(&self[..], start) + } - b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); + /// Given a byte position, return the previous `char` and its position. + /// + /// This function can be used to iterate over a Unicode string in reverse. + /// + /// Returns 0 for next index if called on start index 0. + /// + /// # Panics + /// + /// If `i` is greater than the length of the string. + /// If `i` is not an index following a valid UTF-8 character. + /// + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars().rev()` or `.char_indices()`. + /// + /// ``` + /// use std::str::CharRange; + /// + /// let s = "中华Việt Nam"; + /// let mut i = s.len(); + /// while i > 0 { + /// let CharRange {ch, next} = s.char_range_at_reverse(i); + /// println!("{}: {}", i, ch); + /// i = next; + /// } + /// ``` + /// + /// This outputs: + /// + /// ```text + /// 16: m + /// 15: a + /// 14: N + /// 13: + /// 12: t + /// 11: ệ + /// 8: i + /// 7: V + /// 6: 华 + /// 3: 中 + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_range_at_reverse(&self, start: usize) -> CharRange { + core_str::StrExt::char_range_at_reverse(&self[..], start) } - #[bench] - fn split_unicode_ascii(b: &mut Bencher) { - let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; + /// Given a byte position, return the `char` at that position. + /// + /// # Panics + /// + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. + /// + /// # Examples + /// + /// ``` + /// let s = "abπc"; + /// assert_eq!(s.char_at(1), 'b'); + /// assert_eq!(s.char_at(2), 'π'); + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_at(&self, i: usize) -> char { + core_str::StrExt::char_at(&self[..], i) + } - b.iter(|| assert_eq!(s.split('V').count(), 3)); + /// Given a byte position, return the `char` at that position, counting from the end. + /// + /// # Panics + /// + /// If `i` is greater than the length of the string. + /// If `i` is not an index following a valid UTF-8 character. + /// + /// # Examples + /// + /// ``` + /// let s = "abπc"; + /// assert_eq!(s.char_at_reverse(1), 'a'); + /// assert_eq!(s.char_at_reverse(2), 'b'); + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_at_reverse(&self, i: usize) -> char { + core_str::StrExt::char_at_reverse(&self[..], i) } - #[bench] - fn split_ascii(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); + /// Convert `self` to a byte slice. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("bors".as_bytes(), b"bors"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_bytes(&self) -> &[u8] { + core_str::StrExt::as_bytes(&self[..]) + } - b.iter(|| assert_eq!(s.split(' ').count(), len)); + /// Returns the byte index of the first character of `self` that matches the pattern, if it + /// exists. + /// + /// Returns `None` if it doesn't exist. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find('L'), Some(0)); + /// assert_eq!(s.find('é'), Some(14)); + /// + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.find(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> { + core_str::StrExt::find(&self[..], pat) } - #[bench] - fn split_extern_fn(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - fn pred(c: char) -> bool { c == ' ' } + /// Returns the byte index of the last character of `self` that matches the pattern, if it + /// exists. + /// + /// Returns `None` if it doesn't exist. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind('L'), Some(13)); + /// assert_eq!(s.rfind('é'), Some(14)); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind(|c: char| c.is_whitespace()), Some(12)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.rfind(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rfind(&self[..], pat) + } - b.iter(|| assert_eq!(s.split(pred).count(), len)); + /// Returns the byte index of the first matching substring if it exists. + /// + /// Returns `None` if it doesn't exist. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find_str("老虎 L"), Some(6)); + /// assert_eq!(s.find_str("muffin man"), None); + /// ``` + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use `find()` with a `&str`")] + pub fn find_str<'a, P: Pattern<'a>>(&'a self, needle: P) -> Option<usize> { + core_str::StrExt::find_str(&self[..], needle) } - #[bench] - fn split_closure(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); + /// Retrieves the first character from a `&str` and returns it. + /// + /// This does not allocate a new string; instead, it returns a slice that points one character + /// beyond the character that was shifted. + /// + /// If the slice does not contain any characters, None is returned instead. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let (c, s1) = s.slice_shift_char().unwrap(); + /// + /// assert_eq!(c, 'L'); + /// assert_eq!(s1, "öwe 老虎 Léopard"); + /// + /// let (c, s2) = s1.slice_shift_char().unwrap(); + /// + /// assert_eq!(c, 'ö'); + /// assert_eq!(s2, "we 老虎 Léopard"); + /// ``` + #[unstable(feature = "collections", + reason = "awaiting conventions about shifting and slices")] + pub fn slice_shift_char(&self) -> Option<(char, &str)> { + core_str::StrExt::slice_shift_char(&self[..]) + } - b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); + /// Returns the byte offset of an inner slice relative to an enclosing outer slice. + /// + /// # Panics + /// + /// Panics if `inner` is not a direct slice contained within self. + /// + /// # Examples + /// + /// ``` + /// let string = "a\nb\nc"; + /// let lines: Vec<&str> = string.lines().collect(); + /// + /// assert!(string.subslice_offset(lines[0]) == 0); // &"a" + /// assert!(string.subslice_offset(lines[1]) == 2); // &"b" + /// assert!(string.subslice_offset(lines[2]) == 4); // &"c" + /// ``` + #[unstable(feature = "collections", + reason = "awaiting convention about comparability of arbitrary slices")] + pub fn subslice_offset(&self, inner: &str) -> usize { + core_str::StrExt::subslice_offset(&self[..], inner) } - #[bench] - fn split_slice(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); + /// Return an unsafe pointer to the `&str`'s buffer. + /// + /// The caller must ensure that the string outlives this pointer, and that it is not + /// reallocated (e.g. by pushing to the string). + /// + /// # Examples + /// + /// ``` + /// let s = "Hello"; + /// let p = s.as_ptr(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const u8 { + core_str::StrExt::as_ptr(&self[..]) + } - let c: &[char] = &[' ']; - b.iter(|| assert_eq!(s.split(c).count(), len)); + /// Return an iterator of `u16` over the string encoded as UTF-16. + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn utf16_units(&self) -> Utf16Units { + Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) } } - #[bench] - fn bench_connect(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let sep = "→"; - let v = vec![s, s, s, s, s, s, s, s, s, s]; - b.iter(|| { - assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9); - }) + /// Returns the length of `self` in bytes. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("foo".len(), 3); + /// assert_eq!("ƒoo".len(), 4); // fancy f! + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + core_str::StrExt::len(&self[..]) } - #[bench] - fn bench_contains_short_short(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "sit"; + /// Returns true if this slice has a length of zero bytes. + /// + /// # Examples + /// + /// ``` + /// assert!("".is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + core_str::StrExt::is_empty(&self[..]) + } - b.iter(|| { - assert!(haystack.contains(needle)); - }) + /// Parses `self` into the specified type. + /// + /// # Failure + /// + /// Will return `Err` if it's not possible to parse `self` into the type. + /// + /// # Example + /// + /// ``` + /// assert_eq!("4".parse::<u32>(), Ok(4)); + /// ``` + /// + /// Failing: + /// + /// ``` + /// assert!("j".parse::<u32>().is_err()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> { + core_str::StrExt::parse(&self[..]) } - #[bench] - fn bench_contains_short_long(b: &mut Bencher) { - let haystack = "\ -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ -ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ -eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ -sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ -tempus vel, gravida nec quam. + /// Returns an iterator over the [grapheme clusters][graphemes] of `self`. + /// + /// [graphemes]: http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries + /// + /// If `is_extended` is true, the iterator is over the *extended grapheme clusters*; + /// otherwise, the iterator is over the *legacy grapheme clusters*. + /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) + /// recommends extended grapheme cluster boundaries for general processing. + /// + /// # Examples + /// + /// ``` + /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::<Vec<&str>>(); + /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]; + /// + /// assert_eq!(gr1.as_slice(), b); + /// + /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::<Vec<&str>>(); + /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; + /// + /// assert_eq!(gr2.as_slice(), b); + /// ``` + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn graphemes(&self, is_extended: bool) -> Graphemes { + UnicodeStr::graphemes(&self[..], is_extended) + } -In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ -sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ -diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ -lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ -eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ -interdum. Curabitur ut nisi justo. + /// Returns an iterator over the grapheme clusters of `self` and their byte offsets. See + /// `graphemes()` for more information. + /// + /// # Examples + /// + /// ``` + /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::<Vec<(usize, &str)>>(); + /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + /// + /// assert_eq!(gr_inds.as_slice(), b); + /// ``` + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices { + UnicodeStr::grapheme_indices(&self[..], is_extended) + } -Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ -mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ -lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ -est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ -felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ -ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ -feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ -Aliquam sit amet placerat lorem. + /// An iterator over the non-empty words of `self`. + /// + /// A 'word' is a subsequence separated by any sequence of whitespace. Sequences of whitespace + /// are collapsed, so empty "words" are not included. + /// + /// # Examples + /// + /// ``` + /// let some_words = " Mary had\ta little \n\t lamb"; + /// let v: Vec<&str> = some_words.words().collect(); + /// + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// ``` + #[unstable(feature = "str_words", + reason = "the precise algorithm to use is unclear")] + pub fn words(&self) -> Words { + UnicodeStr::words(&self[..]) + } -Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ -mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ -Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ -lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ -suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ -cursus accumsan. + /// Returns a string's displayed width in columns. + /// + /// Control characters have zero width. + /// + /// `is_cjk` determines behavior for characters in the Ambiguous category: if `is_cjk` is + /// `true`, these are 2 columns wide; otherwise, they are 1. In CJK locales, `is_cjk` should be + /// `true`, else it should be `false`. + /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) recommends that these + /// characters be treated as 1 column (i.e., `is_cjk = false`) if the locale is unknown. + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn width(&self, is_cjk: bool) -> usize { + UnicodeStr::width(&self[..], is_cjk) + } -Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ -feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ -vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ -leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ -malesuada sollicitudin quam eu fermentum."; - let needle = "english"; + /// Returns a `&str` with leading and trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim(), "Hello\tworld"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim(&self) -> &str { + UnicodeStr::trim(&self[..]) + } - b.iter(|| { - assert!(!haystack.contains(needle)); - }) + /// Returns a `&str` with leading whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_left(), "Hello\tworld\t"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left(&self) -> &str { + UnicodeStr::trim_left(&self[..]) } - #[bench] - fn bench_contains_bad_naive(b: &mut Bencher) { - let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let needle = "aaaaaaaab"; + /// Returns a `&str` with trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_right(), " Hello\tworld"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right(&self) -> &str { + UnicodeStr::trim_right(&self[..]) + } - b.iter(|| { - assert!(!haystack.contains(needle)); - }) + /// Returns the lowercase equivalent of this string. + /// + /// # Examples + /// + /// let s = "HELLO"; + /// assert_eq!(s.to_lowercase(), "hello"); + #[unstable(feature = "collections")] + pub fn to_lowercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self[..].chars().flat_map(|c| c.to_lowercase())); + return s; } - - #[bench] - fn bench_contains_equal(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - - b.iter(|| { - assert!(haystack.contains(needle)); - }) + + /// Returns the uppercase equivalent of this string. + /// + /// # Examples + /// + /// let s = "hello"; + /// assert_eq!(s.to_uppercase(), "HELLO"); + #[unstable(feature = "collections")] + pub fn to_uppercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self[..].chars().flat_map(|c| c.to_uppercase())); + return s; } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index bae69a08451..d2bc98096f6 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -24,7 +24,7 @@ use core::iter::{IntoIterator, FromIterator}; use core::mem; use core::ops::{self, Deref, Add, Index}; use core::ptr; -use core::raw::Slice as RawSlice; +use core::slice; use unicode::str as unicode_str; use unicode::str::Utf16Item; @@ -85,6 +85,7 @@ impl String { } } + #[cfg(stage0)] /// Creates a new string buffer from the given string. /// /// # Examples @@ -100,6 +101,33 @@ impl String { String { vec: ::slice::SliceExt::to_vec(string.as_bytes()) } } + #[cfg(not(stage0))] + /// Creates a new string buffer from the given string. + /// + /// # Examples + /// + /// ``` + /// let s = String::from_str("hello"); + /// assert_eq!(s.as_slice(), "hello"); + /// ``` + #[inline] + #[unstable(feature = "collections", + reason = "needs investigation to see if to_string() can match perf")] + #[cfg(not(test))] + pub fn from_str(string: &str) -> String { + String { vec: <[_]>::to_vec(string.as_bytes()) } + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is required for this + // method definition, is not available. Since we don't require this method for testing + // purposes, I'll just stub it + // NB see the slice::hack module in slice.rs for more information + #[inline] + #[cfg(test)] + pub fn from_str(_: &str) -> String { + panic!("not available with cfg(test)"); + } + /// Returns the vector as a string buffer, if possible, taking care not to /// copy it. /// @@ -468,11 +496,11 @@ impl String { unsafe { // Attempt to not use an intermediate buffer by just pushing bytes // directly onto this string. - let slice = RawSlice { - data: self.vec.as_ptr().offset(cur_len as isize), - len: 4, - }; - let used = ch.encode_utf8(mem::transmute(slice)).unwrap_or(0); + let slice = slice::from_raw_parts_mut ( + self.vec.as_mut_ptr().offset(cur_len as isize), + 4 + ); + let used = ch.encode_utf8(slice).unwrap_or(0); self.vec.set_len(cur_len + used); } } @@ -997,450 +1025,3 @@ impl fmt::Write for String { Ok(()) } } - -#[cfg(test)] -mod tests { - use prelude::*; - use test::Bencher; - - use str::Utf8Error; - use core::iter::repeat; - use super::{as_string, CowString}; - - #[test] - fn test_as_string() { - let x = "foo"; - assert_eq!(x, &**as_string(x)); - } - - #[test] - fn test_from_str() { - let owned: Option<::std::string::String> = "string".parse().ok(); - assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); - } - - #[test] - fn test_unsized_to_string() { - let s: &str = "abc"; - let _: String = (*s).to_string(); - } - - #[test] - fn test_from_utf8() { - let xs = b"hello".to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), - String::from_str("hello")); - - let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), - String::from_str("ศไทย中华Việt Nam")); - - let xs = b"hello\xFF".to_vec(); - let err = String::from_utf8(xs).err().unwrap(); - assert_eq!(err.utf8_error(), Utf8Error::TooShort); - assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); - } - - #[test] - fn test_from_utf8_lossy() { - let xs = b"hello"; - let ys: CowString = "hello".into_cow(); - assert_eq!(String::from_utf8_lossy(xs), ys); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - let ys: CowString = "ศไทย中华Việt Nam".into_cow(); - assert_eq!(String::from_utf8_lossy(xs), ys); - - let xs = b"Hello\xC2 There\xFF Goodbye"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()); - - let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()); - - let xs = b"\xF5foo\xF5\x80bar"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()); - - let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()); - - let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()); - - let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; - assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\ - foo\u{10000}bar").into_cow()); - - // surrogates - let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; - assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}foo\ - \u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()); - } - - #[test] - fn test_from_utf16() { - let pairs = - [(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), - vec![0xd800, 0xdf45, 0xd800, 0xdf3f, - 0xd800, 0xdf3b, 0xd800, 0xdf46, - 0xd800, 0xdf39, 0xd800, 0xdf3b, - 0xd800, 0xdf30, 0x000a]), - - (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), - vec![0xd801, 0xdc12, 0xd801, - 0xdc49, 0xd801, 0xdc2e, 0xd801, - 0xdc40, 0xd801, 0xdc32, 0xd801, - 0xdc4b, 0x0020, 0xd801, 0xdc0f, - 0xd801, 0xdc32, 0xd801, 0xdc4d, - 0x000a]), - - (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), - vec![0xd800, 0xdf00, 0xd800, 0xdf16, - 0xd800, 0xdf0b, 0xd800, 0xdf04, - 0xd800, 0xdf11, 0xd800, 0xdf09, - 0x00b7, 0xd800, 0xdf0c, 0xd800, - 0xdf04, 0xd800, 0xdf15, 0xd800, - 0xdf04, 0xd800, 0xdf0b, 0xd800, - 0xdf09, 0xd800, 0xdf11, 0x000a ]), - - (String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), - vec![0xd801, 0xdc8b, 0xd801, 0xdc98, - 0xd801, 0xdc88, 0xd801, 0xdc91, - 0xd801, 0xdc9b, 0xd801, 0xdc92, - 0x0020, 0xd801, 0xdc95, 0xd801, - 0xdc93, 0x0020, 0xd801, 0xdc88, - 0xd801, 0xdc9a, 0xd801, 0xdc8d, - 0x0020, 0xd801, 0xdc8f, 0xd801, - 0xdc9c, 0xd801, 0xdc92, 0xd801, - 0xdc96, 0xd801, 0xdc86, 0x0020, - 0xd801, 0xdc95, 0xd801, 0xdc86, - 0x000a ]), - // Issue #12318, even-numbered non-BMP planes - (String::from_str("\u{20000}"), - vec![0xD840, 0xDC00])]; - - for p in &pairs { - let (s, u) = (*p).clone(); - let s_as_utf16 = s.utf16_units().collect::<Vec<u16>>(); - let u_as_string = String::from_utf16(&u).unwrap(); - - assert!(::unicode::str::is_utf16(&u)); - assert_eq!(s_as_utf16, u); - - assert_eq!(u_as_string, s); - assert_eq!(String::from_utf16_lossy(&u), s); - - assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s); - assert_eq!(u_as_string.utf16_units().collect::<Vec<u16>>(), u); - } - } - - #[test] - fn test_utf16_invalid() { - // completely positive cases tested above. - // lead + eof - assert!(String::from_utf16(&[0xD800]).is_err()); - // lead + lead - assert!(String::from_utf16(&[0xD800, 0xD800]).is_err()); - - // isolated trail - assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err()); - - // general - assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err()); - } - - #[test] - fn test_from_utf16_lossy() { - // completely positive cases tested above. - // lead + eof - assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from_str("\u{FFFD}")); - // lead + lead - assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), - String::from_str("\u{FFFD}\u{FFFD}")); - - // isolated trail - assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from_str("a\u{FFFD}")); - - // general - assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), - String::from_str("\u{FFFD}𐒋\u{FFFD}")); - } - - #[test] - fn test_push_bytes() { - let mut s = String::from_str("ABC"); - unsafe { - let mv = s.as_mut_vec(); - mv.push_all(&[b'D']); - } - assert_eq!(s, "ABCD"); - } - - #[test] - fn test_push_str() { - let mut s = String::new(); - s.push_str(""); - assert_eq!(&s[0..], ""); - s.push_str("abc"); - assert_eq!(&s[0..], "abc"); - s.push_str("ประเทศไทย中华Việt Nam"); - assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam"); - } - - #[test] - fn test_push() { - let mut data = String::from_str("ประเทศไทย中"); - data.push('华'); - data.push('b'); // 1 byte - data.push('¢'); // 2 byte - data.push('€'); // 3 byte - data.push('𤭢'); // 4 byte - assert_eq!(data, "ประเทศไทย中华b¢€𤭢"); - } - - #[test] - fn test_pop() { - let mut data = String::from_str("ประเทศไทย中华b¢€𤭢"); - assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes - assert_eq!(data.pop().unwrap(), '€'); // 3 bytes - assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes - assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes - assert_eq!(data.pop().unwrap(), '华'); - assert_eq!(data, "ประเทศไทย中"); - } - - #[test] - fn test_str_truncate() { - let mut s = String::from_str("12345"); - s.truncate(5); - assert_eq!(s, "12345"); - s.truncate(3); - assert_eq!(s, "123"); - s.truncate(0); - assert_eq!(s, ""); - - let mut s = String::from_str("12345"); - let p = s.as_ptr(); - s.truncate(3); - s.push_str("6"); - let p_ = s.as_ptr(); - assert_eq!(p_, p); - } - - #[test] - #[should_panic] - fn test_str_truncate_invalid_len() { - let mut s = String::from_str("12345"); - s.truncate(6); - } - - #[test] - #[should_panic] - fn test_str_truncate_split_codepoint() { - let mut s = String::from_str("\u{FC}"); // ü - s.truncate(1); - } - - #[test] - fn test_str_clear() { - let mut s = String::from_str("12345"); - s.clear(); - assert_eq!(s.len(), 0); - assert_eq!(s, ""); - } - - #[test] - fn test_str_add() { - let a = String::from_str("12345"); - let b = a + "2"; - let b = b + "2"; - assert_eq!(b.len(), 7); - assert_eq!(b, "1234522"); - } - - #[test] - fn remove() { - let mut s = "ศไทย中华Việt Nam; foobar".to_string();; - assert_eq!(s.remove(0), 'ศ'); - assert_eq!(s.len(), 33); - assert_eq!(s, "ไทย中华Việt Nam; foobar"); - assert_eq!(s.remove(17), 'ệ'); - assert_eq!(s, "ไทย中华Vit Nam; foobar"); - } - - #[test] #[should_panic] - fn remove_bad() { - "ศ".to_string().remove(1); - } - - #[test] - fn insert() { - let mut s = "foobar".to_string(); - s.insert(0, 'ệ'); - assert_eq!(s, "ệfoobar"); - s.insert(6, 'ย'); - assert_eq!(s, "ệfooยbar"); - } - - #[test] #[should_panic] fn insert_bad1() { "".to_string().insert(1, 't'); } - #[test] #[should_panic] fn insert_bad2() { "ệ".to_string().insert(1, 't'); } - - #[test] - fn test_slicing() { - let s = "foobar".to_string(); - assert_eq!("foobar", &s[..]); - assert_eq!("foo", &s[..3]); - assert_eq!("bar", &s[3..]); - assert_eq!("oob", &s[1..4]); - } - - #[test] - fn test_simple_types() { - assert_eq!(1.to_string(), "1"); - assert_eq!((-1).to_string(), "-1"); - assert_eq!(200.to_string(), "200"); - assert_eq!(2.to_string(), "2"); - assert_eq!(true.to_string(), "true"); - assert_eq!(false.to_string(), "false"); - assert_eq!(("hi".to_string()).to_string(), "hi"); - } - - #[test] - fn test_vectors() { - let x: Vec<i32> = vec![]; - assert_eq!(format!("{:?}", x), "[]"); - assert_eq!(format!("{:?}", vec![1]), "[1]"); - assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]"); - assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == - "[[], [1], [1, 1]]"); - } - - #[test] - fn test_from_iterator() { - let s = "ศไทย中华Việt Nam".to_string(); - let t = "ศไทย中华"; - let u = "Việt Nam"; - - let a: String = s.chars().collect(); - assert_eq!(s, a); - - let mut b = t.to_string(); - b.extend(u.chars()); - assert_eq!(s, b); - - let c: String = vec![t, u].into_iter().collect(); - assert_eq!(s, c); - - let mut d = t.to_string(); - d.extend(vec![u].into_iter()); - assert_eq!(s, d); - } - - #[bench] - fn bench_with_capacity(b: &mut Bencher) { - b.iter(|| { - String::with_capacity(100) - }); - } - - #[bench] - fn bench_push_str(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - b.iter(|| { - let mut r = String::new(); - r.push_str(s); - }); - } - - const REPETITIONS: u64 = 10_000; - - #[bench] - fn bench_push_str_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push_str("a") - } - }); - } - - #[bench] - fn bench_push_char_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('a') - } - }); - } - - #[bench] - fn bench_push_char_two_bytes(b: &mut Bencher) { - b.bytes = REPETITIONS * 2; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('â') - } - }); - } - - #[bench] - fn from_utf8_lossy_100_ascii(b: &mut Bencher) { - let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { - let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_invalid(b: &mut Bencher) { - let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_100_invalid(b: &mut Bencher) { - let s = repeat(0xf5).take(100).collect::<Vec<_>>(); - b.iter(|| { - let _ = String::from_utf8_lossy(&s); - }); - } - - #[bench] - fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { - let s = "Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - // ensure our operation produces an exact-size string before we benchmark it - let mut r = String::with_capacity(s.len()); - r.push_str(s); - assert_eq!(r.len(), r.capacity()); - b.iter(|| { - let mut r = String::with_capacity(s.len()); - r.push_str(s); - r.shrink_to_fit(); - r - }); - } -} diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 67594b7c4bc..404179bd484 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -59,12 +59,12 @@ use core::intrinsics::assume; use core::iter::{repeat, FromIterator, IntoIterator}; use core::marker::PhantomData; use core::mem; +#[cfg(stage0)] use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; use core::ptr; use core::ptr::Unique; -use core::raw::Slice as RawSlice; use core::slice; use core::usize; @@ -435,10 +435,7 @@ impl<T> Vec<T> { unsafe { let ptr = *self.ptr; assume(!ptr.is_null()); - mem::transmute(RawSlice { - data: ptr, - len: self.len, - }) + slice::from_raw_parts_mut(ptr, self.len) } } @@ -1286,8 +1283,23 @@ pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> { #[unstable(feature = "collections")] impl<T:Clone> Clone for Vec<T> { + #[cfg(stage0)] fn clone(&self) -> Vec<T> { ::slice::SliceExt::to_vec(&**self) } + #[cfg(not(stage0))] + #[cfg(not(test))] + fn clone(&self) -> Vec<T> { <[T]>::to_vec(&**self) } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is required for this + // method definition, is not available. Instead use the `slice::to_vec` function which is only + // available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(not(stage0))] + #[cfg(test)] + fn clone(&self) -> Vec<T> { + ::slice::to_vec(&**self) + } + fn clone_from(&mut self, other: &Vec<T>) { // drop anything in self that will not be overwritten if self.len() > other.len() { @@ -1560,10 +1572,7 @@ impl<T> AsSlice<T> for Vec<T> { unsafe { let p = *self.ptr; assume(p != 0 as *mut T); - mem::transmute(RawSlice { - data: p, - len: self.len - }) + slice::from_raw_parts(p, self.len) } } } @@ -1953,991 +1962,3 @@ impl<T,U> Drop for PartialVecZeroSized<T,U> { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - use core::mem::size_of; - use core::iter::repeat; - use test::Bencher; - use super::as_vec; - - struct DropCounter<'a> { - count: &'a mut u32 - } - - #[unsafe_destructor] - impl<'a> Drop for DropCounter<'a> { - fn drop(&mut self) { - *self.count += 1; - } - } - - #[test] - fn test_as_vec() { - let xs = [1u8, 2u8, 3u8]; - assert_eq!(&**as_vec(&xs), xs); - } - - #[test] - fn test_as_vec_dtor() { - let (mut count_x, mut count_y) = (0, 0); - { - let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }]; - assert_eq!(as_vec(xs).len(), 2); - } - assert_eq!(count_x, 1); - assert_eq!(count_y, 1); - } - - #[test] - fn test_small_vec_struct() { - assert!(size_of::<Vec<u8>>() == size_of::<usize>() * 3); - } - - #[test] - fn test_double_drop() { - struct TwoVec<T> { - x: Vec<T>, - y: Vec<T> - } - - let (mut count_x, mut count_y) = (0, 0); - { - let mut tv = TwoVec { - x: Vec::new(), - y: Vec::new() - }; - tv.x.push(DropCounter {count: &mut count_x}); - tv.y.push(DropCounter {count: &mut count_y}); - - // If Vec had a drop flag, here is where it would be zeroed. - // Instead, it should rely on its internal state to prevent - // doing anything significant when dropped multiple times. - drop(tv.x); - - // Here tv goes out of scope, tv.y should be dropped, but not tv.x. - } - - assert_eq!(count_x, 1); - assert_eq!(count_y, 1); - } - - #[test] - fn test_reserve() { - let mut v = Vec::new(); - assert_eq!(v.capacity(), 0); - - v.reserve(2); - assert!(v.capacity() >= 2); - - for i in 0..16 { - v.push(i); - } - - assert!(v.capacity() >= 16); - v.reserve(16); - assert!(v.capacity() >= 32); - - v.push(16); - - v.reserve(16); - assert!(v.capacity() >= 33) - } - - #[test] - fn test_extend() { - let mut v = Vec::new(); - let mut w = Vec::new(); - - v.extend(0..3); - for i in 0..3 { w.push(i) } - - assert_eq!(v, w); - - v.extend(3..10); - for i in 3..10 { w.push(i) } - - assert_eq!(v, w); - } - - #[test] - fn test_slice_from_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let slice = &mut values[2 ..]; - assert!(slice == [3, 4, 5]); - for p in slice { - *p += 2; - } - } - - assert!(values == [1, 2, 5, 6, 7]); - } - - #[test] - fn test_slice_to_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let slice = &mut values[.. 2]; - assert!(slice == [1, 2]); - for p in slice { - *p += 1; - } - } - - assert!(values == [2, 3, 3, 4, 5]); - } - - #[test] - fn test_split_at_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let (left, right) = values.split_at_mut(2); - { - let left: &[_] = left; - assert!(&left[..left.len()] == &[1, 2]); - } - for p in left { - *p += 1; - } - - { - let right: &[_] = right; - assert!(&right[..right.len()] == &[3, 4, 5]); - } - for p in right { - *p += 2; - } - } - - assert_eq!(values, [2, 3, 5, 6, 7]); - } - - #[test] - fn test_clone() { - let v: Vec<i32> = vec![]; - let w = vec!(1, 2, 3); - - assert_eq!(v, v.clone()); - - let z = w.clone(); - assert_eq!(w, z); - // they should be disjoint in memory. - assert!(w.as_ptr() != z.as_ptr()) - } - - #[test] - fn test_clone_from() { - let mut v = vec!(); - let three: Vec<Box<_>> = vec!(box 1, box 2, box 3); - let two: Vec<Box<_>> = vec!(box 4, box 5); - // zero, long - v.clone_from(&three); - assert_eq!(v, three); - - // equal - v.clone_from(&three); - assert_eq!(v, three); - - // long, short - v.clone_from(&two); - assert_eq!(v, two); - - // short, long - v.clone_from(&three); - assert_eq!(v, three) - } - - #[test] - fn test_retain() { - let mut vec = vec![1, 2, 3, 4]; - vec.retain(|&x| x % 2 == 0); - assert_eq!(vec, [2, 4]); - } - - #[test] - fn zero_sized_values() { - let mut v = Vec::new(); - assert_eq!(v.len(), 0); - v.push(()); - assert_eq!(v.len(), 1); - v.push(()); - assert_eq!(v.len(), 2); - assert_eq!(v.pop(), Some(())); - assert_eq!(v.pop(), Some(())); - assert_eq!(v.pop(), None); - - assert_eq!(v.iter().count(), 0); - v.push(()); - assert_eq!(v.iter().count(), 1); - v.push(()); - assert_eq!(v.iter().count(), 2); - - for &() in &v {} - - assert_eq!(v.iter_mut().count(), 2); - v.push(()); - assert_eq!(v.iter_mut().count(), 3); - v.push(()); - assert_eq!(v.iter_mut().count(), 4); - - for &mut () in &mut v {} - unsafe { v.set_len(0); } - assert_eq!(v.iter_mut().count(), 0); - } - - #[test] - fn test_partition() { - assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3])); - } - - #[test] - fn test_zip_unzip() { - let z1 = vec![(1, 4), (2, 5), (3, 6)]; - - let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip(); - - assert_eq!((1, 4), (left[0], right[0])); - assert_eq!((2, 5), (left[1], right[1])); - assert_eq!((3, 6), (left[2], right[2])); - } - - #[test] - fn test_unsafe_ptrs() { - unsafe { - // Test on-stack copy-from-buf. - let a = [1, 2, 3]; - let ptr = a.as_ptr(); - let b = Vec::from_raw_buf(ptr, 3); - assert_eq!(b, [1, 2, 3]); - - // Test on-heap copy-from-buf. - let c = vec![1, 2, 3, 4, 5]; - let ptr = c.as_ptr(); - let d = Vec::from_raw_buf(ptr, 5); - assert_eq!(d, [1, 2, 3, 4, 5]); - } - } - - #[test] - fn test_vec_truncate_drop() { - static mut drops: u32 = 0; - struct Elem(i32); - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; - assert_eq!(unsafe { drops }, 0); - v.truncate(3); - assert_eq!(unsafe { drops }, 2); - v.truncate(0); - assert_eq!(unsafe { drops }, 5); - } - - #[test] - #[should_panic] - fn test_vec_truncate_fail() { - struct BadElem(i32); - impl Drop for BadElem { - fn drop(&mut self) { - let BadElem(ref mut x) = *self; - if *x == 0xbadbeef { - panic!("BadElem panic: 0xbadbeef") - } - } - } - - let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)]; - v.truncate(0); - } - - #[test] - fn test_index() { - let vec = vec![1, 2, 3]; - assert!(vec[1] == 2); - } - - #[test] - #[should_panic] - fn test_index_out_of_bounds() { - let vec = vec![1, 2, 3]; - let _ = vec[3]; - } - - #[test] - #[should_panic] - fn test_slice_out_of_bounds_1() { - let x = vec![1, 2, 3, 4, 5]; - &x[-1..]; - } - - #[test] - #[should_panic] - fn test_slice_out_of_bounds_2() { - let x = vec![1, 2, 3, 4, 5]; - &x[..6]; - } - - #[test] - #[should_panic] - fn test_slice_out_of_bounds_3() { - let x = vec![1, 2, 3, 4, 5]; - &x[-1..4]; - } - - #[test] - #[should_panic] - fn test_slice_out_of_bounds_4() { - let x = vec![1, 2, 3, 4, 5]; - &x[1..6]; - } - - #[test] - #[should_panic] - fn test_slice_out_of_bounds_5() { - let x = vec![1, 2, 3, 4, 5]; - &x[3..2]; - } - - #[test] - #[should_panic] - fn test_swap_remove_empty() { - let mut vec= Vec::<i32>::new(); - vec.swap_remove(0); - } - - #[test] - fn test_move_iter_unwrap() { - let mut vec = Vec::with_capacity(7); - vec.push(1); - vec.push(2); - let ptr = vec.as_ptr(); - vec = vec.into_iter().into_inner(); - assert_eq!(vec.as_ptr(), ptr); - assert_eq!(vec.capacity(), 7); - assert_eq!(vec.len(), 0); - } - - #[test] - #[should_panic] - fn test_map_in_place_incompatible_types_fail() { - let v = vec![0, 1, 2]; - v.map_in_place(|_| ()); - } - - #[test] - fn test_map_in_place() { - let v = vec![0, 1, 2]; - assert_eq!(v.map_in_place(|i: u32| i as i32 - 1), [-1, 0, 1]); - } - - #[test] - fn test_map_in_place_zero_sized() { - let v = vec![(), ()]; - #[derive(PartialEq, Debug)] - struct ZeroSized; - assert_eq!(v.map_in_place(|_| ZeroSized), [ZeroSized, ZeroSized]); - } - - #[test] - fn test_map_in_place_zero_drop_count() { - use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; - - #[derive(Clone, PartialEq, Debug)] - struct Nothing; - impl Drop for Nothing { fn drop(&mut self) { } } - - #[derive(Clone, PartialEq, Debug)] - struct ZeroSized; - impl Drop for ZeroSized { - fn drop(&mut self) { - DROP_COUNTER.fetch_add(1, Ordering::Relaxed); - } - } - const NUM_ELEMENTS: usize = 2; - static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; - - let v = repeat(Nothing).take(NUM_ELEMENTS).collect::<Vec<_>>(); - - DROP_COUNTER.store(0, Ordering::Relaxed); - - let v = v.map_in_place(|_| ZeroSized); - assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), 0); - drop(v); - assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), NUM_ELEMENTS); - } - - #[test] - fn test_move_items() { - let vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec { - vec2.push(i); - } - assert_eq!(vec2, [1, 2, 3]); - } - - #[test] - fn test_move_items_reverse() { - let vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.into_iter().rev() { - vec2.push(i); - } - assert_eq!(vec2, [3, 2, 1]); - } - - #[test] - fn test_move_items_zero_sized() { - let vec = vec![(), (), ()]; - let mut vec2 = vec![]; - for i in vec { - vec2.push(i); - } - assert_eq!(vec2, [(), (), ()]); - } - - #[test] - fn test_drain_items() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.drain() { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [ 1, 2, 3 ]); - } - - #[test] - fn test_drain_items_reverse() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.drain().rev() { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [3, 2, 1]); - } - - #[test] - fn test_drain_items_zero_sized() { - let mut vec = vec![(), (), ()]; - let mut vec2 = vec![]; - for i in vec.drain() { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [(), (), ()]); - } - - #[test] - fn test_into_boxed_slice() { - let xs = vec![1, 2, 3]; - let ys = xs.into_boxed_slice(); - assert_eq!(&*ys, [1, 2, 3]); - } - - #[test] - fn test_append() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![4, 5, 6]; - vec.append(&mut vec2); - assert_eq!(vec, [1, 2, 3, 4, 5, 6]); - assert_eq!(vec2, []); - } - - #[test] - fn test_split_off() { - let mut vec = vec![1, 2, 3, 4, 5, 6]; - let vec2 = vec.split_off(4); - assert_eq!(vec, [1, 2, 3, 4]); - assert_eq!(vec2, [5, 6]); - } - - #[bench] - fn bench_new(b: &mut Bencher) { - b.iter(|| { - let v: Vec<u32> = Vec::new(); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), 0); - }) - } - - fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let v: Vec<u32> = Vec::with_capacity(src_len); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), src_len); - }) - } - - #[bench] - fn bench_with_capacity_0000(b: &mut Bencher) { - do_bench_with_capacity(b, 0) - } - - #[bench] - fn bench_with_capacity_0010(b: &mut Bencher) { - do_bench_with_capacity(b, 10) - } - - #[bench] - fn bench_with_capacity_0100(b: &mut Bencher) { - do_bench_with_capacity(b, 100) - } - - #[bench] - fn bench_with_capacity_1000(b: &mut Bencher) { - do_bench_with_capacity(b, 1000) - } - - fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let dst = (0..src_len).collect::<Vec<_>>(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }) - } - - #[bench] - fn bench_from_fn_0000(b: &mut Bencher) { - do_bench_from_fn(b, 0) - } - - #[bench] - fn bench_from_fn_0010(b: &mut Bencher) { - do_bench_from_fn(b, 10) - } - - #[bench] - fn bench_from_fn_0100(b: &mut Bencher) { - do_bench_from_fn(b, 100) - } - - #[bench] - fn bench_from_fn_1000(b: &mut Bencher) { - do_bench_from_fn(b, 1000) - } - - fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let dst: Vec<usize> = repeat(5).take(src_len).collect(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().all(|x| *x == 5)); - }) - } - - #[bench] - fn bench_from_elem_0000(b: &mut Bencher) { - do_bench_from_elem(b, 0) - } - - #[bench] - fn bench_from_elem_0010(b: &mut Bencher) { - do_bench_from_elem(b, 10) - } - - #[bench] - fn bench_from_elem_0100(b: &mut Bencher) { - do_bench_from_elem(b, 100) - } - - #[bench] - fn bench_from_elem_1000(b: &mut Bencher) { - do_bench_from_elem(b, 1000) - } - - fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst = src.clone()[..].to_vec(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_from_slice_0000(b: &mut Bencher) { - do_bench_from_slice(b, 0) - } - - #[bench] - fn bench_from_slice_0010(b: &mut Bencher) { - do_bench_from_slice(b, 10) - } - - #[bench] - fn bench_from_slice_0100(b: &mut Bencher) { - do_bench_from_slice(b, 100) - } - - #[bench] - fn bench_from_slice_1000(b: &mut Bencher) { - do_bench_from_slice(b, 1000) - } - - fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst: Vec<_> = FromIterator::from_iter(src.clone().into_iter()); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_from_iter_0000(b: &mut Bencher) { - do_bench_from_iter(b, 0) - } - - #[bench] - fn bench_from_iter_0010(b: &mut Bencher) { - do_bench_from_iter(b, 10) - } - - #[bench] - fn bench_from_iter_0100(b: &mut Bencher) { - do_bench_from_iter(b, 100) - } - - #[bench] - fn bench_from_iter_1000(b: &mut Bencher) { - do_bench_from_iter(b, 1000) - } - - fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend(src.clone().into_iter()); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_extend_0000_0000(b: &mut Bencher) { - do_bench_extend(b, 0, 0) - } - - #[bench] - fn bench_extend_0000_0010(b: &mut Bencher) { - do_bench_extend(b, 0, 10) - } - - #[bench] - fn bench_extend_0000_0100(b: &mut Bencher) { - do_bench_extend(b, 0, 100) - } - - #[bench] - fn bench_extend_0000_1000(b: &mut Bencher) { - do_bench_extend(b, 0, 1000) - } - - #[bench] - fn bench_extend_0010_0010(b: &mut Bencher) { - do_bench_extend(b, 10, 10) - } - - #[bench] - fn bench_extend_0100_0100(b: &mut Bencher) { - do_bench_extend(b, 100, 100) - } - - #[bench] - fn bench_extend_1000_1000(b: &mut Bencher) { - do_bench_extend(b, 1000, 1000) - } - - fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.push_all(&src); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_push_all_0000_0000(b: &mut Bencher) { - do_bench_push_all(b, 0, 0) - } - - #[bench] - fn bench_push_all_0000_0010(b: &mut Bencher) { - do_bench_push_all(b, 0, 10) - } - - #[bench] - fn bench_push_all_0000_0100(b: &mut Bencher) { - do_bench_push_all(b, 0, 100) - } - - #[bench] - fn bench_push_all_0000_1000(b: &mut Bencher) { - do_bench_push_all(b, 0, 1000) - } - - #[bench] - fn bench_push_all_0010_0010(b: &mut Bencher) { - do_bench_push_all(b, 10, 10) - } - - #[bench] - fn bench_push_all_0100_0100(b: &mut Bencher) { - do_bench_push_all(b, 100, 100) - } - - #[bench] - fn bench_push_all_1000_1000(b: &mut Bencher) { - do_bench_push_all(b, 1000, 1000) - } - - fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend(src.clone().into_iter()); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_push_all_move_0000_0000(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 0) - } - - #[bench] - fn bench_push_all_move_0000_0010(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 10) - } - - #[bench] - fn bench_push_all_move_0000_0100(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 100) - } - - #[bench] - fn bench_push_all_move_0000_1000(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 1000) - } - - #[bench] - fn bench_push_all_move_0010_0010(b: &mut Bencher) { - do_bench_push_all_move(b, 10, 10) - } - - #[bench] - fn bench_push_all_move_0100_0100(b: &mut Bencher) { - do_bench_push_all_move(b, 100, 100) - } - - #[bench] - fn bench_push_all_move_1000_1000(b: &mut Bencher) { - do_bench_push_all_move(b, 1000, 1000) - } - - fn do_bench_clone(b: &mut Bencher, src_len: usize) { - let src: Vec<usize> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst = src.clone(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_clone_0000(b: &mut Bencher) { - do_bench_clone(b, 0) - } - - #[bench] - fn bench_clone_0010(b: &mut Bencher) { - do_bench_clone(b, 10) - } - - #[bench] - fn bench_clone_0100(b: &mut Bencher) { - do_bench_clone(b, 100) - } - - #[bench] - fn bench_clone_1000(b: &mut Bencher) { - do_bench_clone(b, 1000) - } - - fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..src_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = (times * src_len) as u64; - - b.iter(|| { - let mut dst = dst.clone(); - - for _ in 0..times { - dst.clone_from(&src); - - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); - } - }); - } - - #[bench] - fn bench_clone_from_01_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 0) - } - - #[bench] - fn bench_clone_from_01_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 10) - } - - #[bench] - fn bench_clone_from_01_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 100) - } - - #[bench] - fn bench_clone_from_01_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 10) - } - - #[bench] - fn bench_clone_from_01_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 100) - } - - #[bench] - fn bench_clone_from_01_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 100) - } - - #[bench] - fn bench_clone_from_01_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 0) - } - - #[bench] - fn bench_clone_from_01_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 10) - } - - #[bench] - fn bench_clone_from_01_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 100) - } - - #[bench] - fn bench_clone_from_10_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 0) - } - - #[bench] - fn bench_clone_from_10_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 10) - } - - #[bench] - fn bench_clone_from_10_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 100) - } - - #[bench] - fn bench_clone_from_10_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 10) - } - - #[bench] - fn bench_clone_from_10_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 100) - } - - #[bench] - fn bench_clone_from_10_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 100) - } - - #[bench] - fn bench_clone_from_10_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 0) - } - - #[bench] - fn bench_clone_from_10_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 10) - } - - #[bench] - fn bench_clone_from_10_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 100) - } -} diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 3e364584597..aefcad49a58 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -25,11 +25,12 @@ use core::default::Default; use core::fmt; use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; use core::mem; +#[cfg(stage0)] use core::num::{Int, UnsignedInt}; use core::num::wrapping::WrappingOps; use core::ops::{Index, IndexMut}; use core::ptr::{self, Unique}; -use core::raw::Slice as RawSlice; +use core::slice; use core::hash::{Hash, Hasher}; use core::cmp; @@ -91,13 +92,13 @@ impl<T> VecDeque<T> { /// Turn ptr into a slice #[inline] unsafe fn buffer_as_slice(&self) -> &[T] { - mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap }) + slice::from_raw_parts(*self.ptr, self.cap) } /// Turn ptr into a mut slice #[inline] unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] { - mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap }) + slice::from_raw_parts_mut(*self.ptr, self.cap) } /// Moves an element out of the buffer @@ -1769,138 +1770,14 @@ impl<T: fmt::Debug> fmt::Debug for VecDeque<T> { } #[cfg(test)] -mod tests { - use self::Taggy::*; - use self::Taggypar::*; - use prelude::*; - use core::iter; - use std::fmt::Debug; - use std::hash::{self, SipHasher}; - use test::Bencher; +mod test { + use core::iter::{IteratorExt, self}; + use core::option::Option::Some; + use test; use super::VecDeque; - #[test] - #[allow(deprecated)] - fn test_simple() { - let mut d = VecDeque::new(); - assert_eq!(d.len(), 0); - d.push_front(17); - d.push_front(42); - d.push_back(137); - assert_eq!(d.len(), 3); - d.push_back(137); - assert_eq!(d.len(), 4); - assert_eq!(*d.front().unwrap(), 42); - assert_eq!(*d.back().unwrap(), 137); - let mut i = d.pop_front(); - assert_eq!(i, Some(42)); - i = d.pop_back(); - assert_eq!(i, Some(137)); - i = d.pop_back(); - assert_eq!(i, Some(137)); - i = d.pop_back(); - assert_eq!(i, Some(17)); - assert_eq!(d.len(), 0); - d.push_back(3); - assert_eq!(d.len(), 1); - d.push_front(2); - assert_eq!(d.len(), 2); - d.push_back(4); - assert_eq!(d.len(), 3); - d.push_front(1); - assert_eq!(d.len(), 4); - debug!("{}", d[0]); - debug!("{}", d[1]); - debug!("{}", d[2]); - debug!("{}", d[3]); - assert_eq!(d[0], 1); - assert_eq!(d[1], 2); - assert_eq!(d[2], 3); - assert_eq!(d[3], 4); - } - - #[cfg(test)] - fn test_parameterized<T:Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) { - let mut deq = VecDeque::new(); - assert_eq!(deq.len(), 0); - deq.push_front(a.clone()); - deq.push_front(b.clone()); - deq.push_back(c.clone()); - assert_eq!(deq.len(), 3); - deq.push_back(d.clone()); - assert_eq!(deq.len(), 4); - assert_eq!((*deq.front().unwrap()).clone(), b.clone()); - assert_eq!((*deq.back().unwrap()).clone(), d.clone()); - assert_eq!(deq.pop_front().unwrap(), b.clone()); - assert_eq!(deq.pop_back().unwrap(), d.clone()); - assert_eq!(deq.pop_back().unwrap(), c.clone()); - assert_eq!(deq.pop_back().unwrap(), a.clone()); - assert_eq!(deq.len(), 0); - deq.push_back(c.clone()); - assert_eq!(deq.len(), 1); - deq.push_front(b.clone()); - assert_eq!(deq.len(), 2); - deq.push_back(d.clone()); - assert_eq!(deq.len(), 3); - deq.push_front(a.clone()); - assert_eq!(deq.len(), 4); - assert_eq!(deq[0].clone(), a.clone()); - assert_eq!(deq[1].clone(), b.clone()); - assert_eq!(deq[2].clone(), c.clone()); - assert_eq!(deq[3].clone(), d.clone()); - } - - #[test] - fn test_push_front_grow() { - let mut deq = VecDeque::new(); - for i in 0..66 { - deq.push_front(i); - } - assert_eq!(deq.len(), 66); - - for i in 0..66 { - assert_eq!(deq[i], 65 - i); - } - - let mut deq = VecDeque::new(); - for i in 0..66 { - deq.push_back(i); - } - - for i in 0..66 { - assert_eq!(deq[i], i); - } - } - - #[test] - fn test_index() { - let mut deq = VecDeque::new(); - for i in 1..4 { - deq.push_front(i); - } - assert_eq!(deq[1], 2); - } - - #[test] - #[should_panic] - fn test_index_out_of_bounds() { - let mut deq = VecDeque::new(); - for i in 1..4 { - deq.push_front(i); - } - deq[3]; - } - - #[bench] - fn bench_new(b: &mut test::Bencher) { - b.iter(|| { - let ring: VecDeque<i32> = VecDeque::new(); - test::black_box(ring); - }) - } - #[bench] fn bench_push_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); @@ -1951,666 +1828,6 @@ mod tests { }) } - #[bench] - fn bench_grow_1025(b: &mut test::Bencher) { - b.iter(|| { - let mut deq = VecDeque::new(); - for i in 0..1025 { - deq.push_front(i); - } - test::black_box(deq); - }) - } - - #[bench] - fn bench_iter_1000(b: &mut test::Bencher) { - let ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for &i in &ring { - sum += i; - } - test::black_box(sum); - }) - } - - #[bench] - fn bench_mut_iter_1000(b: &mut test::Bencher) { - let mut ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for i in &mut ring { - sum += *i; - } - test::black_box(sum); - }) - } - - #[derive(Clone, PartialEq, Debug)] - enum Taggy { - One(i32), - Two(i32, i32), - Three(i32, i32, i32), - } - - #[derive(Clone, PartialEq, Debug)] - enum Taggypar<T> { - Onepar(T), - Twopar(T, T), - Threepar(T, T, T), - } - - #[derive(Clone, PartialEq, Debug)] - struct RecCy { - x: i32, - y: i32, - t: Taggy - } - - #[test] - fn test_param_int() { - test_parameterized::<i32>(5, 72, 64, 175); - } - - #[test] - fn test_param_taggy() { - test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); - } - - #[test] - fn test_param_taggypar() { - test_parameterized::<Taggypar<i32>>(Onepar::<i32>(1), - Twopar::<i32>(1, 2), - Threepar::<i32>(1, 2, 3), - Twopar::<i32>(17, 42)); - } - - #[test] - fn test_param_reccy() { - let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; - let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; - let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; - let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; - test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4); - } - - #[test] - fn test_with_capacity() { - let mut d = VecDeque::with_capacity(0); - d.push_back(1); - assert_eq!(d.len(), 1); - let mut d = VecDeque::with_capacity(50); - d.push_back(1); - assert_eq!(d.len(), 1); - } - - #[test] - fn test_with_capacity_non_power_two() { - let mut d3 = VecDeque::with_capacity(3); - d3.push_back(1); - - // X = None, | = lo - // [|1, X, X] - assert_eq!(d3.pop_front(), Some(1)); - // [X, |X, X] - assert_eq!(d3.front(), None); - - // [X, |3, X] - d3.push_back(3); - // [X, |3, 6] - d3.push_back(6); - // [X, X, |6] - assert_eq!(d3.pop_front(), Some(3)); - - // Pushing the lo past half way point to trigger - // the 'B' scenario for growth - // [9, X, |6] - d3.push_back(9); - // [9, 12, |6] - d3.push_back(12); - - d3.push_back(15); - // There used to be a bug here about how the - // VecDeque made growth assumptions about the - // underlying Vec which didn't hold and lead - // to corruption. - // (Vec grows to next power of two) - //good- [9, 12, 15, X, X, X, X, |6] - //bug- [15, 12, X, X, X, |6, X, X] - assert_eq!(d3.pop_front(), Some(6)); - - // Which leads us to the following state which - // would be a failure case. - //bug- [15, 12, X, X, X, X, |X, X] - assert_eq!(d3.front(), Some(&9)); - } - - #[test] - fn test_reserve_exact() { - let mut d = VecDeque::new(); - d.push_back(0); - d.reserve_exact(50); - assert!(d.capacity() >= 51); - } - - #[test] - fn test_reserve() { - let mut d = VecDeque::new(); - d.push_back(0); - d.reserve(50); - assert!(d.capacity() >= 51); - } - - #[test] - fn test_swap() { - let mut d: VecDeque<_> = (0..5).collect(); - d.pop_front(); - d.swap(0, 3); - assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]); - } - - #[test] - fn test_iter() { - let mut d = VecDeque::new(); - assert_eq!(d.iter().next(), None); - assert_eq!(d.iter().size_hint(), (0, Some(0))); - - for i in 0..5 { - d.push_back(i); - } - { - let b: &[_] = &[&0,&1,&2,&3,&4]; - assert_eq!(d.iter().collect::<Vec<_>>(), b); - } - - for i in 6..9 { - d.push_front(i); - } - { - let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4]; - assert_eq!(d.iter().collect::<Vec<_>>(), b); - } - - let mut it = d.iter(); - let mut len = d.len(); - loop { - match it.next() { - None => break, - _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) } - } - } - } - - #[test] - fn test_rev_iter() { - let mut d = VecDeque::new(); - assert_eq!(d.iter().rev().next(), None); - - for i in 0..5 { - d.push_back(i); - } - { - let b: &[_] = &[&4,&3,&2,&1,&0]; - assert_eq!(d.iter().rev().collect::<Vec<_>>(), b); - } - - for i in 6..9 { - d.push_front(i); - } - let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8]; - assert_eq!(d.iter().rev().collect::<Vec<_>>(), b); - } - - #[test] - fn test_mut_rev_iter_wrap() { - let mut d = VecDeque::with_capacity(3); - assert!(d.iter_mut().rev().next().is_none()); - - d.push_back(1); - d.push_back(2); - d.push_back(3); - assert_eq!(d.pop_front(), Some(1)); - d.push_back(4); - - assert_eq!(d.iter_mut().rev().cloned().collect::<Vec<_>>(), - vec![4, 3, 2]); - } - - #[test] - fn test_mut_iter() { - let mut d = VecDeque::new(); - assert!(d.iter_mut().next().is_none()); - - for i in 0..3 { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().enumerate() { - assert_eq!(*elt, 2 - i); - *elt = i; - } - - { - let mut it = d.iter_mut(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } - } - - #[test] - fn test_mut_rev_iter() { - let mut d = VecDeque::new(); - assert!(d.iter_mut().rev().next().is_none()); - - for i in 0..3 { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().rev().enumerate() { - assert_eq!(*elt, i); - *elt = i; - } - - { - let mut it = d.iter_mut().rev(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } - } - - #[test] - fn test_into_iter() { - - // Empty iter - { - let d: VecDeque<i32> = VecDeque::new(); - let mut iter = d.into_iter(); - - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - // simple iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - - let b = vec![0,1,2,3,4]; - assert_eq!(d.into_iter().collect::<Vec<_>>(), b); - } - - // wrapped iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - let b = vec![8,7,6,0,1,2,3,4]; - assert_eq!(d.into_iter().collect::<Vec<_>>(), b); - } - - // partially used - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - let mut it = d.into_iter(); - assert_eq!(it.size_hint(), (8, Some(8))); - assert_eq!(it.next(), Some(8)); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.next(), Some(7)); - assert_eq!(it.size_hint(), (5, Some(5))); - } - } - - #[test] - fn test_drain() { - - // Empty iter - { - let mut d: VecDeque<i32> = VecDeque::new(); - - { - let mut iter = d.drain(); - - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert!(d.is_empty()); - } - - // simple iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - - assert_eq!(d.drain().collect::<Vec<_>>(), [0, 1, 2, 3, 4]); - assert!(d.is_empty()); - } - - // wrapped iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - assert_eq!(d.drain().collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]); - assert!(d.is_empty()); - } - - // partially used - { - let mut d: VecDeque<_> = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - { - let mut it = d.drain(); - assert_eq!(it.size_hint(), (8, Some(8))); - assert_eq!(it.next(), Some(8)); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.next(), Some(7)); - assert_eq!(it.size_hint(), (5, Some(5))); - } - assert!(d.is_empty()); - } - } - - #[test] - fn test_from_iter() { - use core::iter; - let v = vec!(1,2,3,4,5,6,7); - let deq: VecDeque<_> = v.iter().cloned().collect(); - let u: Vec<_> = deq.iter().cloned().collect(); - assert_eq!(u, v); - - let seq = iter::count(0, 2).take(256); - let deq: VecDeque<_> = seq.collect(); - for (i, &x) in deq.iter().enumerate() { - assert_eq!(2*i, x); - } - assert_eq!(deq.len(), 256); - } - - #[test] - fn test_clone() { - let mut d = VecDeque::new(); - d.push_front(17); - d.push_front(42); - d.push_back(137); - d.push_back(137); - assert_eq!(d.len(), 4); - let mut e = d.clone(); - assert_eq!(e.len(), 4); - while !d.is_empty() { - assert_eq!(d.pop_back(), e.pop_back()); - } - assert_eq!(d.len(), 0); - assert_eq!(e.len(), 0); - } - - #[test] - fn test_eq() { - let mut d = VecDeque::new(); - assert!(d == VecDeque::with_capacity(0)); - d.push_front(137); - d.push_front(17); - d.push_front(42); - d.push_back(137); - let mut e = VecDeque::with_capacity(0); - e.push_back(42); - e.push_back(17); - e.push_back(137); - e.push_back(137); - assert!(&e == &d); - e.pop_back(); - e.push_back(0); - assert!(e != d); - e.clear(); - assert!(e == VecDeque::new()); - } - - #[test] - fn test_hash() { - let mut x = VecDeque::new(); - let mut y = VecDeque::new(); - - x.push_back(1); - x.push_back(2); - x.push_back(3); - - y.push_back(0); - y.push_back(1); - y.pop_front(); - y.push_back(2); - y.push_back(3); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - #[test] - fn test_ord() { - let x = VecDeque::new(); - let mut y = VecDeque::new(); - y.push_back(1); - y.push_back(2); - y.push_back(3); - assert!(x < y); - assert!(y > x); - assert!(x <= x); - assert!(x >= x); - } - - #[test] - fn test_show() { - let ringbuf: VecDeque<_> = (0..10).collect(); - assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - - let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter() - .cloned() - .collect(); - assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]"); - } - - #[test] - fn test_drop() { - static mut drops: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - drop(ring); - - assert_eq!(unsafe {drops}, 4); - } - - #[test] - fn test_drop_with_pop() { - static mut drops: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - - drop(ring.pop_back()); - drop(ring.pop_front()); - assert_eq!(unsafe {drops}, 2); - - drop(ring); - assert_eq!(unsafe {drops}, 4); - } - - #[test] - fn test_drop_clear() { - static mut drops: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - ring.clear(); - assert_eq!(unsafe {drops}, 4); - - drop(ring); - assert_eq!(unsafe {drops}, 4); - } - - #[test] - fn test_reserve_grow() { - // test growth path A - // [T o o H] -> [T o o H . . . . ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - - // test growth path B - // [H T o o] -> [. T o o H . . . ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..1 { - ring.push_back(i); - assert_eq!(ring.pop_front(), Some(i)); - } - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - - // test growth path C - // [o o H T] -> [o o H . . . . T ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..3 { - ring.push_back(i); - assert_eq!(ring.pop_front(), Some(i)); - } - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - } - - #[test] - fn test_get() { - let mut ring = VecDeque::new(); - ring.push_back(0); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), None); - - ring.push_back(1); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), Some(&1)); - assert_eq!(ring.get(2), None); - - ring.push_back(2); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), Some(&1)); - assert_eq!(ring.get(2), Some(&2)); - assert_eq!(ring.get(3), None); - - assert_eq!(ring.pop_front(), Some(0)); - assert_eq!(ring.get(0), Some(&1)); - assert_eq!(ring.get(1), Some(&2)); - assert_eq!(ring.get(2), None); - - assert_eq!(ring.pop_front(), Some(1)); - assert_eq!(ring.get(0), Some(&2)); - assert_eq!(ring.get(1), None); - - assert_eq!(ring.pop_front(), Some(2)); - assert_eq!(ring.get(0), None); - assert_eq!(ring.get(1), None); - } - - #[test] - fn test_get_mut() { - let mut ring = VecDeque::new(); - for i in 0..3 { - ring.push_back(i); - } - - match ring.get_mut(1) { - Some(x) => *x = -1, - None => () - }; - - assert_eq!(ring.get_mut(0), Some(&mut 0)); - assert_eq!(ring.get_mut(1), Some(&mut -1)); - assert_eq!(ring.get_mut(2), Some(&mut 2)); - assert_eq!(ring.get_mut(3), None); - - assert_eq!(ring.pop_front(), Some(0)); - assert_eq!(ring.get_mut(0), Some(&mut -1)); - assert_eq!(ring.get_mut(1), Some(&mut 2)); - assert_eq!(ring.get_mut(2), None); - } - #[test] fn test_swap_front_back_remove() { fn test(back: bool) { @@ -2759,74 +1976,6 @@ mod tests { } #[test] - fn test_front() { - let mut ring = VecDeque::new(); - ring.push_back(10); - ring.push_back(20); - assert_eq!(ring.front(), Some(&10)); - ring.pop_front(); - assert_eq!(ring.front(), Some(&20)); - ring.pop_front(); - assert_eq!(ring.front(), None); - } - - #[test] - fn test_as_slices() { - let mut ring: VecDeque<i32> = VecDeque::with_capacity(127); - let cap = ring.capacity() as i32; - let first = cap/2; - let last = cap - first; - for i in 0..first { - ring.push_back(i); - - let (left, right) = ring.as_slices(); - let expected: Vec<_> = (0..i+1).collect(); - assert_eq!(left, expected); - assert_eq!(right, []); - } - - for j in -last..0 { - ring.push_front(j); - let (left, right) = ring.as_slices(); - let expected_left: Vec<_> = (-last..j+1).rev().collect(); - let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, expected_left); - assert_eq!(right, expected_right); - } - - assert_eq!(ring.len() as i32, cap); - assert_eq!(ring.capacity() as i32, cap); - } - - #[test] - fn test_as_mut_slices() { - let mut ring: VecDeque<i32> = VecDeque::with_capacity(127); - let cap = ring.capacity() as i32; - let first = cap/2; - let last = cap - first; - for i in 0..first { - ring.push_back(i); - - let (left, right) = ring.as_mut_slices(); - let expected: Vec<_> = (0..i+1).collect(); - assert_eq!(left, expected); - assert_eq!(right, []); - } - - for j in -last..0 { - ring.push_front(j); - let (left, right) = ring.as_mut_slices(); - let expected_left: Vec<_> = (-last..j+1).rev().collect(); - let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, expected_left); - assert_eq!(right, expected_right); - } - - assert_eq!(ring.len() as i32, cap); - assert_eq!(ring.capacity() as i32, cap); - } - - #[test] fn test_split_off() { // This test checks that every single combination of tail position, length, and // split position is tested. Capacity 15 should be large enough to cover every case. @@ -2863,25 +2012,4 @@ mod tests { } } } - - #[test] - fn test_append() { - let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); - let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect(); - - // normal append - a.append(&mut b); - assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []); - - // append nothing to something - a.append(&mut b); - assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []); - - // append something to nothing - b.append(&mut a); - assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []); - } } diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 431c8d5df8c..6e67d876327 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -1004,510 +1004,3 @@ impl<V> Iterator for IntoIter<V> { impl<V> DoubleEndedIterator for IntoIter<V> { fn next_back(&mut self) -> Option<(usize, V)> { self.iter.next_back() } } - -#[cfg(test)] -mod test_map { - use prelude::*; - use core::hash::{hash, SipHasher}; - - use super::VecMap; - use super::Entry::{Occupied, Vacant}; - - #[test] - fn test_get_mut() { - let mut m = VecMap::new(); - assert!(m.insert(1, 12).is_none()); - assert!(m.insert(2, 8).is_none()); - assert!(m.insert(5, 14).is_none()); - let new = 100; - match m.get_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.get(&5), Some(&new)); - } - - #[test] - fn test_len() { - let mut map = VecMap::new(); - assert_eq!(map.len(), 0); - assert!(map.is_empty()); - assert!(map.insert(5, 20).is_none()); - assert_eq!(map.len(), 1); - assert!(!map.is_empty()); - assert!(map.insert(11, 12).is_none()); - assert_eq!(map.len(), 2); - assert!(!map.is_empty()); - assert!(map.insert(14, 22).is_none()); - assert_eq!(map.len(), 3); - assert!(!map.is_empty()); - } - - #[test] - fn test_clear() { - let mut map = VecMap::new(); - assert!(map.insert(5, 20).is_none()); - assert!(map.insert(11, 12).is_none()); - assert!(map.insert(14, 22).is_none()); - map.clear(); - assert!(map.is_empty()); - assert!(map.get(&5).is_none()); - assert!(map.get(&11).is_none()); - assert!(map.get(&14).is_none()); - } - - #[test] - fn test_insert() { - let mut m = VecMap::new(); - assert_eq!(m.insert(1, 2), None); - assert_eq!(m.insert(1, 3), Some(2)); - assert_eq!(m.insert(1, 4), Some(3)); - } - - #[test] - fn test_remove() { - let mut m = VecMap::new(); - m.insert(1, 2); - assert_eq!(m.remove(&1), Some(2)); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_keys() { - let mut map = VecMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let keys: Vec<_> = map.keys().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let mut map = VecMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let values: Vec<_> = map.values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - let mut it = m.iter(); - assert_eq!(it.size_hint(), (0, Some(11))); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.size_hint(), (0, Some(10))); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.size_hint(), (0, Some(9))); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.size_hint(), (0, Some(7))); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.size_hint(), (0, Some(4))); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_size_hints() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - assert_eq!(m.iter().size_hint(), (0, Some(11))); - assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); - } - - #[test] - fn test_mut_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - for (k, v) in &mut m { - *v += k as isize; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_rev_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - let mut it = m.iter().rev(); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.next().unwrap(), (0, &1)); - assert!(it.next().is_none()); - } - - #[test] - fn test_mut_rev_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - for (k, v) in m.iter_mut().rev() { - *v += k as isize; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_move_iter() { - let mut m: VecMap<Box<_>> = VecMap::new(); - m.insert(1, box 2); - let mut called = false; - for (k, v) in m { - assert!(!called); - called = true; - assert_eq!(k, 1); - assert_eq!(v, box 2); - } - assert!(called); - } - - #[test] - fn test_drain_iterator() { - let mut map = VecMap::new(); - map.insert(1, "a"); - map.insert(3, "c"); - map.insert(2, "b"); - - let vec: Vec<_> = map.drain().collect(); - - assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); - assert_eq!(map.len(), 0); - } - - #[test] - fn test_append() { - let mut a = VecMap::new(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - - let mut b = VecMap::new(); - b.insert(3, "d"); // Overwrite element from a - b.insert(4, "e"); - b.insert(5, "f"); - - a.append(&mut b); - - assert_eq!(a.len(), 5); - assert_eq!(b.len(), 0); - // Capacity shouldn't change for possible reuse - assert!(b.capacity() >= 4); - - assert_eq!(a[1], "a"); - assert_eq!(a[2], "b"); - assert_eq!(a[3], "d"); - assert_eq!(a[4], "e"); - assert_eq!(a[5], "f"); - } - - #[test] - fn test_split_off() { - // Split within the key range - let mut a = VecMap::new(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - a.insert(4, "d"); - - let b = a.split_off(3); - - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - - assert_eq!(a[1], "a"); - assert_eq!(a[2], "b"); - - assert_eq!(b[3], "c"); - assert_eq!(b[4], "d"); - - // Split at 0 - a.clear(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - a.insert(4, "d"); - - let b = a.split_off(0); - - assert_eq!(a.len(), 0); - assert_eq!(b.len(), 4); - assert_eq!(b[1], "a"); - assert_eq!(b[2], "b"); - assert_eq!(b[3], "c"); - assert_eq!(b[4], "d"); - - // Split behind max_key - a.clear(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - a.insert(4, "d"); - - let b = a.split_off(5); - - assert_eq!(a.len(), 4); - assert_eq!(b.len(), 0); - assert_eq!(a[1], "a"); - assert_eq!(a[2], "b"); - assert_eq!(a[3], "c"); - assert_eq!(a[4], "d"); - } - - #[test] - fn test_show() { - let mut map = VecMap::new(); - let empty = VecMap::<i32>::new(); - - map.insert(1, 2); - map.insert(3, 4); - - let map_str = format!("{:?}", map); - assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); - assert_eq!(format!("{:?}", empty), "{}"); - } - - #[test] - fn test_clone() { - let mut a = VecMap::new(); - - a.insert(1, 'x'); - a.insert(4, 'y'); - a.insert(6, 'z'); - - assert!(a.clone() == a); - } - - #[test] - fn test_eq() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(a == b); - assert!(a.insert(0, 5).is_none()); - assert!(a != b); - assert!(b.insert(0, 4).is_none()); - assert!(a != b); - assert!(a.insert(5, 19).is_none()); - assert!(a != b); - assert!(!b.insert(0, 5).is_none()); - assert!(a != b); - assert!(b.insert(5, 19).is_none()); - assert!(a == b); - - a = VecMap::new(); - b = VecMap::with_capacity(1); - assert!(a == b); - } - - #[test] - fn test_lt() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(2, 5).is_none()); - assert!(a < b); - assert!(a.insert(2, 7).is_none()); - assert!(!(a < b) && b < a); - assert!(b.insert(1, 0).is_none()); - assert!(b < a); - assert!(a.insert(0, 6).is_none()); - assert!(a < b); - assert!(a.insert(6, 2).is_none()); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1, 1).is_none()); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2, 2).is_none()); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - #[test] - fn test_hash() { - let mut x = VecMap::new(); - let mut y = VecMap::new(); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - x.insert(1, 'a'); - x.insert(2, 'b'); - x.insert(3, 'c'); - - y.insert(3, 'c'); - y.insert(2, 'b'); - y.insert(1, 'a'); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - - x.insert(1000, 'd'); - x.remove(&1000); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - } - - #[test] - fn test_from_iter() { - let xs = vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; - - let map: VecMap<_> = xs.iter().cloned().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - } - - #[test] - fn test_index() { - let mut map = VecMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[3], 4); - } - - #[test] - #[should_panic] - fn test_index_nonexistent() { - let mut map = VecMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[4]; - } - - #[test] - fn test_entry(){ - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: VecMap<_> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - *v *= 10; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } -} - -#[cfg(test)] -mod bench { - use super::VecMap; - - map_insert_rand_bench!{insert_rand_100, 100, VecMap} - map_insert_rand_bench!{insert_rand_10_000, 10_000, VecMap} - - map_insert_seq_bench!{insert_seq_100, 100, VecMap} - map_insert_seq_bench!{insert_seq_10_000, 10_000, VecMap} - - map_find_rand_bench!{find_rand_100, 100, VecMap} - map_find_rand_bench!{find_rand_10_000, 10_000, VecMap} - - map_find_seq_bench!{find_seq_100, 100, VecMap} - map_find_seq_bench!{find_seq_10_000, 10_000, VecMap} -} diff --git a/src/libcollections/bench.rs b/src/libcollectionstest/bench.rs index 107f6031c11..2396a577589 100644 --- a/src/libcollections/bench.rs +++ b/src/libcollectionstest/bench.rs @@ -66,11 +66,11 @@ macro_rules! map_find_rand_bench { ($name: ident, $n: expr, $map: ident) => ( #[bench] pub fn $name(b: &mut ::test::Bencher) { - use std::rand; use std::iter::IteratorExt; use std::rand::Rng; + use std::rand; + use std::vec::Vec; use test::black_box; - use vec::Vec; let mut map = $map::new(); let n: usize = $n; diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs new file mode 100644 index 00000000000..47a366bb1e2 --- /dev/null +++ b/src/libcollectionstest/binary_heap.rs @@ -0,0 +1,219 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BinaryHeap; + +#[test] +fn test_iterator() { + let data = vec![5, 9, 3]; + let iterout = [9, 5, 3]; + let heap = BinaryHeap::from_vec(data); + let mut i = 0; + for el in &heap { + assert_eq!(*el, iterout[i]); + i += 1; + } +} + +#[test] +fn test_iterator_reverse() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from_vec(data); + + let v: Vec<_> = pq.iter().rev().cloned().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_move_iter() { + let data = vec![5, 9, 3]; + let iterout = vec![9, 5, 3]; + let pq = BinaryHeap::from_vec(data); + + let v: Vec<_> = pq.into_iter().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_move_iter_size_hint() { + let data = vec![5, 9]; + let pq = BinaryHeap::from_vec(data); + + let mut it = pq.into_iter(); + + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next(), Some(9)); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next(), Some(5)); + + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_move_iter_reverse() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from_vec(data); + + let v: Vec<_> = pq.into_iter().rev().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_peek_and_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from_vec(data); + while !heap.is_empty() { + assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); + assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); + } +} + +#[test] +fn test_push() { + let mut heap = BinaryHeap::from_vec(vec![2, 4, 9]); + assert_eq!(heap.len(), 3); + assert!(*heap.peek().unwrap() == 9); + heap.push(11); + assert_eq!(heap.len(), 4); + assert!(*heap.peek().unwrap() == 11); + heap.push(5); + assert_eq!(heap.len(), 5); + assert!(*heap.peek().unwrap() == 11); + heap.push(27); + assert_eq!(heap.len(), 6); + assert!(*heap.peek().unwrap() == 27); + heap.push(3); + assert_eq!(heap.len(), 7); + assert!(*heap.peek().unwrap() == 27); + heap.push(103); + assert_eq!(heap.len(), 8); + assert!(*heap.peek().unwrap() == 103); +} + +#[test] +fn test_push_unique() { + let mut heap = BinaryHeap::<Box<_>>::from_vec(vec![box 2, box 4, box 9]); + assert_eq!(heap.len(), 3); + assert!(*heap.peek().unwrap() == box 9); + heap.push(box 11); + assert_eq!(heap.len(), 4); + assert!(*heap.peek().unwrap() == box 11); + heap.push(box 5); + assert_eq!(heap.len(), 5); + assert!(*heap.peek().unwrap() == box 11); + heap.push(box 27); + assert_eq!(heap.len(), 6); + assert!(*heap.peek().unwrap() == box 27); + heap.push(box 3); + assert_eq!(heap.len(), 7); + assert!(*heap.peek().unwrap() == box 27); + heap.push(box 103); + assert_eq!(heap.len(), 8); + assert!(*heap.peek().unwrap() == box 103); +} + +#[test] +fn test_push_pop() { + let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(6), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(0), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(4), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(1), 4); + assert_eq!(heap.len(), 5); +} + +#[test] +fn test_replace() { + let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(6).unwrap(), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(0).unwrap(), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(4).unwrap(), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(1).unwrap(), 4); + assert_eq!(heap.len(), 5); +} + +fn check_to_vec(mut data: Vec<i32>) { + let heap = BinaryHeap::from_vec(data.clone()); + let mut v = heap.clone().into_vec(); + v.sort(); + data.sort(); + + assert_eq!(v, data); + assert_eq!(heap.into_sorted_vec(), data); +} + +#[test] +fn test_to_vec() { + check_to_vec(vec![]); + check_to_vec(vec![5]); + check_to_vec(vec![3, 2]); + check_to_vec(vec![2, 3]); + check_to_vec(vec![5, 1, 2]); + check_to_vec(vec![1, 100, 2, 3]); + check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); + check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); + check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); +} + +#[test] +fn test_empty_pop() { + let mut heap = BinaryHeap::<i32>::new(); + assert!(heap.pop().is_none()); +} + +#[test] +fn test_empty_peek() { + let empty = BinaryHeap::<i32>::new(); + assert!(empty.peek().is_none()); +} + +#[test] +fn test_empty_replace() { + let mut heap = BinaryHeap::new(); + assert!(heap.replace(5).is_none()); +} + +#[test] +fn test_from_iter() { + let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); + + for &x in &xs { + assert_eq!(q.pop().unwrap(), x); + } +} + +#[test] +fn test_drain() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain().take(5).count(), 5); + + assert!(q.is_empty()); +} diff --git a/src/libcollectionstest/bit/mod.rs b/src/libcollectionstest/bit/mod.rs new file mode 100644 index 00000000000..8e06524f2e5 --- /dev/null +++ b/src/libcollectionstest/bit/mod.rs @@ -0,0 +1,12 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod set; +mod vec; diff --git a/src/libcollectionstest/bit/set.rs b/src/libcollectionstest/bit/set.rs new file mode 100644 index 00000000000..4b4995d5fa7 --- /dev/null +++ b/src/libcollectionstest/bit/set.rs @@ -0,0 +1,441 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::collections::{BitSet, BitVec}; +use std::iter::range_step; + +#[test] +fn test_bit_set_show() { + let mut s = BitSet::new(); + s.insert(1); + s.insert(10); + s.insert(50); + s.insert(2); + assert_eq!("{1, 2, 10, 50}", format!("{:?}", s)); +} + +#[test] +fn test_bit_set_from_usizes() { + let usizes = vec![0, 2, 2, 3]; + let a: BitSet = usizes.into_iter().collect(); + let mut b = BitSet::new(); + b.insert(0); + b.insert(2); + b.insert(3); + assert_eq!(a, b); +} + +#[test] +fn test_bit_set_iterator() { + let usizes = vec![0, 2, 2, 3]; + let bit_vec: BitSet = usizes.into_iter().collect(); + + let idxs: Vec<_> = bit_vec.iter().collect(); + assert_eq!(idxs, [0, 2, 3]); + + let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); + let real: Vec<_> = range_step(0, 10000, 2).collect(); + + let idxs: Vec<_> = long.iter().collect(); + assert_eq!(idxs, real); +} + +#[test] +fn test_bit_set_frombit_vec_init() { + let bools = [true, false]; + let lengths = [10, 64, 100]; + for &b in &bools { + for &l in &lengths { + let bitset = BitSet::from_bit_vec(BitVec::from_elem(l, b)); + assert_eq!(bitset.contains(&1), b); + assert_eq!(bitset.contains(&(l-1)), b); + assert!(!bitset.contains(&l)); + } + } +} + +#[test] +fn test_bit_vec_masking() { + let b = BitVec::from_elem(140, true); + let mut bs = BitSet::from_bit_vec(b); + assert!(bs.contains(&139)); + assert!(!bs.contains(&140)); + assert!(bs.insert(150)); + assert!(!bs.contains(&140)); + assert!(!bs.contains(&149)); + assert!(bs.contains(&150)); + assert!(!bs.contains(&151)); +} + +#[test] +fn test_bit_set_basic() { + let mut b = BitSet::new(); + assert!(b.insert(3)); + assert!(!b.insert(3)); + assert!(b.contains(&3)); + assert!(b.insert(4)); + assert!(!b.insert(4)); + assert!(b.contains(&3)); + assert!(b.insert(400)); + assert!(!b.insert(400)); + assert!(b.contains(&400)); + assert_eq!(b.len(), 3); +} + +#[test] +fn test_bit_set_intersection() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(11)); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(77)); + assert!(a.insert(103)); + assert!(a.insert(5)); + + assert!(b.insert(2)); + assert!(b.insert(11)); + assert!(b.insert(77)); + assert!(b.insert(5)); + assert!(b.insert(3)); + + let expected = [3, 5, 11, 77]; + let actual: Vec<_> = a.intersection(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_difference() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(200)); + assert!(a.insert(500)); + + assert!(b.insert(3)); + assert!(b.insert(200)); + + let expected = [1, 5, 500]; + let actual: Vec<_> = a.difference(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_symmetric_difference() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3)); + assert!(b.insert(9)); + assert!(b.insert(14)); + assert!(b.insert(220)); + + let expected = [1, 5, 11, 14, 220]; + let actual: Vec<_> = a.symmetric_difference(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_union() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + assert!(a.insert(160)); + assert!(a.insert(19)); + assert!(a.insert(24)); + assert!(a.insert(200)); + + assert!(b.insert(1)); + assert!(b.insert(5)); + assert!(b.insert(9)); + assert!(b.insert(13)); + assert!(b.insert(19)); + + let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; + let actual: Vec<_> = a.union(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_subset() { + let mut set1 = BitSet::new(); + let mut set2 = BitSet::new(); + + assert!(set1.is_subset(&set2)); // {} {} + set2.insert(100); + assert!(set1.is_subset(&set2)); // {} { 1 } + set2.insert(200); + assert!(set1.is_subset(&set2)); // {} { 1, 2 } + set1.insert(200); + assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } + set1.insert(300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } + set2.insert(300); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } + set2.insert(400); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } + set2.remove(&100); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } + set2.remove(&300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } + set1.remove(&300); + assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } +} + +#[test] +fn test_bit_set_is_disjoint() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01000000])); + let c = BitSet::new(); + let d = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00110000])); + + assert!(!a.is_disjoint(&d)); + assert!(!d.is_disjoint(&a)); + + assert!(a.is_disjoint(&b)); + assert!(a.is_disjoint(&c)); + assert!(b.is_disjoint(&a)); + assert!(b.is_disjoint(&c)); + assert!(c.is_disjoint(&a)); + assert!(c.is_disjoint(&b)); +} + +#[test] +fn test_bit_set_union_with() { + //a should grow to include larger elements + let mut a = BitSet::new(); + a.insert(0); + let mut b = BitSet::new(); + b.insert(5); + let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); + a.union_with(&b); + assert_eq!(a, expected); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.union_with(&b); + b.union_with(&c); + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 4); +} + +#[test] +fn test_bit_set_intersect_with() { + // Explicitly 0'ed bits + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::new(); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); +} + +#[test] +fn test_bit_set_difference_with() { + // Explicitly 0'ed bits + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitSet::new(); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11111111])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.difference_with(&b); + b.difference_with(&c); + assert_eq!(a.len(), 1); + assert_eq!(b.len(), 1); +} + +#[test] +fn test_bit_set_symmetric_difference_with() { + //a should grow to include larger elements + let mut a = BitSet::new(); + a.insert(0); + a.insert(1); + let mut b = BitSet::new(); + b.insert(1); + b.insert(5); + let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); + a.symmetric_difference_with(&b); + assert_eq!(a, expected); + + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::new(); + let c = a.clone(); + a.symmetric_difference_with(&b); + assert_eq!(a, c); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101010])); + let c = a.clone(); + a.symmetric_difference_with(&b); + b.symmetric_difference_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); +} + +#[test] +fn test_bit_set_eq() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = BitSet::new(); + + assert!(a == a); + assert!(a != b); + assert!(a != c); + assert!(b == b); + assert!(b == c); + assert!(c == c); +} + +#[test] +fn test_bit_set_cmp() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = BitSet::new(); + + assert_eq!(a.cmp(&b), Greater); + assert_eq!(a.cmp(&c), Greater); + assert_eq!(b.cmp(&a), Less); + assert_eq!(b.cmp(&c), Equal); + assert_eq!(c.cmp(&a), Less); + assert_eq!(c.cmp(&b), Equal); +} + +#[test] +fn test_bit_vec_remove() { + let mut a = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.remove(&1)); + + assert!(a.insert(100)); + assert!(a.remove(&100)); + + assert!(a.insert(1000)); + assert!(a.remove(&1000)); + a.shrink_to_fit(); +} + +#[test] +fn test_bit_vec_clone() { + let mut a = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(100)); + assert!(a.insert(1000)); + + let mut b = a.clone(); + + assert!(a == b); + + assert!(b.remove(&1)); + assert!(a.contains(&1)); + + assert!(a.remove(&1000)); + assert!(b.contains(&1000)); +} + +mod bench { + use std::collections::{BitSet, BitVec}; + use std::rand::{Rng, self}; + use std::u32; + + use test::{Bencher, black_box}; + + const BENCH_BITS : usize = 1 << 14; + + fn rng() -> rand::IsaacRng { + let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + rand::SeedableRng::from_seed(seed) + } + + #[bench] + fn bench_bit_vecset_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitSet::new(); + b.iter(|| { + for _ in 0..100 { + bit_vec.insert((r.next_u32() as usize) % u32::BITS as usize); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vecset_big(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitSet::new(); + b.iter(|| { + for _ in 0..100 { + bit_vec.insert((r.next_u32() as usize) % BENCH_BITS); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vecset_iter(b: &mut Bencher) { + let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, + |idx| {idx % 3 == 0})); + b.iter(|| { + let mut sum = 0; + for idx in &bit_vec { + sum += idx as usize; + } + sum + }) + } +} diff --git a/src/libcollectionstest/bit/vec.rs b/src/libcollectionstest/bit/vec.rs new file mode 100644 index 00000000000..3826974d1ad --- /dev/null +++ b/src/libcollectionstest/bit/vec.rs @@ -0,0 +1,729 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BitVec; +use std::u32; + +#[test] +fn test_to_str() { + let zerolen = BitVec::new(); + assert_eq!(format!("{:?}", zerolen), ""); + + let eightbits = BitVec::from_elem(8, false); + assert_eq!(format!("{:?}", eightbits), "00000000") +} + +#[test] +fn test_0_elements() { + let act = BitVec::new(); + let exp = Vec::new(); + assert!(act.eq_vec(&exp)); + assert!(act.none() && act.all()); +} + +#[test] +fn test_1_element() { + let mut act = BitVec::from_elem(1, false); + assert!(act.eq_vec(&[false])); + assert!(act.none() && !act.all()); + act = BitVec::from_elem(1, true); + assert!(act.eq_vec(&[true])); + assert!(!act.none() && act.all()); +} + +#[test] +fn test_2_elements() { + let mut b = BitVec::from_elem(2, false); + b.set(0, true); + b.set(1, false); + assert_eq!(format!("{:?}", b), "10"); + assert!(!b.none() && !b.all()); +} + +#[test] +fn test_10_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(10, false); + assert!((act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false]))); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(10, true); + assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(5, true); + act.set(6, true); + act.set(7, true); + act.set(8, true); + act.set(9, true); + assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(0, true); + act.set(3, true); + act.set(6, true); + act.set(9, true); + assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true]))); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_31_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(31, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(31, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_32_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(32, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(32, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true, true])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_33_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(33, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(33, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true, true, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + act.set(31, true); + act.set(32, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_equal_differing_sizes() { + let v0 = BitVec::from_elem(10, false); + let v1 = BitVec::from_elem(11, false); + assert!(v0 != v1); +} + +#[test] +fn test_equal_greatly_differing_sizes() { + let v0 = BitVec::from_elem(10, false); + let v1 = BitVec::from_elem(110, false); + assert!(v0 != v1); +} + +#[test] +fn test_equal_sneaky_small() { + let mut a = BitVec::from_elem(1, false); + a.set(0, true); + + let mut b = BitVec::from_elem(1, true); + b.set(0, true); + + assert_eq!(a, b); +} + +#[test] +fn test_equal_sneaky_big() { + let mut a = BitVec::from_elem(100, false); + for i in 0..100 { + a.set(i, true); + } + + let mut b = BitVec::from_elem(100, true); + for i in 0..100 { + b.set(i, true); + } + + assert_eq!(a, b); +} + +#[test] +fn test_from_bytes() { + let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let str = concat!("10110110", "00000000", "11111111"); + assert_eq!(format!("{:?}", bit_vec), str); +} + +#[test] +fn test_to_bytes() { + let mut bv = BitVec::from_elem(3, true); + bv.set(1, false); + assert_eq!(bv.to_bytes(), [0b10100000]); + + let mut bv = BitVec::from_elem(9, false); + bv.set(2, true); + bv.set(8, true); + assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); +} + +#[test] +fn test_from_bools() { + let bools = vec![true, false, true, true]; + let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); + assert_eq!(format!("{:?}", bit_vec), "1011"); +} + +#[test] +fn test_to_bools() { + let bools = vec![false, false, true, false, false, true, true, false]; + assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::<Vec<bool>>(), bools); +} + +#[test] +fn test_bit_vec_iterator() { + let bools = vec![true, false, true, true]; + let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); + + assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), bools); + + let long: Vec<_> = (0..10000).map(|i| i % 2 == 0).collect(); + let bit_vec: BitVec = long.iter().map(|n| *n).collect(); + assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), long) +} + +#[test] +fn test_small_difference() { + let mut b1 = BitVec::from_elem(3, false); + let mut b2 = BitVec::from_elem(3, false); + b1.set(0, true); + b1.set(1, true); + b2.set(1, true); + b2.set(2, true); + assert!(b1.difference(&b2)); + assert!(b1[0]); + assert!(!b1[1]); + assert!(!b1[2]); +} + +#[test] +fn test_big_difference() { + let mut b1 = BitVec::from_elem(100, false); + let mut b2 = BitVec::from_elem(100, false); + b1.set(0, true); + b1.set(40, true); + b2.set(40, true); + b2.set(80, true); + assert!(b1.difference(&b2)); + assert!(b1[0]); + assert!(!b1[40]); + assert!(!b1[80]); +} + +#[test] +fn test_small_clear() { + let mut b = BitVec::from_elem(14, true); + assert!(!b.none() && b.all()); + b.clear(); + assert!(b.none() && !b.all()); +} + +#[test] +fn test_big_clear() { + let mut b = BitVec::from_elem(140, true); + assert!(!b.none() && b.all()); + b.clear(); + assert!(b.none() && !b.all()); +} + +#[test] +fn test_bit_vec_lt() { + let mut a = BitVec::from_elem(5, false); + let mut b = BitVec::from_elem(5, false); + + assert!(!(a < b) && !(b < a)); + b.set(2, true); + assert!(a < b); + a.set(3, true); + assert!(a < b); + a.set(2, true); + assert!(!(a < b) && b < a); + b.set(0, true); + assert!(a < b); +} + +#[test] +fn test_ord() { + let mut a = BitVec::from_elem(5, false); + let mut b = BitVec::from_elem(5, false); + + assert!(a <= b && a >= b); + a.set(1, true); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + b.set(1, true); + b.set(2, true); + assert!(b > a && b >= a); + assert!(a < b && a <= b); +} + + +#[test] +fn test_small_bit_vec_tests() { + let v = BitVec::from_bytes(&[0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = BitVec::from_bytes(&[0b00010100]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = BitVec::from_bytes(&[0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); +} + +#[test] +fn test_big_bit_vec_tests() { + let v = BitVec::from_bytes(&[ // 88 bits + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = BitVec::from_bytes(&[ // 88 bits + 0, 0, 0b00010100, 0, + 0, 0, 0, 0b00110100, + 0, 0, 0]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = BitVec::from_bytes(&[ // 88 bits + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); +} + +#[test] +fn test_bit_vec_push_pop() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize - 2, false); + assert_eq!(s.len(), 5 * u32::BITS as usize - 2); + assert_eq!(s[5 * u32::BITS as usize - 3], false); + s.push(true); + s.push(true); + assert_eq!(s[5 * u32::BITS as usize - 2], true); + assert_eq!(s[5 * u32::BITS as usize - 1], true); + // Here the internal vector will need to be extended + s.push(false); + assert_eq!(s[5 * u32::BITS as usize], false); + s.push(false); + assert_eq!(s[5 * u32::BITS as usize + 1], false); + assert_eq!(s.len(), 5 * u32::BITS as usize + 2); + // Pop it all off + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.len(), 5 * u32::BITS as usize - 2); +} + +#[test] +fn test_bit_vec_truncate() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); + + assert_eq!(s, BitVec::from_elem(5 * u32::BITS as usize, true)); + assert_eq!(s.len(), 5 * u32::BITS as usize); + s.truncate(4 * u32::BITS as usize); + assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); + assert_eq!(s.len(), 4 * u32::BITS as usize); + // Truncating to a size > s.len() should be a noop + s.truncate(5 * u32::BITS as usize); + assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); + assert_eq!(s.len(), 4 * u32::BITS as usize); + s.truncate(3 * u32::BITS as usize - 10); + assert_eq!(s, BitVec::from_elem(3 * u32::BITS as usize - 10, true)); + assert_eq!(s.len(), 3 * u32::BITS as usize - 10); + s.truncate(0); + assert_eq!(s, BitVec::from_elem(0, true)); + assert_eq!(s.len(), 0); +} + +#[test] +fn test_bit_vec_reserve() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); + // Check capacity + assert!(s.capacity() >= 5 * u32::BITS as usize); + s.reserve(2 * u32::BITS as usize); + assert!(s.capacity() >= 7 * u32::BITS as usize); + s.reserve(7 * u32::BITS as usize); + assert!(s.capacity() >= 12 * u32::BITS as usize); + s.reserve_exact(7 * u32::BITS as usize); + assert!(s.capacity() >= 12 * u32::BITS as usize); + s.reserve(7 * u32::BITS as usize + 1); + assert!(s.capacity() >= 12 * u32::BITS as usize + 1); + // Check that length hasn't changed + assert_eq!(s.len(), 5 * u32::BITS as usize); + s.push(true); + s.push(false); + s.push(true); + assert_eq!(s[5 * u32::BITS as usize - 1], true); + assert_eq!(s[5 * u32::BITS as usize - 0], true); + assert_eq!(s[5 * u32::BITS as usize + 1], false); + assert_eq!(s[5 * u32::BITS as usize + 2], true); +} + +#[test] +fn test_bit_vec_grow() { + let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]); + bit_vec.grow(32, true); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF])); + bit_vec.grow(64, false); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); + bit_vec.grow(16, true); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); +} + +#[test] +fn test_bit_vec_extend() { + let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]); + bit_vec.extend(ext.iter()); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111, + 0b01001001, 0b10010010, 0b10111101])); +} + +mod bench { + use std::collections::BitVec; + use std::u32; + use std::rand::{Rng, self}; + + use test::{Bencher, black_box}; + + const BENCH_BITS : usize = 1 << 14; + + fn rng() -> rand::IsaacRng { + let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + rand::SeedableRng::from_seed(seed) + } + + #[bench] + fn bench_usize_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = 0 as usize; + b.iter(|| { + for _ in 0..100 { + bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS as usize); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_big_fixed(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_big_variable(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen()); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(u32::BITS as usize, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % u32::BITS as usize, true); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vec_big_union(b: &mut Bencher) { + let mut b1 = BitVec::from_elem(BENCH_BITS, false); + let b2 = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + b1.union(&b2) + }) + } + + #[bench] + fn bench_bit_vec_small_iter(b: &mut Bencher) { + let bit_vec = BitVec::from_elem(u32::BITS as usize, false); + b.iter(|| { + let mut sum = 0; + for _ in 0..10 { + for pres in &bit_vec { + sum += pres as usize; + } + } + sum + }) + } + + #[bench] + fn bench_bit_vec_big_iter(b: &mut Bencher) { + let bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + let mut sum = 0; + for pres in &bit_vec { + sum += pres as usize; + } + sum + }) + } +} diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs new file mode 100644 index 00000000000..10d69c9f5ec --- /dev/null +++ b/src/libcollectionstest/btree/map.rs @@ -0,0 +1,299 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeMap; +use std::collections::Bound::{Excluded, Included, Unbounded, self}; +use std::collections::btree_map::Entry::{Occupied, Vacant}; +use std::iter::range_inclusive; + +#[test] +fn test_basic_large() { + let mut map = BTreeMap::new(); + let size = 10000; + assert_eq!(map.len(), 0); + + for i in 0..size { + assert_eq!(map.insert(i, 10*i), None); + assert_eq!(map.len(), i + 1); + } + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i*10)); + } + + for i in size..size*2 { + assert_eq!(map.get(&i), None); + } + + for i in 0..size { + assert_eq!(map.insert(i, 100*i), Some(10*i)); + assert_eq!(map.len(), size); + } + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i*100)); + } + + for i in 0..size/2 { + assert_eq!(map.remove(&(i*2)), Some(i*200)); + assert_eq!(map.len(), size - i - 1); + } + + for i in 0..size/2 { + assert_eq!(map.get(&(2*i)), None); + assert_eq!(map.get(&(2*i+1)).unwrap(), &(i*200 + 100)); + } + + for i in 0..size/2 { + assert_eq!(map.remove(&(2*i)), None); + assert_eq!(map.remove(&(2*i+1)), Some(i*200 + 100)); + assert_eq!(map.len(), size/2 - i - 1); + } +} + +#[test] +fn test_basic_small() { + let mut map = BTreeMap::new(); + assert_eq!(map.remove(&1), None); + assert_eq!(map.get(&1), None); + assert_eq!(map.insert(1, 1), None); + assert_eq!(map.get(&1), Some(&1)); + assert_eq!(map.insert(1, 2), Some(1)); + assert_eq!(map.get(&1), Some(&2)); + assert_eq!(map.insert(2, 4), None); + assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.remove(&1), Some(2)); + assert_eq!(map.remove(&2), Some(4)); + assert_eq!(map.remove(&1), None); +} + +#[test] +fn test_iter() { + let size = 10000; + + // Forwards + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test<T>(size: usize, mut iter: T) where T: Iterator<Item=(usize, usize)> { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_iter_rev() { + let size = 10000; + + // Forwards + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test<T>(size: usize, mut iter: T) where T: Iterator<Item=(usize, usize)> { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().rev().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter().rev()); +} + +#[test] +fn test_iter_mixed() { + let size = 10000; + + // Forwards + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test<T>(size: usize, mut iter: T) + where T: Iterator<Item=(usize, usize)> + DoubleEndedIterator { + for i in 0..size / 4 { + assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); + assert_eq!(iter.next().unwrap(), (i, i)); + assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1)); + } + for i in size / 4..size * 3 / 4 { + assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_range_small() { + let size = 5; + + // Forwards + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + let mut j = 0; + for ((&k, &v), i) in map.range(Included(&2), Unbounded).zip(2..size) { + assert_eq!(k, i); + assert_eq!(v, i); + j += 1; + } + assert_eq!(j, size - 2); +} + +#[test] +fn test_range_1000() { + let size = 1000; + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) { + let mut kvs = map.range(min, max).map(|(&k, &v)| (k, v)); + let mut pairs = (0..size).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + test(&map, size, Included(&0), Excluded(&size)); + test(&map, size, Unbounded, Excluded(&size)); + test(&map, size, Included(&0), Included(&(size - 1))); + test(&map, size, Unbounded, Included(&(size - 1))); + test(&map, size, Included(&0), Unbounded); + test(&map, size, Unbounded, Unbounded); +} + +#[test] +fn test_range() { + let size = 200; + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + for i in 0..size { + for j in i..size { + let mut kvs = map.range(Included(&i), Included(&j)).map(|(&k, &v)| (k, v)); + let mut pairs = range_inclusive(i, j).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + } +} + +#[test] +fn test_entry(){ + let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map: BTreeMap<_, _> = xs.iter().cloned().collect(); + + // Existing key (insert) + match map.entry(1) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.insert(100), 10); + } + } + assert_eq!(map.get(&1).unwrap(), &100); + assert_eq!(map.len(), 6); + + + // Existing key (update) + match map.entry(2) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + let v = view.get_mut(); + *v *= 10; + } + } + assert_eq!(map.get(&2).unwrap(), &200); + assert_eq!(map.len(), 6); + + // Existing key (take) + match map.entry(3) { + Vacant(_) => unreachable!(), + Occupied(view) => { + assert_eq!(view.remove(), 30); + } + } + assert_eq!(map.get(&3), None); + assert_eq!(map.len(), 5); + + + // Inexistent key (insert) + match map.entry(10) { + Occupied(_) => unreachable!(), + Vacant(view) => { + assert_eq!(*view.insert(1000), 1000); + } + } + assert_eq!(map.get(&10).unwrap(), &1000); + assert_eq!(map.len(), 6); +} + +mod bench { + use std::collections::BTreeMap; + use std::rand::{Rng, weak_rng}; + + use test::{Bencher, black_box}; + + map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} + map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} + + map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} + map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} + + map_find_rand_bench!{find_rand_100, 100, BTreeMap} + map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} + + map_find_seq_bench!{find_seq_100, 100, BTreeMap} + map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} + + fn bench_iter(b: &mut Bencher, size: i32) { + let mut map = BTreeMap::<i32, i32>::new(); + let mut rng = weak_rng(); + + for _ in 0..size { + map.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for entry in &map { + black_box(entry); + } + }); + } + + #[bench] + pub fn iter_20(b: &mut Bencher) { + bench_iter(b, 20); + } + + #[bench] + pub fn iter_1000(b: &mut Bencher) { + bench_iter(b, 1000); + } + + #[bench] + pub fn iter_100000(b: &mut Bencher) { + bench_iter(b, 100000); + } +} diff --git a/src/libcollectionstest/btree/mod.rs b/src/libcollectionstest/btree/mod.rs new file mode 100644 index 00000000000..0db48f3ce9e --- /dev/null +++ b/src/libcollectionstest/btree/mod.rs @@ -0,0 +1,12 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod map; +mod set; diff --git a/src/libcollectionstest/btree/set.rs b/src/libcollectionstest/btree/set.rs new file mode 100644 index 00000000000..488f0d756d3 --- /dev/null +++ b/src/libcollectionstest/btree/set.rs @@ -0,0 +1,180 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeSet; +use std::hash::{SipHasher, self}; + +#[test] +fn test_clone_eq() { + let mut m = BTreeSet::new(); + + m.insert(1); + m.insert(2); + + assert!(m.clone() == m); +} + +#[test] +fn test_hash() { + let mut x = BTreeSet::new(); + let mut y = BTreeSet::new(); + + x.insert(1); + x.insert(2); + x.insert(3); + + y.insert(3); + y.insert(2); + y.insert(1); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +struct Counter<'a, 'b> { + i: &'a mut usize, + expected: &'b [i32], +} + +impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> { + type Output = bool; + + extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool { + assert_eq!(x, self.expected[*self.i]); + *self.i += 1; + true + } +} + +fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where + // FIXME Replace Counter with `Box<FnMut(_) -> _>` + F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool, +{ + let mut set_a = BTreeSet::new(); + let mut set_b = BTreeSet::new(); + + for x in a { assert!(set_a.insert(*x)) } + for y in b { assert!(set_b.insert(*y)) } + + let mut i = 0; + f(&set_a, &set_b, Counter { i: &mut i, expected: expected }); + assert_eq!(i, expected.len()); +} + +#[test] +fn test_intersection() { + fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.intersection(y).all(f)) + } + + check_intersection(&[], &[], &[]); + check_intersection(&[1, 2, 3], &[], &[]); + check_intersection(&[], &[1, 2, 3], &[]); + check_intersection(&[2], &[1, 2, 3], &[2]); + check_intersection(&[1, 2, 3], &[2], &[2]); + check_intersection(&[11, 1, 3, 77, 103, 5, -5], + &[2, 11, 77, -9, -42, 5, 3], + &[3, 5, 11, 77]); +} + +#[test] +fn test_difference() { + fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.difference(y).all(f)) + } + + check_difference(&[], &[], &[]); + check_difference(&[1, 12], &[], &[1, 12]); + check_difference(&[], &[1, 2, 3, 9], &[]); + check_difference(&[1, 3, 5, 9, 11], + &[3, 9], + &[1, 5, 11]); + check_difference(&[-5, 11, 22, 33, 40, 42], + &[-12, -5, 14, 23, 34, 38, 39, 50], + &[11, 22, 33, 40, 42]); +} + +#[test] +fn test_symmetric_difference() { + fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) + } + + check_symmetric_difference(&[], &[], &[]); + check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); + check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); + check_symmetric_difference(&[1, 3, 5, 9, 11], + &[-2, 3, 9, 14, 22], + &[-2, 1, 5, 11, 14, 22]); +} + +#[test] +fn test_union() { + fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.union(y).all(f)) + } + + check_union(&[], &[], &[]); + check_union(&[1, 2, 3], &[2], &[1, 2, 3]); + check_union(&[2], &[1, 2, 3], &[1, 2, 3]); + check_union(&[1, 3, 5, 9, 11, 16, 19, 24], + &[-2, 1, 5, 9, 13, 19], + &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); +} + +#[test] +fn test_zip() { + let mut x = BTreeSet::new(); + x.insert(5); + x.insert(12); + x.insert(11); + + let mut y = BTreeSet::new(); + y.insert("foo"); + y.insert("bar"); + + let x = x; + let y = y; + let mut z = x.iter().zip(y.iter()); + + // FIXME: #5801: this needs a type hint to compile... + let result: Option<(&usize, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&5, &("bar"))); + + let result: Option<(&usize, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&11, &("foo"))); + + let result: Option<(&usize, & &'static str)> = z.next(); + assert!(result.is_none()); +} + +#[test] +fn test_from_iter() { + let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let set: BTreeSet<_> = xs.iter().cloned().collect(); + + for x in &xs { + assert!(set.contains(x)); + } +} + +#[test] +fn test_show() { + let mut set = BTreeSet::new(); + let empty = BTreeSet::<i32>::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{:?}", set); + + assert_eq!(set_str, "{1, 2}"); + assert_eq!(format!("{:?}", empty), "{}"); +} diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs new file mode 100644 index 00000000000..f04367147cb --- /dev/null +++ b/src/libcollectionstest/enum_set.rs @@ -0,0 +1,244 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::mem; + +use collections::enum_set::{CLike, EnumSet}; + +use self::Foo::*; + +#[derive(Copy, PartialEq, Debug)] +#[repr(usize)] +enum Foo { + A, B, C +} + +impl CLike for Foo { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Foo { + unsafe { mem::transmute(v) } + } +} + +#[test] +fn test_new() { + let e: EnumSet<Foo> = EnumSet::new(); + assert!(e.is_empty()); +} + +#[test] +fn test_show() { + let mut e = EnumSet::new(); + assert!(format!("{:?}", e) == "{}"); + e.insert(A); + assert!(format!("{:?}", e) == "{A}"); + e.insert(C); + assert!(format!("{:?}", e) == "{A, C}"); +} + +#[test] +fn test_len() { + let mut e = EnumSet::new(); + assert_eq!(e.len(), 0); + e.insert(A); + e.insert(B); + e.insert(C); + assert_eq!(e.len(), 3); + e.remove(&A); + assert_eq!(e.len(), 2); + e.clear(); + assert_eq!(e.len(), 0); +} + +/////////////////////////////////////////////////////////////////////////// +// intersect + +#[test] +fn test_two_empties_do_not_intersect() { + let e1: EnumSet<Foo> = EnumSet::new(); + let e2: EnumSet<Foo> = EnumSet::new(); + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_empty_does_not_intersect_with_full() { + let e1: EnumSet<Foo> = EnumSet::new(); + + let mut e2: EnumSet<Foo> = EnumSet::new(); + e2.insert(A); + e2.insert(B); + e2.insert(C); + + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_disjoint_intersects() { + let mut e1: EnumSet<Foo> = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet<Foo> = EnumSet::new(); + e2.insert(B); + + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_overlapping_intersects() { + let mut e1: EnumSet<Foo> = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet<Foo> = EnumSet::new(); + e2.insert(A); + e2.insert(B); + + assert!(!e1.is_disjoint(&e2)); +} + +/////////////////////////////////////////////////////////////////////////// +// contains and contains_elem + +#[test] +fn test_superset() { + let mut e1: EnumSet<Foo> = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet<Foo> = EnumSet::new(); + e2.insert(A); + e2.insert(B); + + let mut e3: EnumSet<Foo> = EnumSet::new(); + e3.insert(C); + + assert!(e1.is_subset(&e2)); + assert!(e2.is_superset(&e1)); + assert!(!e3.is_superset(&e2)); + assert!(!e2.is_superset(&e3)) +} + +#[test] +fn test_contains() { + let mut e1: EnumSet<Foo> = EnumSet::new(); + e1.insert(A); + assert!(e1.contains(&A)); + assert!(!e1.contains(&B)); + assert!(!e1.contains(&C)); + + e1.insert(A); + e1.insert(B); + assert!(e1.contains(&A)); + assert!(e1.contains(&B)); + assert!(!e1.contains(&C)); +} + +/////////////////////////////////////////////////////////////////////////// +// iter + +#[test] +fn test_iterator() { + let mut e1: EnumSet<Foo> = EnumSet::new(); + + let elems: Vec<Foo> = e1.iter().collect(); + assert!(elems.is_empty()); + + e1.insert(A); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!([A], elems); + + e1.insert(C); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!([A,C], elems); + + e1.insert(C); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!([A,C], elems); + + e1.insert(B); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!([A,B,C], elems); +} + +/////////////////////////////////////////////////////////////////////////// +// operators + +#[test] +fn test_operators() { + let mut e1: EnumSet<Foo> = EnumSet::new(); + e1.insert(A); + e1.insert(C); + + let mut e2: EnumSet<Foo> = EnumSet::new(); + e2.insert(B); + e2.insert(C); + + let e_union = e1 | e2; + let elems: Vec<_> = e_union.iter().collect(); + assert_eq!([A,B,C], elems); + + let e_intersection = e1 & e2; + let elems: Vec<_> = e_intersection.iter().collect(); + assert_eq!([C], elems); + + // Another way to express intersection + let e_intersection = e1 - (e1 - e2); + let elems: Vec<_> = e_intersection.iter().collect(); + assert_eq!([C], elems); + + let e_subtract = e1 - e2; + let elems: Vec<_> = e_subtract.iter().collect(); + assert_eq!([A], elems); + + // Bitwise XOR of two sets, aka symmetric difference + let e_symmetric_diff = e1 ^ e2; + let elems: Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!([A,B], elems); + + // Another way to express symmetric difference + let e_symmetric_diff = (e1 - e2) | (e2 - e1); + let elems: Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!([A,B], elems); + + // Yet another way to express symmetric difference + let e_symmetric_diff = (e1 | e2) - (e1 & e2); + let elems: Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!([A,B], elems); +} + +#[test] +#[should_panic] +fn test_overflow() { + #[allow(dead_code)] + #[derive(Copy)] + #[repr(usize)] + enum Bar { + V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, + V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, + V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, + V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, + V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, + V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, + V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, + } + + impl CLike for Bar { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Bar { + unsafe { mem::transmute(v) } + } + } + let mut set = EnumSet::new(); + set.insert(Bar::V64); +} diff --git a/src/libcollectionstest/fmt.rs b/src/libcollectionstest/fmt.rs new file mode 100644 index 00000000000..9a9aa71b58b --- /dev/null +++ b/src/libcollectionstest/fmt.rs @@ -0,0 +1,17 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt; + +#[test] +fn test_format() { + let s = fmt::format(format_args!("Hello, {}!", "world")); + assert_eq!(s.as_slice(), "Hello, world!"); +} diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs new file mode 100644 index 00000000000..7f029340d25 --- /dev/null +++ b/src/libcollectionstest/lib.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(deprecated)] +#![feature(box_syntax)] +#![feature(collections)] +#![feature(core)] +#![feature(hash)] +#![feature(rand)] +#![feature(rustc_private)] +#![feature(str_words)] +#![feature(test)] +#![feature(unboxed_closures)] +#![feature(unicode)] +#![feature(unsafe_destructor)] + +#[macro_use] extern crate log; + +extern crate collections; +extern crate test; +extern crate unicode; + +#[cfg(test)] #[macro_use] mod bench; + +mod binary_heap; +mod bit; +mod btree; +mod enum_set; +mod fmt; +mod linked_list; +mod slice; +mod str; +mod string; +mod vec_deque; +mod vec_map; +mod vec; diff --git a/src/libcollectionstest/linked_list.rs b/src/libcollectionstest/linked_list.rs new file mode 100644 index 00000000000..fd73938095f --- /dev/null +++ b/src/libcollectionstest/linked_list.rs @@ -0,0 +1,397 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::LinkedList; +use std::hash::{SipHasher, self}; + +use test; + +#[test] +fn test_basic() { + let mut m = LinkedList::<Box<_>>::new(); + assert_eq!(m.pop_front(), None); + assert_eq!(m.pop_back(), None); + assert_eq!(m.pop_front(), None); + m.push_front(box 1); + assert_eq!(m.pop_front(), Some(box 1)); + m.push_back(box 2); + m.push_back(box 3); + assert_eq!(m.len(), 2); + assert_eq!(m.pop_front(), Some(box 2)); + assert_eq!(m.pop_front(), Some(box 3)); + assert_eq!(m.len(), 0); + assert_eq!(m.pop_front(), None); + m.push_back(box 1); + m.push_back(box 3); + m.push_back(box 5); + m.push_back(box 7); + assert_eq!(m.pop_front(), Some(box 1)); + + let mut n = LinkedList::new(); + n.push_front(2); + n.push_front(3); + { + assert_eq!(n.front().unwrap(), &3); + let x = n.front_mut().unwrap(); + assert_eq!(*x, 3); + *x = 0; + } + { + assert_eq!(n.back().unwrap(), &2); + let y = n.back_mut().unwrap(); + assert_eq!(*y, 2); + *y = 1; + } + assert_eq!(n.pop_front(), Some(0)); + assert_eq!(n.pop_front(), Some(1)); +} + +#[cfg(test)] +fn generate_test() -> LinkedList<i32> { + list_from(&[0,1,2,3,4,5,6]) +} + +#[cfg(test)] +fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { + v.iter().cloned().collect() +} + +#[test] +fn test_split_off() { + // singleton + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(0); + assert_eq!(m.len(), 0); + assert_eq!(p.len(), 1); + assert_eq!(p.back(), Some(&1)); + assert_eq!(p.front(), Some(&1)); + } + + // not singleton, forwards + { + let u = vec![1,2,3,4,5]; + let mut m = list_from(&u); + let mut n = m.split_off(2); + assert_eq!(m.len(), 2); + assert_eq!(n.len(), 3); + for elt in 1..3 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 3..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + // not singleton, backwards + { + let u = vec![1,2,3,4,5]; + let mut m = list_from(&u); + let mut n = m.split_off(4); + assert_eq!(m.len(), 4); + assert_eq!(n.len(), 1); + for elt in 1..5 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 5..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + + // no-op on the last index + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(1); + assert_eq!(m.len(), 1); + assert_eq!(p.len(), 0); + assert_eq!(m.back(), Some(&1)); + assert_eq!(m.front(), Some(&1)); + } + +} + +#[test] +fn test_iterator() { + let m = generate_test(); + for (i, elt) in m.iter().enumerate() { + assert_eq!(i as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iterator_clone() { + let mut n = LinkedList::new(); + n.push_back(2); + n.push_back(3); + n.push_back(4); + let mut it = n.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next_back(), jt.next_back()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_iterator_double_end() { + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next_back().unwrap(), &5); + assert_eq!(it.next_back(), None); + assert_eq!(it.next(), None); +} + +#[test] +fn test_rev_iter() { + let m = generate_test(); + for (i, elt) in m.iter().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().rev().next(), None); + n.push_front(4); + let mut it = n.iter().rev(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_mut_iter() { + let mut m = generate_test(); + let mut len = m.len(); + for (i, elt) in m.iter_mut().enumerate() { + assert_eq!(i as i32, *elt); + len -= 1; + } + assert_eq!(len, 0); + let mut n = LinkedList::new(); + assert!(n.iter_mut().next().is_none()); + n.push_front(4); + n.push_back(5); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (2, Some(2))); + assert!(it.next().is_some()); + assert!(it.next().is_some()); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_mut_double_end() { + let mut n = LinkedList::new(); + assert!(n.iter_mut().next_back().is_none()); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(*it.next().unwrap(), 6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(*it.next_back().unwrap(), 4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(*it.next_back().unwrap(), 5); + assert!(it.next_back().is_none()); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iter() { + let mut m = generate_test(); + for (i, elt) in m.iter_mut().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert!(n.iter_mut().rev().next().is_none()); + n.push_front(4); + let mut it = n.iter_mut().rev(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); +} + +#[test] +fn test_eq() { + let mut n = list_from(&[]); + let mut m = list_from(&[]); + assert!(n == m); + n.push_front(1); + assert!(n != m); + m.push_back(1); + assert!(n == m); + + let n = list_from(&[2,3,4]); + let m = list_from(&[1,2,3]); + assert!(n != m); +} + +#[test] +fn test_hash() { + let mut x = LinkedList::new(); + let mut y = LinkedList::new(); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); + + x.push_back(1); + x.push_back(2); + x.push_back(3); + + y.push_front(3); + y.push_front(2); + y.push_front(1); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +#[test] +fn test_ord() { + let n = list_from(&[]); + let m = list_from(&[1,2,3]); + assert!(n < m); + assert!(m > n); + assert!(n <= n); + assert!(n >= n); +} + +#[test] +fn test_ord_nan() { + let nan = 0.0f64/0.0; + let n = list_from(&[nan]); + let m = list_from(&[nan]); + assert!(!(n < m)); + assert!(!(n > m)); + assert!(!(n <= m)); + assert!(!(n >= m)); + + let n = list_from(&[nan]); + let one = list_from(&[1.0f64]); + assert!(!(n < one)); + assert!(!(n > one)); + assert!(!(n <= one)); + assert!(!(n >= one)); + + let u = list_from(&[1.0f64,2.0,nan]); + let v = list_from(&[1.0f64,2.0,3.0]); + assert!(!(u < v)); + assert!(!(u > v)); + assert!(!(u <= v)); + assert!(!(u >= v)); + + let s = list_from(&[1.0f64,2.0,4.0,2.0]); + let t = list_from(&[1.0f64,2.0,3.0,2.0]); + assert!(!(s < t)); + assert!(s > one); + assert!(!(s <= one)); + assert!(s >= one); +} + +#[test] +fn test_show() { + let list: LinkedList<_> = (0..10).collect(); + assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); + assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[bench] +fn bench_collect_into(b: &mut test::Bencher) { + let v = &[0; 64]; + b.iter(|| { + let _: LinkedList<_> = v.iter().cloned().collect(); + }) +} + +#[bench] +fn bench_push_front(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + }) +} + +#[bench] +fn bench_push_back(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + }) +} + +#[bench] +fn bench_push_back_pop_back(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + m.pop_back(); + }) +} + +#[bench] +fn bench_push_front_pop_front(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + m.pop_front(); + }) +} + +#[bench] +fn bench_iter(b: &mut test::Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().count() == 128); + }) +} +#[bench] +fn bench_iter_mut(b: &mut test::Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().count() == 128); + }) +} +#[bench] +fn bench_iter_rev(b: &mut test::Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().rev().count() == 128); + }) +} +#[bench] +fn bench_iter_mut_rev(b: &mut test::Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().rev().count() == 128); + }) +} diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs new file mode 100644 index 00000000000..0c3c82eea78 --- /dev/null +++ b/src/libcollectionstest/slice.rs @@ -0,0 +1,1571 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::default::Default; +use std::iter::RandomAccessIterator; +use std::mem; +use std::rand::{Rng, thread_rng}; +use std::rc::Rc; +use std::slice::ElementSwaps; + +fn square(n: usize) -> usize { n * n } + +fn is_odd(n: &usize) -> bool { *n % 2 == 1 } + +#[test] +fn test_from_fn() { + // Test on-stack from_fn. + let mut v: Vec<_> = (0..3).map(square).collect(); + { + let v = v; + assert_eq!(v.len(), 3); + assert_eq!(v[0], 0); + assert_eq!(v[1], 1); + assert_eq!(v[2], 4); + } + + // Test on-heap from_fn. + v = (0..5).map(square).collect(); + { + let v = v; + assert_eq!(v.len(), 5); + assert_eq!(v[0], 0); + assert_eq!(v[1], 1); + assert_eq!(v[2], 4); + assert_eq!(v[3], 9); + assert_eq!(v[4], 16); + } +} + +#[test] +fn test_from_elem() { + // Test on-stack from_elem. + let mut v = vec![10, 10]; + { + let v = v; + assert_eq!(v.len(), 2); + assert_eq!(v[0], 10); + assert_eq!(v[1], 10); + } + + // Test on-heap from_elem. + v = vec![20; 6]; + { + let v = v.as_slice(); + assert_eq!(v[0], 20); + assert_eq!(v[1], 20); + assert_eq!(v[2], 20); + assert_eq!(v[3], 20); + assert_eq!(v[4], 20); + assert_eq!(v[5], 20); + } +} + +#[test] +fn test_is_empty() { + let xs: [i32; 0] = []; + assert!(xs.is_empty()); + assert!(![0].is_empty()); +} + +#[test] +fn test_len_divzero() { + type Z = [i8; 0]; + let v0 : &[Z] = &[]; + let v1 : &[Z] = &[[]]; + let v2 : &[Z] = &[[], []]; + assert_eq!(mem::size_of::<Z>(), 0); + assert_eq!(v0.len(), 0); + assert_eq!(v1.len(), 1); + assert_eq!(v2.len(), 2); +} + +#[test] +fn test_get() { + let mut a = vec![11]; + assert_eq!(a.get(1), None); + a = vec![11, 12]; + assert_eq!(a.get(1).unwrap(), &12); + a = vec![11, 12, 13]; + assert_eq!(a.get(1).unwrap(), &12); +} + +#[test] +fn test_first() { + let mut a = vec![]; + assert_eq!(a.first(), None); + a = vec![11]; + assert_eq!(a.first().unwrap(), &11); + a = vec![11, 12]; + assert_eq!(a.first().unwrap(), &11); +} + +#[test] +fn test_first_mut() { + let mut a = vec![]; + assert_eq!(a.first_mut(), None); + a = vec![11]; + assert_eq!(*a.first_mut().unwrap(), 11); + a = vec![11, 12]; + assert_eq!(*a.first_mut().unwrap(), 11); +} + +#[test] +fn test_tail() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert_eq!(a.tail(), b); + a = vec![11, 12]; + let b: &[i32] = &[12]; + assert_eq!(a.tail(), b); +} + +#[test] +fn test_tail_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(a.tail_mut() == b); + a = vec![11, 12]; + let b: &mut [_] = &mut [12]; + assert!(a.tail_mut() == b); +} + +#[test] +#[should_panic] +fn test_tail_empty() { + let a = Vec::<i32>::new(); + a.tail(); +} + +#[test] +#[should_panic] +fn test_tail_mut_empty() { + let mut a = Vec::<i32>::new(); + a.tail_mut(); +} + +#[test] +fn test_init() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert_eq!(a.init(), b); + a = vec![11, 12]; + let b: &[_] = &[11]; + assert_eq!(a.init(), b); +} + +#[test] +fn test_init_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(a.init_mut() == b); + a = vec![11, 12]; + let b: &mut [_] = &mut [11]; + assert!(a.init_mut() == b); +} + +#[test] +#[should_panic] +fn test_init_empty() { + let a = Vec::<i32>::new(); + a.init(); +} + +#[test] +#[should_panic] +fn test_init_mut_empty() { + let mut a = Vec::<i32>::new(); + a.init_mut(); +} + +#[test] +fn test_last() { + let mut a = vec![]; + assert_eq!(a.last(), None); + a = vec![11]; + assert_eq!(a.last().unwrap(), &11); + a = vec![11, 12]; + assert_eq!(a.last().unwrap(), &12); +} + +#[test] +fn test_last_mut() { + let mut a = vec![]; + assert_eq!(a.last_mut(), None); + a = vec![11]; + assert_eq!(*a.last_mut().unwrap(), 11); + a = vec![11, 12]; + assert_eq!(*a.last_mut().unwrap(), 12); +} + +#[test] +fn test_slice() { + // Test fixed length vector. + let vec_fixed = [1, 2, 3, 4]; + let v_a = vec_fixed[1..vec_fixed.len()].to_vec(); + assert_eq!(v_a.len(), 3); + + assert_eq!(v_a[0], 2); + assert_eq!(v_a[1], 3); + assert_eq!(v_a[2], 4); + + // Test on stack. + let vec_stack: &[_] = &[1, 2, 3]; + let v_b = vec_stack[1..3].to_vec(); + assert_eq!(v_b.len(), 2); + + assert_eq!(v_b[0], 2); + assert_eq!(v_b[1], 3); + + // Test `Box<[T]>` + let vec_unique = vec![1, 2, 3, 4, 5, 6]; + let v_d = vec_unique[1..6].to_vec(); + assert_eq!(v_d.len(), 5); + + assert_eq!(v_d[0], 2); + assert_eq!(v_d[1], 3); + assert_eq!(v_d[2], 4); + assert_eq!(v_d[3], 5); + assert_eq!(v_d[4], 6); +} + +#[test] +fn test_slice_from() { + let vec: &[_] = &[1, 2, 3, 4]; + assert_eq!(&vec[..], vec); + let b: &[_] = &[3, 4]; + assert_eq!(&vec[2..], b); + let b: &[_] = &[]; + assert_eq!(&vec[4..], b); +} + +#[test] +fn test_slice_to() { + let vec: &[_] = &[1, 2, 3, 4]; + assert_eq!(&vec[..4], vec); + let b: &[_] = &[1, 2]; + assert_eq!(&vec[..2], b); + let b: &[_] = &[]; + assert_eq!(&vec[..0], b); +} + + +#[test] +fn test_pop() { + let mut v = vec![5]; + let e = v.pop(); + assert_eq!(v.len(), 0); + assert_eq!(e, Some(5)); + let f = v.pop(); + assert_eq!(f, None); + let g = v.pop(); + assert_eq!(g, None); +} + +#[test] +fn test_swap_remove() { + let mut v = vec![1, 2, 3, 4, 5]; + let mut e = v.swap_remove(0); + assert_eq!(e, 1); + assert_eq!(v, [5, 2, 3, 4]); + e = v.swap_remove(3); + assert_eq!(e, 4); + assert_eq!(v, [5, 2, 3]); +} + +#[test] +#[should_panic] +fn test_swap_remove_fail() { + let mut v = vec![1]; + let _ = v.swap_remove(0); + let _ = v.swap_remove(0); +} + +#[test] +fn test_swap_remove_noncopyable() { + // Tests that we don't accidentally run destructors twice. + let mut v: Vec<Box<_>> = Vec::new(); + v.push(box 0u8); + v.push(box 0u8); + v.push(box 0u8); + let mut _e = v.swap_remove(0); + assert_eq!(v.len(), 2); + _e = v.swap_remove(1); + assert_eq!(v.len(), 1); + _e = v.swap_remove(0); + assert_eq!(v.len(), 0); +} + +#[test] +fn test_push() { + // Test on-stack push(). + let mut v = vec![]; + v.push(1); + assert_eq!(v.len(), 1); + assert_eq!(v[0], 1); + + // Test on-heap push(). + v.push(2); + assert_eq!(v.len(), 2); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); +} + +#[test] +fn test_truncate() { + let mut v: Vec<Box<_>> = vec![box 6,box 5,box 4]; + v.truncate(1); + let v = v; + assert_eq!(v.len(), 1); + assert_eq!(*(v[0]), 6); + // If the unsafe block didn't drop things properly, we blow up here. +} + +#[test] +fn test_clear() { + let mut v: Vec<Box<_>> = vec![box 6,box 5,box 4]; + v.clear(); + assert_eq!(v.len(), 0); + // If the unsafe block didn't drop things properly, we blow up here. +} + +#[test] +fn test_dedup() { + fn case(a: Vec<i32>, b: Vec<i32>) { + let mut v = a; + v.dedup(); + assert_eq!(v, b); + } + case(vec![], vec![]); + case(vec![1], vec![1]); + case(vec![1,1], vec![1]); + case(vec![1,2,3], vec![1,2,3]); + case(vec![1,1,2,3], vec![1,2,3]); + case(vec![1,2,2,3], vec![1,2,3]); + case(vec![1,2,3,3], vec![1,2,3]); + case(vec![1,1,2,2,2,3,3], vec![1,2,3]); +} + +#[test] +fn test_dedup_unique() { + let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3]; + v0.dedup(); + let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3]; + v1.dedup(); + let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3]; + v2.dedup(); + /* + * If the boxed pointers were leaked or otherwise misused, valgrind + * and/or rt should raise errors. + */ +} + +#[test] +fn test_dedup_shared() { + let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3]; + v0.dedup(); + let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3]; + v1.dedup(); + let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3]; + v2.dedup(); + /* + * If the pointers were leaked or otherwise misused, valgrind and/or + * rt should raise errors. + */ +} + +#[test] +fn test_retain() { + let mut v = vec![1, 2, 3, 4, 5]; + v.retain(is_odd); + assert_eq!(v, [1, 3, 5]); +} + +#[test] +fn test_element_swaps() { + let mut v = [1, 2, 3]; + for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { + v.swap(a, b); + match i { + 0 => assert!(v == [1, 3, 2]), + 1 => assert!(v == [3, 1, 2]), + 2 => assert!(v == [3, 2, 1]), + 3 => assert!(v == [2, 3, 1]), + 4 => assert!(v == [2, 1, 3]), + 5 => assert!(v == [1, 2, 3]), + _ => panic!(), + } + } +} + +#[test] +fn test_lexicographic_permutations() { + let v : &mut[_] = &mut[1, 2, 3, 4, 5]; + assert!(v.prev_permutation() == false); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 3, 5, 4]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[1, 2, 3, 4, 5]; + assert!(v == b); + assert!(v.next_permutation()); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 4, 3, 5]; + assert!(v == b); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 4, 5, 3]; + assert!(v == b); + + let v : &mut[_] = &mut[1, 0, 0, 0]; + assert!(v.next_permutation() == false); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 1, 0, 0]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 0, 1, 0]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 0, 0, 1]; + assert!(v == b); + assert!(v.prev_permutation() == false); +} + +#[test] +fn test_lexicographic_permutations_empty_and_short() { + let empty : &mut[i32] = &mut[]; + assert!(empty.next_permutation() == false); + let b: &mut[i32] = &mut[]; + assert!(empty == b); + assert!(empty.prev_permutation() == false); + assert!(empty == b); + + let one_elem : &mut[_] = &mut[4]; + assert!(one_elem.prev_permutation() == false); + let b: &mut[_] = &mut[4]; + assert!(one_elem == b); + assert!(one_elem.next_permutation() == false); + assert!(one_elem == b); + + let two_elem : &mut[_] = &mut[1, 2]; + assert!(two_elem.prev_permutation() == false); + let b : &mut[_] = &mut[1, 2]; + let c : &mut[_] = &mut[2, 1]; + assert!(two_elem == b); + assert!(two_elem.next_permutation()); + assert!(two_elem == c); + assert!(two_elem.next_permutation() == false); + assert!(two_elem == c); + assert!(two_elem.prev_permutation()); + assert!(two_elem == b); + assert!(two_elem.prev_permutation() == false); + assert!(two_elem == b); +} + +#[test] +fn test_position_elem() { + assert!([].position_elem(&1).is_none()); + + let v1 = vec![1, 2, 3, 3, 2, 5]; + assert_eq!(v1.position_elem(&1), Some(0)); + assert_eq!(v1.position_elem(&2), Some(1)); + assert_eq!(v1.position_elem(&5), Some(5)); + assert!(v1.position_elem(&4).is_none()); +} + +#[test] +fn test_binary_search() { + assert_eq!([1,2,3,4,5].binary_search(&5).ok(), Some(4)); + assert_eq!([1,2,3,4,5].binary_search(&4).ok(), Some(3)); + assert_eq!([1,2,3,4,5].binary_search(&3).ok(), Some(2)); + assert_eq!([1,2,3,4,5].binary_search(&2).ok(), Some(1)); + assert_eq!([1,2,3,4,5].binary_search(&1).ok(), Some(0)); + + assert_eq!([2,4,6,8,10].binary_search(&1).ok(), None); + assert_eq!([2,4,6,8,10].binary_search(&5).ok(), None); + assert_eq!([2,4,6,8,10].binary_search(&4).ok(), Some(1)); + assert_eq!([2,4,6,8,10].binary_search(&10).ok(), Some(4)); + + assert_eq!([2,4,6,8].binary_search(&1).ok(), None); + assert_eq!([2,4,6,8].binary_search(&5).ok(), None); + assert_eq!([2,4,6,8].binary_search(&4).ok(), Some(1)); + assert_eq!([2,4,6,8].binary_search(&8).ok(), Some(3)); + + assert_eq!([2,4,6].binary_search(&1).ok(), None); + assert_eq!([2,4,6].binary_search(&5).ok(), None); + assert_eq!([2,4,6].binary_search(&4).ok(), Some(1)); + assert_eq!([2,4,6].binary_search(&6).ok(), Some(2)); + + assert_eq!([2,4].binary_search(&1).ok(), None); + assert_eq!([2,4].binary_search(&5).ok(), None); + assert_eq!([2,4].binary_search(&2).ok(), Some(0)); + assert_eq!([2,4].binary_search(&4).ok(), Some(1)); + + assert_eq!([2].binary_search(&1).ok(), None); + assert_eq!([2].binary_search(&5).ok(), None); + assert_eq!([2].binary_search(&2).ok(), Some(0)); + + assert_eq!([].binary_search(&1).ok(), None); + assert_eq!([].binary_search(&5).ok(), None); + + assert!([1,1,1,1,1].binary_search(&1).ok() != None); + assert!([1,1,1,1,2].binary_search(&1).ok() != None); + assert!([1,1,1,2,2].binary_search(&1).ok() != None); + assert!([1,1,2,2,2].binary_search(&1).ok() != None); + assert_eq!([1,2,2,2,2].binary_search(&1).ok(), Some(0)); + + assert_eq!([1,2,3,4,5].binary_search(&6).ok(), None); + assert_eq!([1,2,3,4,5].binary_search(&0).ok(), None); +} + +#[test] +fn test_reverse() { + let mut v = vec![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 mut v3 = Vec::<i32>::new(); + v3.reverse(); + assert!(v3.is_empty()); +} + +#[test] +fn test_sort() { + for len in 4..25 { + for _ in 0..100 { + let mut v: Vec<_> = thread_rng().gen_iter::<i32>().take(len).collect(); + let mut v1 = v.clone(); + + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + v1.sort_by(|a, b| a.cmp(b)); + assert!(v1.windows(2).all(|w| w[0] <= w[1])); + + v1.sort_by(|a, b| b.cmp(a)); + assert!(v1.windows(2).all(|w| w[0] >= w[1])); + } + } + + // shouldn't panic + let mut v: [i32; 0] = []; + v.sort(); + + let mut v = [0xDEADBEEFu64]; + v.sort(); + assert!(v == [0xDEADBEEF]); +} + +#[test] +fn test_sort_stability() { + for len in 4..25 { + for _ in 0..10 { + let mut counts = [0; 10]; + + // create a vector like [(6, 1), (5, 1), (6, 2), ...], + // where the first item of each tuple is random, but + // the second item represents which occurrence of that + // number this element is, i.e. the second elements + // will occur in sorted order. + let mut v: Vec<_> = (0..len).map(|_| { + let n = thread_rng().gen::<usize>() % 10; + counts[n] += 1; + (n, counts[n]) + }).collect(); + + // only sort on the first element, so an unstable sort + // may mix up the counts. + v.sort_by(|&(a,_), &(b,_)| a.cmp(&b)); + + // this comparison includes the count (the second item + // of the tuple), so elements with equal first items + // will need to be ordered with increasing + // counts... i.e. exactly asserting that this sort is + // stable. + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } + } +} + +#[test] +fn test_concat() { + let v: [Vec<i32>; 0] = []; + let c = v.concat(); + assert_eq!(c, []); + let d = [vec![1], vec![2, 3]].concat(); + assert_eq!(d, [1, 2, 3]); + + let v: &[&[_]] = &[&[1], &[2, 3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 3]); + let v: &[&[_]] = &[&[1], &[2], &[3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); +} + +#[test] +fn test_connect() { + let v: [Vec<i32>; 0] = []; + assert_eq!(v.connect(&0), []); + assert_eq!([vec![1], vec![2, 3]].connect(&0), [1, 0, 2, 3]); + assert_eq!([vec![1], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]); + + let v: [&[_]; 2] = [&[1], &[2, 3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 3]); + let v: [&[_]; 3] = [&[1], &[2], &[3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); +} + +#[test] +fn test_insert() { + let mut a = vec![1, 2, 4]; + a.insert(2, 3); + assert_eq!(a, [1, 2, 3, 4]); + + let mut a = vec![1, 2, 3]; + a.insert(0, 0); + assert_eq!(a, [0, 1, 2, 3]); + + let mut a = vec![1, 2, 3]; + a.insert(3, 4); + assert_eq!(a, [1, 2, 3, 4]); + + let mut a = vec![]; + a.insert(0, 1); + assert_eq!(a, [1]); +} + +#[test] +#[should_panic] +fn test_insert_oob() { + let mut a = vec![1, 2, 3]; + a.insert(4, 5); +} + +#[test] +fn test_remove() { + let mut a = vec![1, 2, 3, 4]; + + assert_eq!(a.remove(2), 3); + assert_eq!(a, [1, 2, 4]); + + assert_eq!(a.remove(2), 4); + assert_eq!(a, [1, 2]); + + assert_eq!(a.remove(0), 1); + assert_eq!(a, [2]); + + assert_eq!(a.remove(0), 2); + assert_eq!(a, []); +} + +#[test] +#[should_panic] +fn test_remove_fail() { + let mut a = vec![1]; + let _ = a.remove(0); + let _ = a.remove(0); +} + +#[test] +fn test_capacity() { + let mut v = vec![0]; + v.reserve_exact(10); + assert!(v.capacity() >= 11); +} + +#[test] +fn test_slice_2() { + let v = vec![1, 2, 3, 4, 5]; + let v = v.slice(1, 3); + assert_eq!(v.len(), 2); + assert_eq!(v[0], 2); + assert_eq!(v[1], 3); +} + +#[test] +#[should_panic] +fn test_permute_fail() { + let v: [(Box<_>, Rc<_>); 4] = + [(box 0, Rc::new(0)), (box 0, Rc::new(0)), + (box 0, Rc::new(0)), (box 0, Rc::new(0))]; + let mut i = 0; + for _ in v.permutations() { + if i == 2 { + panic!() + } + i += 1; + } +} + +#[test] +fn test_total_ord() { + let c = &[1, 2, 3]; + [1, 2, 3, 4][..].cmp(c) == Greater; + let c = &[1, 2, 3, 4]; + [1, 2, 3][..].cmp(c) == Less; + let c = &[1, 2, 3, 6]; + [1, 2, 3, 4][..].cmp(c) == Equal; + let c = &[1, 2, 3, 4, 5, 6]; + [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less; + let c = &[1, 2, 3, 4]; + [2, 2][..].cmp(c) == Greater; +} + +#[test] +fn test_iterator() { + let xs = [1, 2, 5, 10, 11]; + let mut it = xs.iter(); + assert_eq!(it.size_hint(), (5, Some(5))); + assert_eq!(it.next().unwrap(), &1); + assert_eq!(it.size_hint(), (4, Some(4))); + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next().unwrap(), &10); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &11); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_random_access_iterator() { + let xs = [1, 2, 5, 10, 11]; + let mut it = xs.iter(); + + assert_eq!(it.indexable(), 5); + assert_eq!(it.idx(0).unwrap(), &1); + assert_eq!(it.idx(2).unwrap(), &5); + assert_eq!(it.idx(4).unwrap(), &11); + assert!(it.idx(5).is_none()); + + assert_eq!(it.next().unwrap(), &1); + assert_eq!(it.indexable(), 4); + assert_eq!(it.idx(0).unwrap(), &2); + assert_eq!(it.idx(3).unwrap(), &11); + assert!(it.idx(4).is_none()); + + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.indexable(), 3); + assert_eq!(it.idx(1).unwrap(), &10); + assert!(it.idx(3).is_none()); + + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.indexable(), 2); + assert_eq!(it.idx(1).unwrap(), &11); + + assert_eq!(it.next().unwrap(), &10); + assert_eq!(it.indexable(), 1); + assert_eq!(it.idx(0).unwrap(), &11); + assert!(it.idx(1).is_none()); + + assert_eq!(it.next().unwrap(), &11); + assert_eq!(it.indexable(), 0); + assert!(it.idx(0).is_none()); + + assert!(it.next().is_none()); +} + +#[test] +fn test_iter_size_hints() { + let mut xs = [1, 2, 5, 10, 11]; + assert_eq!(xs.iter().size_hint(), (5, Some(5))); + assert_eq!(xs.iter_mut().size_hint(), (5, Some(5))); +} + +#[test] +fn test_iter_clone() { + let xs = [1, 2, 5]; + let mut it = xs.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_mut_iterator() { + let mut xs = [1, 2, 3, 4, 5]; + for x in &mut xs { + *x += 1; + } + assert!(xs == [2, 3, 4, 5, 6]) +} + +#[test] +fn test_rev_iterator() { + + let xs = [1, 2, 5, 10, 11]; + let ys = [11, 10, 5, 2, 1]; + let mut i = 0; + for &x in xs.iter().rev() { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, 5); +} + +#[test] +fn test_mut_rev_iterator() { + let mut xs = [1, 2, 3, 4, 5]; + for (i,x) in xs.iter_mut().rev().enumerate() { + *x += i; + } + assert!(xs == [5, 5, 5, 5, 5]) +} + +#[test] +fn test_move_iterator() { + let xs = vec![1,2,3,4,5]; + assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10*a + b), 12345); +} + +#[test] +fn test_move_rev_iterator() { + let xs = vec![1,2,3,4,5]; + assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10*a + b), 54321); +} + +#[test] +fn test_splitator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1], &[3], &[5]]; + assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[], &[2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 1).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4], &[]]; + assert_eq!(xs.split(|x| *x == 5).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 10).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; + assert_eq!(xs.split(|_| true).collect::<Vec<&[i32]>>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[i32]>>(), splits); +} + +#[test] +fn test_splitnator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[1], &[3,4,5]]; + assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[4,5]]; + assert_eq!(xs.splitn(3, |_| true).collect::<Vec<_>>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.splitn(1, |x| *x == 5).collect::<Vec<_>>(), splits); +} + +#[test] +fn test_splitnator_mut() { + let xs = &mut [1,2,3,4,5]; + + let splits: &[&mut[_]] = &[&mut [1,2,3,4,5]]; + assert_eq!(xs.splitn_mut(0, |x| *x % 2 == 0).collect::<Vec<_>>(), + splits); + let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]]; + assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(), + splits); + let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]]; + assert_eq!(xs.splitn_mut(3, |_| true).collect::<Vec<_>>(), + splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&mut[i32]] = &[&mut []]; + assert_eq!(xs.splitn_mut(1, |x| *x == 5).collect::<Vec<_>>(), + splits); +} + +#[test] +fn test_rsplitator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[5], &[3], &[1]]; + assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[2,3,4,5], &[]]; + assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[], &[1,2,3,4]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<_>>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[i32]>>(), splits); +} + +#[test] +fn test_rsplitnator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[5], &[1,2,3]]; + assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[1,2]]; + assert_eq!(xs.rsplitn(3, |_| true).collect::<Vec<_>>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<Vec<&[i32]>>(), splits); +} + +#[test] +fn test_windowsator() { + let v = &[1,2,3,4]; + + let wins: &[&[_]] = &[&[1,2], &[2,3], &[3,4]]; + assert_eq!(v.windows(2).collect::<Vec<_>>(), wins); + + let wins: &[&[_]] = &[&[1,2,3], &[2,3,4]]; + assert_eq!(v.windows(3).collect::<Vec<_>>(), wins); + assert!(v.windows(6).next().is_none()); + + let wins: &[&[_]] = &[&[3,4], &[2,3], &[1,2]]; + assert_eq!(v.windows(2).rev().collect::<Vec<&[_]>>(), wins); + let mut it = v.windows(2); + assert_eq!(it.indexable(), 3); + let win: &[_] = &[1,2]; + assert_eq!(it.idx(0).unwrap(), win); + let win: &[_] = &[2,3]; + assert_eq!(it.idx(1).unwrap(), win); + let win: &[_] = &[3,4]; + assert_eq!(it.idx(2).unwrap(), win); + assert_eq!(it.idx(3), None); +} + +#[test] +#[should_panic] +fn test_windowsator_0() { + let v = &[1,2,3,4]; + let _it = v.windows(0); +} + +#[test] +fn test_chunksator() { + let v = &[1,2,3,4,5]; + + assert_eq!(v.chunks(2).len(), 3); + + let chunks: &[&[_]] = &[&[1,2], &[3,4], &[5]]; + assert_eq!(v.chunks(2).collect::<Vec<_>>(), chunks); + let chunks: &[&[_]] = &[&[1,2,3], &[4,5]]; + assert_eq!(v.chunks(3).collect::<Vec<_>>(), chunks); + let chunks: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(v.chunks(6).collect::<Vec<_>>(), chunks); + + let chunks: &[&[_]] = &[&[5], &[3,4], &[1,2]]; + assert_eq!(v.chunks(2).rev().collect::<Vec<_>>(), chunks); + let mut it = v.chunks(2); + assert_eq!(it.indexable(), 3); + + let chunk: &[_] = &[1,2]; + assert_eq!(it.idx(0).unwrap(), chunk); + let chunk: &[_] = &[3,4]; + assert_eq!(it.idx(1).unwrap(), chunk); + let chunk: &[_] = &[5]; + assert_eq!(it.idx(2).unwrap(), chunk); + assert_eq!(it.idx(3), None); +} + +#[test] +#[should_panic] +fn test_chunksator_0() { + let v = &[1,2,3,4]; + let _it = v.chunks(0); +} + +#[test] +fn test_move_from() { + let mut a = [1,2,3,4,5]; + let b = vec![6,7,8]; + assert_eq!(a.move_from(b, 0, 3), 3); + assert!(a == [6,7,8,4,5]); + let mut a = [7,2,8,1]; + let b = vec![3,1,4,1,5,9]; + assert_eq!(a.move_from(b, 0, 6), 4); + assert!(a == [3,1,4,1]); + let mut a = [1,2,3,4]; + let b = vec![5,6,7,8,9,0]; + assert_eq!(a.move_from(b, 2, 3), 1); + assert!(a == [7,2,3,4]); + let mut a = [1,2,3,4,5]; + let b = vec![5,6,7,8,9,0]; + assert_eq!(a[2..4].move_from(b,1,6), 2); + assert!(a == [1,2,6,7,5]); +} + +#[test] +fn test_reverse_part() { + let mut values = [1,2,3,4,5]; + values[1..4].reverse(); + assert!(values == [1,4,3,2,5]); +} + +#[test] +fn test_show() { + macro_rules! test_show_vec { + ($x:expr, $x_str:expr) => ({ + let (x, x_str) = ($x, $x_str); + assert_eq!(format!("{:?}", x), x_str); + assert_eq!(format!("{:?}", x), x_str); + }) + } + let empty = Vec::<i32>::new(); + test_show_vec!(empty, "[]"); + test_show_vec!(vec![1], "[1]"); + test_show_vec!(vec![1, 2, 3], "[1, 2, 3]"); + test_show_vec!(vec![vec![], vec![1], vec![1, 1]], + "[[], [1], [1, 1]]"); + + let empty_mut: &mut [i32] = &mut[]; + test_show_vec!(empty_mut, "[]"); + let v = &mut[1]; + test_show_vec!(v, "[1]"); + let v = &mut[1, 2, 3]; + test_show_vec!(v, "[1, 2, 3]"); + let v: &mut[&mut[_]] = &mut[&mut[], &mut[1], &mut[1, 1]]; + test_show_vec!(v, "[[], [1], [1, 1]]"); +} + +#[test] +fn test_vec_default() { + macro_rules! t { + ($ty:ty) => {{ + let v: $ty = Default::default(); + assert!(v.is_empty()); + }} + } + + t!(&[i32]); + t!(Vec<i32>); +} + +#[test] +fn test_bytes_set_memory() { + use std::slice::bytes::MutableByteVector; + + let mut values = [1,2,3,4,5]; + values[0..5].set_memory(0xAB); + assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); + values[2..4].set_memory(0xFF); + assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); +} + +#[test] +#[should_panic] +fn test_overflow_does_not_cause_segfault() { + let mut v = vec![]; + v.reserve_exact(-1); + v.push(1); + v.push(2); +} + +#[test] +#[should_panic] +fn test_overflow_does_not_cause_segfault_managed() { + let mut v = vec![Rc::new(1)]; + v.reserve_exact(-1); + v.push(Rc::new(2)); +} + +#[test] +fn test_mut_split_at() { + let mut values = [1u8,2,3,4,5]; + { + let (left, right) = values.split_at_mut(2); + { + let left: &[_] = left; + assert!(left[..left.len()] == [1, 2]); + } + for p in left { + *p += 1; + } + + { + let right: &[_] = right; + assert!(right[..right.len()] == [3, 4, 5]); + } + for p in right { + *p += 2; + } + } + + assert!(values == [2, 3, 5, 6, 7]); +} + +#[derive(Clone, PartialEq)] +struct Foo; + +#[test] +fn test_iter_zero_sized() { + let mut v = vec![Foo, Foo, Foo]; + assert_eq!(v.len(), 3); + let mut cnt = 0; + + for f in &v { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 3); + + for f in &v[1..3] { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 5); + + for f in &mut v { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 8); + + for f in v { + assert!(f == Foo); + cnt += 1; + } + assert_eq!(cnt, 11); + + let xs: [Foo; 3] = [Foo, Foo, Foo]; + cnt = 0; + for f in &xs { + assert!(*f == Foo); + cnt += 1; + } + assert!(cnt == 3); +} + +#[test] +fn test_shrink_to_fit() { + let mut xs = vec![0, 1, 2, 3]; + for i in 4..100 { + xs.push(i) + } + assert_eq!(xs.capacity(), 128); + xs.shrink_to_fit(); + assert_eq!(xs.capacity(), 100); + assert_eq!(xs, (0..100).collect::<Vec<_>>()); +} + +#[test] +fn test_starts_with() { + assert!(b"foobar".starts_with(b"foo")); + assert!(!b"foobar".starts_with(b"oob")); + assert!(!b"foobar".starts_with(b"bar")); + assert!(!b"foo".starts_with(b"foobar")); + assert!(!b"bar".starts_with(b"foobar")); + assert!(b"foobar".starts_with(b"foobar")); + let empty: &[u8] = &[]; + assert!(empty.starts_with(empty)); + assert!(!empty.starts_with(b"foo")); + assert!(b"foobar".starts_with(empty)); +} + +#[test] +fn test_ends_with() { + assert!(b"foobar".ends_with(b"bar")); + assert!(!b"foobar".ends_with(b"oba")); + assert!(!b"foobar".ends_with(b"foo")); + assert!(!b"foo".ends_with(b"foobar")); + assert!(!b"bar".ends_with(b"foobar")); + assert!(b"foobar".ends_with(b"foobar")); + let empty: &[u8] = &[]; + assert!(empty.ends_with(empty)); + assert!(!empty.ends_with(b"foo")); + assert!(b"foobar".ends_with(empty)); +} + +#[test] +fn test_mut_splitator() { + let mut xs = [0,1,0,2,3,0,0,4,5,0]; + assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); + for slice in xs.split_mut(|x| *x == 0) { + slice.reverse(); + } + assert!(xs == [0,1,0,3,2,0,0,5,4,0]); + + let mut xs = [0,1,0,2,3,0,0,4,5,0,6,7]; + for slice in xs.split_mut(|x| *x == 0).take(5) { + slice.reverse(); + } + assert!(xs == [0,1,0,3,2,0,0,5,4,0,6,7]); +} + +#[test] +fn test_mut_splitator_rev() { + let mut xs = [1,2,0,3,4,0,0,5,6,0]; + for slice in xs.split_mut(|x| *x == 0).rev().take(4) { + slice.reverse(); + } + assert!(xs == [1,2,0,4,3,0,0,6,5,0]); +} + +#[test] +fn test_get_mut() { + let mut v = [0,1,2]; + assert_eq!(v.get_mut(3), None); + v.get_mut(1).map(|e| *e = 7); + assert_eq!(v[1], 7); + let mut x = 2; + assert_eq!(v.get_mut(2), Some(&mut x)); +} + +#[test] +fn test_mut_chunks() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + assert_eq!(v.chunks_mut(2).len(), 4); + for (i, chunk) in v.chunks_mut(3).enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [0, 0, 0, 1, 1, 1, 2]; + assert!(v == result); +} + +#[test] +fn test_mut_chunks_rev() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + for (i, chunk) in v.chunks_mut(3).rev().enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [2, 2, 2, 1, 1, 1, 0]; + assert!(v == result); +} + +#[test] +#[should_panic] +fn test_mut_chunks_0() { + let mut v = [1, 2, 3, 4]; + let _it = v.chunks_mut(0); +} + +#[test] +fn test_mut_last() { + let mut x = [1, 2, 3, 4, 5]; + let h = x.last_mut(); + assert_eq!(*h.unwrap(), 5); + + let y: &mut [i32] = &mut []; + assert!(y.last_mut().is_none()); +} + +#[test] +fn test_to_vec() { + let xs: Box<_> = box [1, 2, 3]; + let ys = xs.to_vec(); + assert_eq!(ys, [1, 2, 3]); +} + +mod bench { + use std::iter::repeat; + use std::{mem, ptr}; + use std::rand::{Rng, weak_rng}; + + use test::{Bencher, black_box}; + + #[bench] + fn iterator(b: &mut Bencher) { + // peculiar numbers to stop LLVM from optimising the summation + // out. + let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); + + b.iter(|| { + let mut sum = 0; + for x in &v { + sum += *x; + } + // sum == 11806, to stop dead code elimination. + if sum == 0 {panic!()} + }) + } + + #[bench] + fn mut_iterator(b: &mut Bencher) { + let mut v: Vec<_> = repeat(0).take(100).collect(); + + b.iter(|| { + let mut i = 0; + for x in &mut v { + *x = i; + i += 1; + } + }) + } + + #[bench] + fn concat(b: &mut Bencher) { + let xss: Vec<Vec<i32>> = + (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| { + xss.concat(); + }); + } + + #[bench] + fn connect(b: &mut Bencher) { + let xss: Vec<Vec<i32>> = + (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| { + xss.connect(&0) + }); + } + + #[bench] + fn push(b: &mut Bencher) { + let mut vec = Vec::<i32>::new(); + b.iter(|| { + vec.push(0); + black_box(&vec); + }); + } + + #[bench] + fn starts_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.starts_with(&vec) + }) + } + + #[bench] + fn starts_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| { + vec.starts_with(&vec) + }) + } + + #[bench] + fn starts_with_diff_one_element_at_end(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..99).collect(); + match_vec.push(0); + b.iter(|| { + vec.starts_with(&match_vec) + }) + } + + #[bench] + fn ends_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.ends_with(&vec) + }) + } + + #[bench] + fn ends_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| { + vec.ends_with(&vec) + }) + } + + #[bench] + fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..100).collect(); + match_vec[0] = 200; + b.iter(|| { + vec.starts_with(&match_vec) + }) + } + + #[bench] + fn contains_last_element(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.contains(&99) + }) + } + + #[bench] + fn zero_1kb_from_elem(b: &mut Bencher) { + b.iter(|| { + repeat(0u8).take(1024).collect::<Vec<_>>() + }); + } + + #[bench] + fn zero_1kb_set_memory(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::<u8>::with_capacity(1024); + unsafe { + let vp = v.as_mut_ptr(); + ptr::set_memory(vp, 0, 1024); + v.set_len(1024); + } + v + }); + } + + #[bench] + fn zero_1kb_loop_set(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::<u8>::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for i in 0..1024 { + v[i] = 0; + } + }); + } + + #[bench] + fn zero_1kb_mut_iter(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::<u8>::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for x in &mut v { + *x = 0; + } + v + }); + } + + #[bench] + fn random_inserts(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = repeat((0, 0)).take(30).collect(); + for _ in 0..100 { + let l = v.len(); + v.insert(rng.gen::<usize>() % (l + 1), + (1, 1)); + } + }) + } + #[bench] + fn random_removes(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = repeat((0, 0)).take(130).collect(); + for _ in 0..100 { + let l = v.len(); + v.remove(rng.gen::<usize>() % l); + } + }) + } + + #[bench] + fn sort_random_small(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::<u64>().take(5).collect(); + v.sort(); + }); + b.bytes = 5 * mem::size_of::<u64>() as u64; + } + + #[bench] + fn sort_random_medium(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::<u64>().take(100).collect(); + v.sort(); + }); + b.bytes = 100 * mem::size_of::<u64>() as u64; + } + + #[bench] + fn sort_random_large(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::<u64>().take(10000).collect(); + v.sort(); + }); + b.bytes = 10000 * mem::size_of::<u64>() as u64; + } + + #[bench] + fn sort_sorted(b: &mut Bencher) { + let mut v: Vec<_> = (0..10000).collect(); + b.iter(|| { + v.sort(); + }); + b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; + } + + type BigSortable = (u64, u64, u64, u64); + + #[bench] + fn sort_big_random_small(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::<BigSortable>().take(5) + .collect::<Vec<BigSortable>>(); + v.sort(); + }); + b.bytes = 5 * mem::size_of::<BigSortable>() as u64; + } + + #[bench] + fn sort_big_random_medium(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::<BigSortable>().take(100) + .collect::<Vec<BigSortable>>(); + v.sort(); + }); + b.bytes = 100 * mem::size_of::<BigSortable>() as u64; + } + + #[bench] + fn sort_big_random_large(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::<BigSortable>().take(10000) + .collect::<Vec<BigSortable>>(); + v.sort(); + }); + b.bytes = 10000 * mem::size_of::<BigSortable>() as u64; + } + + #[bench] + fn sort_big_sorted(b: &mut Bencher) { + let mut v: Vec<BigSortable> = (0..10000).map(|i| (i, i, i, i)).collect(); + b.iter(|| { + v.sort(); + }); + b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; + } +} diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs new file mode 100644 index 00000000000..79c2d719862 --- /dev/null +++ b/src/libcollectionstest/str.rs @@ -0,0 +1,1668 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::iter::AdditiveIterator; +use std::str::{Utf8Error, from_utf8}; + +#[test] +fn test_le() { + assert!("" <= ""); + assert!("" <= "foo"); + assert!("foo" <= "foo"); + assert!("foo" != "bar"); +} + +#[test] +fn test_len() { + assert_eq!("".len(), 0); + assert_eq!("hello world".len(), 11); + assert_eq!("\x63".len(), 1); + assert_eq!("\u{a2}".len(), 2); + assert_eq!("\u{3c0}".len(), 2); + assert_eq!("\u{2620}".len(), 3); + assert_eq!("\u{1d11e}".len(), 4); + + assert_eq!("".chars().count(), 0); + assert_eq!("hello world".chars().count(), 11); + assert_eq!("\x63".chars().count(), 1); + assert_eq!("\u{a2}".chars().count(), 1); + assert_eq!("\u{3c0}".chars().count(), 1); + assert_eq!("\u{2620}".chars().count(), 1); + assert_eq!("\u{1d11e}".chars().count(), 1); + assert_eq!("ประเทศไทย中华Việt Nam".chars().count(), 19); + + assert_eq!("hello".width(false), 10); + assert_eq!("hello".width(true), 10); + assert_eq!("\0\0\0\0\0".width(false), 0); + assert_eq!("\0\0\0\0\0".width(true), 0); + assert_eq!("".width(false), 0); + assert_eq!("".width(true), 0); + assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(false), 4); + assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(true), 8); +} + +#[test] +fn test_find() { + assert_eq!("hello".find('l'), Some(2)); + assert_eq!("hello".find(|c:char| c == 'o'), Some(4)); + assert!("hello".find('x').is_none()); + assert!("hello".find(|c:char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30)); + assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30)); +} + +#[test] +fn test_rfind() { + assert_eq!("hello".rfind('l'), Some(3)); + assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4)); + assert!("hello".rfind('x').is_none()); + assert!("hello".rfind(|c:char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30)); + assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30)); +} + +#[test] +fn test_collect() { + let empty = String::from_str(""); + let s: String = empty.chars().collect(); + assert_eq!(empty, s); + let data = String::from_str("ประเทศไทย中"); + let s: String = data.chars().collect(); + assert_eq!(data, s); +} + +#[test] +fn test_into_bytes() { + let data = String::from_str("asdf"); + let buf = data.into_bytes(); + assert_eq!(b"asdf", buf); +} + +#[test] +fn test_find_str() { + // byte positions + assert_eq!("".find_str(""), Some(0)); + assert!("banana".find_str("apple pie").is_none()); + + let data = "abcabc"; + assert_eq!(data[0..6].find_str("ab"), Some(0)); + assert_eq!(data[2..6].find_str("ab"), Some(3 - 2)); + assert!(data[2..4].find_str("ab").is_none()); + + let string = "ประเทศไทย中华Việt Nam"; + let mut data = String::from_str(string); + data.push_str(string); + assert!(data.find_str("ไท华").is_none()); + assert_eq!(data[0..43].find_str(""), Some(0)); + assert_eq!(data[6..43].find_str(""), Some(6 - 6)); + + assert_eq!(data[0..43].find_str("ประ"), Some( 0)); + assert_eq!(data[0..43].find_str("ทศไ"), Some(12)); + assert_eq!(data[0..43].find_str("ย中"), Some(24)); + assert_eq!(data[0..43].find_str("iệt"), Some(34)); + assert_eq!(data[0..43].find_str("Nam"), Some(40)); + + assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43)); + assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43)); + assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43)); + assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43)); + assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43)); +} + +#[test] +fn test_slice_chars() { + fn t(a: &str, b: &str, start: usize) { + assert_eq!(a.slice_chars(start, start + b.chars().count()), b); + } + t("", "", 0); + t("hello", "llo", 2); + t("hello", "el", 1); + t("αβλ", "β", 1); + t("αβλ", "", 3); + assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8)); +} + +fn s(x: &str) -> String { x.to_string() } + +macro_rules! test_concat { + ($expected: expr, $string: expr) => { + { + let s: String = $string.concat(); + assert_eq!($expected, s); + } + } +} + +#[test] +fn test_concat_for_different_types() { + test_concat!("ab", vec![s("a"), s("b")]); + test_concat!("ab", vec!["a", "b"]); + test_concat!("ab", vec!["a", "b"]); + test_concat!("ab", vec![s("a"), s("b")]); +} + +#[test] +fn test_concat_for_different_lengths() { + let empty: &[&str] = &[]; + test_concat!("", empty); + test_concat!("a", ["a"]); + test_concat!("ab", ["a", "b"]); + test_concat!("abc", ["", "a", "bc"]); +} + +macro_rules! test_connect { + ($expected: expr, $string: expr, $delim: expr) => { + { + let s = $string.connect($delim); + assert_eq!($expected, s); + } + } +} + +#[test] +fn test_connect_for_different_types() { + test_connect!("a-b", ["a", "b"], "-"); + let hyphen = "-".to_string(); + test_connect!("a-b", [s("a"), s("b")], &*hyphen); + test_connect!("a-b", vec!["a", "b"], &*hyphen); + test_connect!("a-b", &*vec!["a", "b"], "-"); + test_connect!("a-b", vec![s("a"), s("b")], "-"); +} + +#[test] +fn test_connect_for_different_lengths() { + let empty: &[&str] = &[]; + test_connect!("", empty, "-"); + test_connect!("a", ["a"], "-"); + test_connect!("a-b", ["a", "b"], "-"); + test_connect!("-a-bc", ["", "a", "bc"], "-"); +} + +#[test] +fn test_unsafe_slice() { + assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)}); + assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)}); + assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)}); + fn a_million_letter_a() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("aaaaaaaaaa"); + i += 1; + } + rs + } + fn half_a_million_letter_a() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("aaaaa"); + i += 1; + } + rs + } + let letters = a_million_letter_a(); + assert!(half_a_million_letter_a() == + unsafe {String::from_str(letters.slice_unchecked( + 0, + 500000))}); +} + +#[test] +fn test_starts_with() { + assert!(("".starts_with(""))); + assert!(("abc".starts_with(""))); + assert!(("abc".starts_with("a"))); + assert!((!"a".starts_with("abc"))); + assert!((!"".starts_with("abc"))); + assert!((!"ödd".starts_with("-"))); + assert!(("ödd".starts_with("öd"))); +} + +#[test] +fn test_ends_with() { + assert!(("".ends_with(""))); + assert!(("abc".ends_with(""))); + assert!(("abc".ends_with("c"))); + assert!((!"a".ends_with("abc"))); + assert!((!"".ends_with("abc"))); + assert!((!"ddö".ends_with("-"))); + assert!(("ddö".ends_with("dö"))); +} + +#[test] +fn test_is_empty() { + assert!("".is_empty()); + assert!(!"a".is_empty()); +} + +#[test] +fn test_replace() { + let a = "a"; + assert_eq!("".replace(a, "b"), String::from_str("")); + assert_eq!("a".replace(a, "b"), String::from_str("b")); + assert_eq!("ab".replace(a, "b"), String::from_str("bb")); + let test = "test"; + assert!(" test test ".replace(test, "toast") == + String::from_str(" toast toast ")); + assert_eq!(" test test ".replace(test, ""), String::from_str(" ")); +} + +#[test] +fn test_replace_2a() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let a = "ประเ"; + let a2 = "دولة الكويتทศไทย中华"; + assert_eq!(data.replace(a, repl), a2); +} + +#[test] +fn test_replace_2b() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let b = "ะเ"; + let b2 = "ปรدولة الكويتทศไทย中华"; + assert_eq!(data.replace(b, repl), b2); +} + +#[test] +fn test_replace_2c() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let c = "中华"; + let c2 = "ประเทศไทยدولة الكويت"; + assert_eq!(data.replace(c, repl), c2); +} + +#[test] +fn test_replace_2d() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let d = "ไท华"; + assert_eq!(data.replace(d, repl), data); +} + +#[test] +fn test_slice() { + assert_eq!("ab", "abc".slice(0, 2)); + assert_eq!("bc", "abc".slice(1, 3)); + assert_eq!("", "abc".slice(1, 1)); + assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3)); + + let data = "ประเทศไทย中华"; + assert_eq!("ป", data.slice(0, 3)); + assert_eq!("ร", data.slice(3, 6)); + assert_eq!("", data.slice(3, 3)); + assert_eq!("华", data.slice(30, 33)); + + fn a_million_letter_x() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("华华华华华华华华华华"); + i += 1; + } + rs + } + fn half_a_million_letter_x() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("华华华华华"); + i += 1; + } + rs + } + let letters = a_million_letter_x(); + assert!(half_a_million_letter_x() == + String::from_str(letters.slice(0, 3 * 500000))); +} + +#[test] +fn test_slice_2() { + let ss = "中华Việt Nam"; + + assert_eq!("华", ss.slice(3, 6)); + assert_eq!("Việt Nam", ss.slice(6, 16)); + + assert_eq!("ab", "abc".slice(0, 2)); + assert_eq!("bc", "abc".slice(1, 3)); + assert_eq!("", "abc".slice(1, 1)); + + assert_eq!("中", ss.slice(0, 3)); + assert_eq!("华V", ss.slice(3, 7)); + assert_eq!("", ss.slice(3, 3)); + /*0: 中 + 3: 华 + 6: V + 7: i + 8: ệ + 11: t + 12: + 13: N + 14: a + 15: m */ +} + +#[test] +#[should_panic] +fn test_slice_fail() { + "中华Việt Nam".slice(0, 2); +} + +#[test] +fn test_slice_from() { + assert_eq!("abcd".slice_from(0), "abcd"); + assert_eq!("abcd".slice_from(2), "cd"); + assert_eq!("abcd".slice_from(4), ""); +} +#[test] +fn test_slice_to() { + assert_eq!("abcd".slice_to(0), ""); + assert_eq!("abcd".slice_to(2), "ab"); + assert_eq!("abcd".slice_to(4), "abcd"); +} + +#[test] +fn test_trim_left_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** "); + assert_eq!(" *** *** ".trim_left_matches(chars), ""); + assert_eq!("foo *** ".trim_left_matches(chars), "foo *** "); + + assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12"); + assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); +} + +#[test] +fn test_trim_right_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo"); + assert_eq!(" *** *** ".trim_right_matches(chars), ""); + assert_eq!(" *** foo".trim_right_matches(chars), " *** foo"); + + assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar"); + assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); +} + +#[test] +fn test_trim_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_matches(chars), "foo"); + assert_eq!(" *** *** ".trim_matches(chars), ""); + assert_eq!("foo".trim_matches(chars), "foo"); + + assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar"); + assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); +} + +#[test] +fn test_trim_left() { + assert_eq!("".trim_left(), ""); + assert_eq!("a".trim_left(), "a"); + assert_eq!(" ".trim_left(), ""); + assert_eq!(" blah".trim_left(), "blah"); + assert_eq!(" \u{3000} wut".trim_left(), "wut"); + assert_eq!("hey ".trim_left(), "hey "); +} + +#[test] +fn test_trim_right() { + assert_eq!("".trim_right(), ""); + assert_eq!("a".trim_right(), "a"); + assert_eq!(" ".trim_right(), ""); + assert_eq!("blah ".trim_right(), "blah"); + assert_eq!("wut \u{3000} ".trim_right(), "wut"); + assert_eq!(" hey".trim_right(), " hey"); +} + +#[test] +fn test_trim() { + assert_eq!("".trim(), ""); + assert_eq!("a".trim(), "a"); + assert_eq!(" ".trim(), ""); + assert_eq!(" blah ".trim(), "blah"); + assert_eq!("\nwut \u{3000} ".trim(), "wut"); + assert_eq!(" hey dude ".trim(), "hey dude"); +} + +#[test] +fn test_is_whitespace() { + assert!("".chars().all(|c| c.is_whitespace())); + assert!(" ".chars().all(|c| c.is_whitespace())); + assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space + assert!(" \n\t ".chars().all(|c| c.is_whitespace())); + assert!(!" _ ".chars().all(|c| c.is_whitespace())); +} + +#[test] +fn test_slice_shift_char() { + let data = "ประเทศไทย中"; + assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中"))); +} + +#[test] +fn test_slice_shift_char_2() { + let empty = ""; + assert_eq!(empty.slice_shift_char(), None); +} + +#[test] +fn test_is_utf8() { + // deny overlong encodings + assert!(from_utf8(&[0xc0, 0x80]).is_err()); + assert!(from_utf8(&[0xc0, 0xae]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); + assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); + assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); + assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); + + // deny surrogates + assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); + assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); + + assert!(from_utf8(&[0xC2, 0x80]).is_ok()); + assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); + assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); + assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); +} + +#[test] +fn test_is_utf16() { + use unicode::str::is_utf16; + + macro_rules! pos { + ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } } + } + + // non-surrogates + pos!(&[0x0000], + &[0x0001, 0x0002], + &[0xD7FF], + &[0xE000]); + + // surrogate pairs (randomly generated with Python 3's + // .encode('utf-16be')) + pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45], + &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14], + &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]); + + // mixtures (also random) + pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65], + &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006], + &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]); + + // negative tests + macro_rules! neg { + ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } } + } + + neg!( + // surrogate + regular unit + &[0xdb45, 0x0000], + // surrogate + lead surrogate + &[0xd900, 0xd900], + // unterminated surrogate + &[0xd8ff], + // trail surrogate without a lead + &[0xddb7]); + + // random byte sequences that Python 3's .decode('utf-16be') + // failed on + neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7], + &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3], + &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca], + &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278], + &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e], + &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5], + &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee], + &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7], + &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a], + &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a], + &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe], + &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf], + &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e], + &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5], + &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f], + &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b], + &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7], + &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9], + &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8], + &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282], + &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]); +} + +#[test] +fn test_as_bytes() { + // no null + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let b: &[u8] = &[]; + assert_eq!("".as_bytes(), b); + assert_eq!("abc".as_bytes(), b"abc"); + assert_eq!("ศไทย中华Việt Nam".as_bytes(), v); +} + +#[test] +#[should_panic] +fn test_as_bytes_fail() { + // Don't double free. (I'm not sure if this exercises the + // original problem code path anymore.) + let s = String::from_str(""); + let _bytes = s.as_bytes(); + panic!(); +} + +#[test] +fn test_as_ptr() { + let buf = "hello".as_ptr(); + unsafe { + assert_eq!(*buf.offset(0), b'h'); + assert_eq!(*buf.offset(1), b'e'); + assert_eq!(*buf.offset(2), b'l'); + assert_eq!(*buf.offset(3), b'l'); + assert_eq!(*buf.offset(4), b'o'); + } +} + +#[test] +fn test_subslice_offset() { + let a = "kernelsprite"; + let b = &a[7..a.len()]; + let c = &a[0..a.len() - 6]; + assert_eq!(a.subslice_offset(b), 7); + assert_eq!(a.subslice_offset(c), 0); + + let string = "a\nb\nc"; + let lines: Vec<&str> = string.lines().collect(); + assert_eq!(string.subslice_offset(lines[0]), 0); + assert_eq!(string.subslice_offset(lines[1]), 2); + assert_eq!(string.subslice_offset(lines[2]), 4); +} + +#[test] +#[should_panic] +fn test_subslice_offset_2() { + let a = "alchemiter"; + let b = "cruxtruder"; + a.subslice_offset(b); +} + +#[test] +fn vec_str_conversions() { + let s1: String = String::from_str("All mimsy were the borogoves"); + + let v: Vec<u8> = s1.as_bytes().to_vec(); + let s2: String = String::from_str(from_utf8(&v).unwrap()); + let mut i = 0; + let n1 = s1.len(); + let n2 = v.len(); + assert_eq!(n1, n2); + while i < n1 { + let a: u8 = s1.as_bytes()[i]; + let b: u8 = s2.as_bytes()[i]; + debug!("{}", a); + debug!("{}", b); + assert_eq!(a, b); + i += 1; + } +} + +#[test] +fn test_contains() { + assert!("abcde".contains("bcd")); + assert!("abcde".contains("abcd")); + assert!("abcde".contains("bcde")); + assert!("abcde".contains("")); + assert!("".contains("")); + assert!(!"abcde".contains("def")); + assert!(!"".contains("a")); + + let data = "ประเทศไทย中华Việt Nam"; + assert!(data.contains("ประเ")); + assert!(data.contains("ะเ")); + assert!(data.contains("中华")); + assert!(!data.contains("ไท华")); +} + +#[test] +fn test_contains_char() { + assert!("abc".contains_char('b')); + assert!("a".contains_char('a')); + assert!(!"abc".contains_char('d')); + assert!(!"".contains_char('a')); +} + +#[test] +fn test_char_at() { + let s = "ศไทย中华Việt Nam"; + let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = 0; + for ch in &v { + assert!(s.char_at(pos) == *ch); + pos += ch.to_string().len(); + } +} + +#[test] +fn test_char_at_reverse() { + let s = "ศไทย中华Việt Nam"; + let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = s.len(); + for ch in v.iter().rev() { + assert!(s.char_at_reverse(pos) == *ch); + pos -= ch.to_string().len(); + } +} + +#[test] +fn test_escape_unicode() { + assert_eq!("abc".escape_unicode(), + String::from_str("\\u{61}\\u{62}\\u{63}")); + assert_eq!("a c".escape_unicode(), + String::from_str("\\u{61}\\u{20}\\u{63}")); + assert_eq!("\r\n\t".escape_unicode(), + String::from_str("\\u{d}\\u{a}\\u{9}")); + assert_eq!("'\"\\".escape_unicode(), + String::from_str("\\u{27}\\u{22}\\u{5c}")); + assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), + String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}")); + assert_eq!("\u{100}\u{ffff}".escape_unicode(), + String::from_str("\\u{100}\\u{ffff}")); + assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), + String::from_str("\\u{10000}\\u{10ffff}")); + assert_eq!("ab\u{fb00}".escape_unicode(), + String::from_str("\\u{61}\\u{62}\\u{fb00}")); + assert_eq!("\u{1d4ea}\r".escape_unicode(), + String::from_str("\\u{1d4ea}\\u{d}")); +} + +#[test] +fn test_escape_default() { + assert_eq!("abc".escape_default(), String::from_str("abc")); + assert_eq!("a c".escape_default(), String::from_str("a c")); + assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t")); + assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\")); + assert_eq!("\u{100}\u{ffff}".escape_default(), + String::from_str("\\u{100}\\u{ffff}")); + assert_eq!("\u{10000}\u{10ffff}".escape_default(), + String::from_str("\\u{10000}\\u{10ffff}")); + assert_eq!("ab\u{fb00}".escape_default(), + String::from_str("ab\\u{fb00}")); + assert_eq!("\u{1d4ea}\r".escape_default(), + String::from_str("\\u{1d4ea}\\r")); +} + +#[test] +fn test_total_ord() { + "1234".cmp("123") == Greater; + "123".cmp("1234") == Less; + "1234".cmp("1234") == Equal; + "12345555".cmp("123456") == Less; + "22".cmp("1234") == Greater; +} + +#[test] +fn test_char_range_at() { + let data = "b¢€𤭢𤭢€¢b"; + assert_eq!('b', data.char_range_at(0).ch); + assert_eq!('¢', data.char_range_at(1).ch); + assert_eq!('€', data.char_range_at(3).ch); + assert_eq!('𤭢', data.char_range_at(6).ch); + assert_eq!('𤭢', data.char_range_at(10).ch); + assert_eq!('€', data.char_range_at(14).ch); + assert_eq!('¢', data.char_range_at(17).ch); + assert_eq!('b', data.char_range_at(19).ch); +} + +#[test] +fn test_char_range_at_reverse_underflow() { + assert_eq!("abc".char_range_at_reverse(0).next, 0); +} + +#[test] +fn test_iterator() { + let s = "ศไทย中华Việt Nam"; + let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + + let mut pos = 0; + let it = s.chars(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); +} + +#[test] +fn test_rev_iterator() { + let s = "ศไทย中华Việt Nam"; + let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; + + let mut pos = 0; + let it = s.chars().rev(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); +} + +#[test] +fn test_chars_decoding() { + let mut bytes = [0; 4]; + for c in (0..0x110000).filter_map(::std::char::from_u32) { + let len = c.encode_utf8(&mut bytes).unwrap_or(0); + let s = ::std::str::from_utf8(&bytes[..len]).unwrap(); + if Some(c) != s.chars().next() { + panic!("character {:x}={} does not decode correctly", c as u32, c); + } + } +} + +#[test] +fn test_chars_rev_decoding() { + let mut bytes = [0; 4]; + for c in (0..0x110000).filter_map(::std::char::from_u32) { + let len = c.encode_utf8(&mut bytes).unwrap_or(0); + let s = ::std::str::from_utf8(&bytes[..len]).unwrap(); + if Some(c) != s.chars().rev().next() { + panic!("character {:x}={} does not decode correctly", c as u32, c); + } + } +} + +#[test] +fn test_iterator_clone() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.chars(); + it.next(); + assert!(it.clone().zip(it).all(|(x,y)| x == y)); +} + +#[test] +fn test_bytesator() { + let s = "ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = 0; + + for b in s.bytes() { + assert_eq!(b, v[pos]); + pos += 1; + } +} + +#[test] +fn test_bytes_revator() { + let s = "ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = v.len(); + + for b in s.bytes().rev() { + pos -= 1; + assert_eq!(b, v[pos]); + } +} + +#[test] +fn test_char_indicesator() { + let s = "ศไทย中华Việt Nam"; + let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27]; + let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + + let mut pos = 0; + let it = s.char_indices(); + + for c in it { + assert_eq!(c, (p[pos], v[pos])); + pos += 1; + } + assert_eq!(pos, v.len()); + assert_eq!(pos, p.len()); +} + +#[test] +fn test_char_indices_revator() { + let s = "ศไทย中华Việt Nam"; + let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0]; + let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; + + let mut pos = 0; + let it = s.char_indices().rev(); + + for c in it { + assert_eq!(c, (p[pos], v[pos])); + pos += 1; + } + assert_eq!(pos, v.len()); + assert_eq!(pos, p.len()); +} + +#[test] +fn test_splitn_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.splitn(3, ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + // Unicode + let split: Vec<&str> = data.splitn(3, 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); +} + +#[test] +fn test_split_char_iterator_no_trailing() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split('\n').collect(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); + + let split: Vec<&str> = data.split_terminator('\n').collect(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); +} + +#[test] +fn test_words() { + let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; + let words: Vec<&str> = data.words().collect(); + assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) +} + +#[test] +fn test_nfd_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfd_chars().collect::<String>(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "d\u{307}\u{1c4}"); + t!("\u{2026}", "\u{2026}"); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); + t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); + t!("a\u{301}", "a\u{301}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); + t!("\u{ac1c}", "\u{1100}\u{1162}"); +} + +#[test] +fn test_nfkd_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfkd_chars().collect::<String>(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "d\u{307}DZ\u{30c}"); + t!("\u{2026}", "..."); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); + t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); + t!("a\u{301}", "a\u{301}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); + t!("\u{ac1c}", "\u{1100}\u{1162}"); +} + +#[test] +fn test_nfc_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfc_chars().collect::<String>(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "\u{1e0b}\u{1c4}"); + t!("\u{2026}", "\u{2026}"); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); + t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); + t!("a\u{301}", "\u{e1}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{d4db}"); + t!("\u{ac1c}", "\u{ac1c}"); + t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); +} + +#[test] +fn test_nfkc_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfkc_chars().collect::<String>(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "\u{1e0b}D\u{17d}"); + t!("\u{2026}", "..."); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); + t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); + t!("a\u{301}", "\u{e1}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{d4db}"); + t!("\u{ac1c}", "\u{ac1c}"); + t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); +} + +#[test] +fn test_lines() { + let data = "\nMäry häd ä little lämb\n\nLittle lämb\n"; + let lines: Vec<&str> = data.lines().collect(); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); + + let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n + let lines: Vec<&str> = data.lines().collect(); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); +} + +#[test] +fn test_graphemes() { + use std::iter::order; + + // official Unicode test data + // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt + let test_same: [(_, &[_]); 325] = [ + ("\u{20}\u{20}", &["\u{20}", "\u{20}"]), + ("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]), + ("\u{20}\u{D}", &["\u{20}", "\u{D}"]), + ("\u{20}\u{308}\u{D}", &["\u{20}\u{308}", "\u{D}"]), + ("\u{20}\u{A}", &["\u{20}", "\u{A}"]), + ("\u{20}\u{308}\u{A}", &["\u{20}\u{308}", "\u{A}"]), + ("\u{20}\u{1}", &["\u{20}", "\u{1}"]), + ("\u{20}\u{308}\u{1}", &["\u{20}\u{308}", "\u{1}"]), + ("\u{20}\u{300}", &["\u{20}\u{300}"]), + ("\u{20}\u{308}\u{300}", &["\u{20}\u{308}\u{300}"]), + ("\u{20}\u{1100}", &["\u{20}", "\u{1100}"]), + ("\u{20}\u{308}\u{1100}", &["\u{20}\u{308}", "\u{1100}"]), + ("\u{20}\u{1160}", &["\u{20}", "\u{1160}"]), + ("\u{20}\u{308}\u{1160}", &["\u{20}\u{308}", "\u{1160}"]), + ("\u{20}\u{11A8}", &["\u{20}", "\u{11A8}"]), + ("\u{20}\u{308}\u{11A8}", &["\u{20}\u{308}", "\u{11A8}"]), + ("\u{20}\u{AC00}", &["\u{20}", "\u{AC00}"]), + ("\u{20}\u{308}\u{AC00}", &["\u{20}\u{308}", "\u{AC00}"]), + ("\u{20}\u{AC01}", &["\u{20}", "\u{AC01}"]), + ("\u{20}\u{308}\u{AC01}", &["\u{20}\u{308}", "\u{AC01}"]), + ("\u{20}\u{1F1E6}", &["\u{20}", "\u{1F1E6}"]), + ("\u{20}\u{308}\u{1F1E6}", &["\u{20}\u{308}", "\u{1F1E6}"]), + ("\u{20}\u{378}", &["\u{20}", "\u{378}"]), + ("\u{20}\u{308}\u{378}", &["\u{20}\u{308}", "\u{378}"]), + ("\u{D}\u{20}", &["\u{D}", "\u{20}"]), + ("\u{D}\u{308}\u{20}", &["\u{D}", "\u{308}", "\u{20}"]), + ("\u{D}\u{D}", &["\u{D}", "\u{D}"]), + ("\u{D}\u{308}\u{D}", &["\u{D}", "\u{308}", "\u{D}"]), + ("\u{D}\u{A}", &["\u{D}\u{A}"]), + ("\u{D}\u{308}\u{A}", &["\u{D}", "\u{308}", "\u{A}"]), + ("\u{D}\u{1}", &["\u{D}", "\u{1}"]), + ("\u{D}\u{308}\u{1}", &["\u{D}", "\u{308}", "\u{1}"]), + ("\u{D}\u{300}", &["\u{D}", "\u{300}"]), + ("\u{D}\u{308}\u{300}", &["\u{D}", "\u{308}\u{300}"]), + ("\u{D}\u{903}", &["\u{D}", "\u{903}"]), + ("\u{D}\u{1100}", &["\u{D}", "\u{1100}"]), + ("\u{D}\u{308}\u{1100}", &["\u{D}", "\u{308}", "\u{1100}"]), + ("\u{D}\u{1160}", &["\u{D}", "\u{1160}"]), + ("\u{D}\u{308}\u{1160}", &["\u{D}", "\u{308}", "\u{1160}"]), + ("\u{D}\u{11A8}", &["\u{D}", "\u{11A8}"]), + ("\u{D}\u{308}\u{11A8}", &["\u{D}", "\u{308}", "\u{11A8}"]), + ("\u{D}\u{AC00}", &["\u{D}", "\u{AC00}"]), + ("\u{D}\u{308}\u{AC00}", &["\u{D}", "\u{308}", "\u{AC00}"]), + ("\u{D}\u{AC01}", &["\u{D}", "\u{AC01}"]), + ("\u{D}\u{308}\u{AC01}", &["\u{D}", "\u{308}", "\u{AC01}"]), + ("\u{D}\u{1F1E6}", &["\u{D}", "\u{1F1E6}"]), + ("\u{D}\u{308}\u{1F1E6}", &["\u{D}", "\u{308}", "\u{1F1E6}"]), + ("\u{D}\u{378}", &["\u{D}", "\u{378}"]), + ("\u{D}\u{308}\u{378}", &["\u{D}", "\u{308}", "\u{378}"]), + ("\u{A}\u{20}", &["\u{A}", "\u{20}"]), + ("\u{A}\u{308}\u{20}", &["\u{A}", "\u{308}", "\u{20}"]), + ("\u{A}\u{D}", &["\u{A}", "\u{D}"]), + ("\u{A}\u{308}\u{D}", &["\u{A}", "\u{308}", "\u{D}"]), + ("\u{A}\u{A}", &["\u{A}", "\u{A}"]), + ("\u{A}\u{308}\u{A}", &["\u{A}", "\u{308}", "\u{A}"]), + ("\u{A}\u{1}", &["\u{A}", "\u{1}"]), + ("\u{A}\u{308}\u{1}", &["\u{A}", "\u{308}", "\u{1}"]), + ("\u{A}\u{300}", &["\u{A}", "\u{300}"]), + ("\u{A}\u{308}\u{300}", &["\u{A}", "\u{308}\u{300}"]), + ("\u{A}\u{903}", &["\u{A}", "\u{903}"]), + ("\u{A}\u{1100}", &["\u{A}", "\u{1100}"]), + ("\u{A}\u{308}\u{1100}", &["\u{A}", "\u{308}", "\u{1100}"]), + ("\u{A}\u{1160}", &["\u{A}", "\u{1160}"]), + ("\u{A}\u{308}\u{1160}", &["\u{A}", "\u{308}", "\u{1160}"]), + ("\u{A}\u{11A8}", &["\u{A}", "\u{11A8}"]), + ("\u{A}\u{308}\u{11A8}", &["\u{A}", "\u{308}", "\u{11A8}"]), + ("\u{A}\u{AC00}", &["\u{A}", "\u{AC00}"]), + ("\u{A}\u{308}\u{AC00}", &["\u{A}", "\u{308}", "\u{AC00}"]), + ("\u{A}\u{AC01}", &["\u{A}", "\u{AC01}"]), + ("\u{A}\u{308}\u{AC01}", &["\u{A}", "\u{308}", "\u{AC01}"]), + ("\u{A}\u{1F1E6}", &["\u{A}", "\u{1F1E6}"]), + ("\u{A}\u{308}\u{1F1E6}", &["\u{A}", "\u{308}", "\u{1F1E6}"]), + ("\u{A}\u{378}", &["\u{A}", "\u{378}"]), + ("\u{A}\u{308}\u{378}", &["\u{A}", "\u{308}", "\u{378}"]), + ("\u{1}\u{20}", &["\u{1}", "\u{20}"]), + ("\u{1}\u{308}\u{20}", &["\u{1}", "\u{308}", "\u{20}"]), + ("\u{1}\u{D}", &["\u{1}", "\u{D}"]), + ("\u{1}\u{308}\u{D}", &["\u{1}", "\u{308}", "\u{D}"]), + ("\u{1}\u{A}", &["\u{1}", "\u{A}"]), + ("\u{1}\u{308}\u{A}", &["\u{1}", "\u{308}", "\u{A}"]), + ("\u{1}\u{1}", &["\u{1}", "\u{1}"]), + ("\u{1}\u{308}\u{1}", &["\u{1}", "\u{308}", "\u{1}"]), + ("\u{1}\u{300}", &["\u{1}", "\u{300}"]), + ("\u{1}\u{308}\u{300}", &["\u{1}", "\u{308}\u{300}"]), + ("\u{1}\u{903}", &["\u{1}", "\u{903}"]), + ("\u{1}\u{1100}", &["\u{1}", "\u{1100}"]), + ("\u{1}\u{308}\u{1100}", &["\u{1}", "\u{308}", "\u{1100}"]), + ("\u{1}\u{1160}", &["\u{1}", "\u{1160}"]), + ("\u{1}\u{308}\u{1160}", &["\u{1}", "\u{308}", "\u{1160}"]), + ("\u{1}\u{11A8}", &["\u{1}", "\u{11A8}"]), + ("\u{1}\u{308}\u{11A8}", &["\u{1}", "\u{308}", "\u{11A8}"]), + ("\u{1}\u{AC00}", &["\u{1}", "\u{AC00}"]), + ("\u{1}\u{308}\u{AC00}", &["\u{1}", "\u{308}", "\u{AC00}"]), + ("\u{1}\u{AC01}", &["\u{1}", "\u{AC01}"]), + ("\u{1}\u{308}\u{AC01}", &["\u{1}", "\u{308}", "\u{AC01}"]), + ("\u{1}\u{1F1E6}", &["\u{1}", "\u{1F1E6}"]), + ("\u{1}\u{308}\u{1F1E6}", &["\u{1}", "\u{308}", "\u{1F1E6}"]), + ("\u{1}\u{378}", &["\u{1}", "\u{378}"]), + ("\u{1}\u{308}\u{378}", &["\u{1}", "\u{308}", "\u{378}"]), + ("\u{300}\u{20}", &["\u{300}", "\u{20}"]), + ("\u{300}\u{308}\u{20}", &["\u{300}\u{308}", "\u{20}"]), + ("\u{300}\u{D}", &["\u{300}", "\u{D}"]), + ("\u{300}\u{308}\u{D}", &["\u{300}\u{308}", "\u{D}"]), + ("\u{300}\u{A}", &["\u{300}", "\u{A}"]), + ("\u{300}\u{308}\u{A}", &["\u{300}\u{308}", "\u{A}"]), + ("\u{300}\u{1}", &["\u{300}", "\u{1}"]), + ("\u{300}\u{308}\u{1}", &["\u{300}\u{308}", "\u{1}"]), + ("\u{300}\u{300}", &["\u{300}\u{300}"]), + ("\u{300}\u{308}\u{300}", &["\u{300}\u{308}\u{300}"]), + ("\u{300}\u{1100}", &["\u{300}", "\u{1100}"]), + ("\u{300}\u{308}\u{1100}", &["\u{300}\u{308}", "\u{1100}"]), + ("\u{300}\u{1160}", &["\u{300}", "\u{1160}"]), + ("\u{300}\u{308}\u{1160}", &["\u{300}\u{308}", "\u{1160}"]), + ("\u{300}\u{11A8}", &["\u{300}", "\u{11A8}"]), + ("\u{300}\u{308}\u{11A8}", &["\u{300}\u{308}", "\u{11A8}"]), + ("\u{300}\u{AC00}", &["\u{300}", "\u{AC00}"]), + ("\u{300}\u{308}\u{AC00}", &["\u{300}\u{308}", "\u{AC00}"]), + ("\u{300}\u{AC01}", &["\u{300}", "\u{AC01}"]), + ("\u{300}\u{308}\u{AC01}", &["\u{300}\u{308}", "\u{AC01}"]), + ("\u{300}\u{1F1E6}", &["\u{300}", "\u{1F1E6}"]), + ("\u{300}\u{308}\u{1F1E6}", &["\u{300}\u{308}", "\u{1F1E6}"]), + ("\u{300}\u{378}", &["\u{300}", "\u{378}"]), + ("\u{300}\u{308}\u{378}", &["\u{300}\u{308}", "\u{378}"]), + ("\u{903}\u{20}", &["\u{903}", "\u{20}"]), + ("\u{903}\u{308}\u{20}", &["\u{903}\u{308}", "\u{20}"]), + ("\u{903}\u{D}", &["\u{903}", "\u{D}"]), + ("\u{903}\u{308}\u{D}", &["\u{903}\u{308}", "\u{D}"]), + ("\u{903}\u{A}", &["\u{903}", "\u{A}"]), + ("\u{903}\u{308}\u{A}", &["\u{903}\u{308}", "\u{A}"]), + ("\u{903}\u{1}", &["\u{903}", "\u{1}"]), + ("\u{903}\u{308}\u{1}", &["\u{903}\u{308}", "\u{1}"]), + ("\u{903}\u{300}", &["\u{903}\u{300}"]), + ("\u{903}\u{308}\u{300}", &["\u{903}\u{308}\u{300}"]), + ("\u{903}\u{1100}", &["\u{903}", "\u{1100}"]), + ("\u{903}\u{308}\u{1100}", &["\u{903}\u{308}", "\u{1100}"]), + ("\u{903}\u{1160}", &["\u{903}", "\u{1160}"]), + ("\u{903}\u{308}\u{1160}", &["\u{903}\u{308}", "\u{1160}"]), + ("\u{903}\u{11A8}", &["\u{903}", "\u{11A8}"]), + ("\u{903}\u{308}\u{11A8}", &["\u{903}\u{308}", "\u{11A8}"]), + ("\u{903}\u{AC00}", &["\u{903}", "\u{AC00}"]), + ("\u{903}\u{308}\u{AC00}", &["\u{903}\u{308}", "\u{AC00}"]), + ("\u{903}\u{AC01}", &["\u{903}", "\u{AC01}"]), + ("\u{903}\u{308}\u{AC01}", &["\u{903}\u{308}", "\u{AC01}"]), + ("\u{903}\u{1F1E6}", &["\u{903}", "\u{1F1E6}"]), + ("\u{903}\u{308}\u{1F1E6}", &["\u{903}\u{308}", "\u{1F1E6}"]), + ("\u{903}\u{378}", &["\u{903}", "\u{378}"]), + ("\u{903}\u{308}\u{378}", &["\u{903}\u{308}", "\u{378}"]), + ("\u{1100}\u{20}", &["\u{1100}", "\u{20}"]), + ("\u{1100}\u{308}\u{20}", &["\u{1100}\u{308}", "\u{20}"]), + ("\u{1100}\u{D}", &["\u{1100}", "\u{D}"]), + ("\u{1100}\u{308}\u{D}", &["\u{1100}\u{308}", "\u{D}"]), + ("\u{1100}\u{A}", &["\u{1100}", "\u{A}"]), + ("\u{1100}\u{308}\u{A}", &["\u{1100}\u{308}", "\u{A}"]), + ("\u{1100}\u{1}", &["\u{1100}", "\u{1}"]), + ("\u{1100}\u{308}\u{1}", &["\u{1100}\u{308}", "\u{1}"]), + ("\u{1100}\u{300}", &["\u{1100}\u{300}"]), + ("\u{1100}\u{308}\u{300}", &["\u{1100}\u{308}\u{300}"]), + ("\u{1100}\u{1100}", &["\u{1100}\u{1100}"]), + ("\u{1100}\u{308}\u{1100}", &["\u{1100}\u{308}", "\u{1100}"]), + ("\u{1100}\u{1160}", &["\u{1100}\u{1160}"]), + ("\u{1100}\u{308}\u{1160}", &["\u{1100}\u{308}", "\u{1160}"]), + ("\u{1100}\u{11A8}", &["\u{1100}", "\u{11A8}"]), + ("\u{1100}\u{308}\u{11A8}", &["\u{1100}\u{308}", "\u{11A8}"]), + ("\u{1100}\u{AC00}", &["\u{1100}\u{AC00}"]), + ("\u{1100}\u{308}\u{AC00}", &["\u{1100}\u{308}", "\u{AC00}"]), + ("\u{1100}\u{AC01}", &["\u{1100}\u{AC01}"]), + ("\u{1100}\u{308}\u{AC01}", &["\u{1100}\u{308}", "\u{AC01}"]), + ("\u{1100}\u{1F1E6}", &["\u{1100}", "\u{1F1E6}"]), + ("\u{1100}\u{308}\u{1F1E6}", &["\u{1100}\u{308}", "\u{1F1E6}"]), + ("\u{1100}\u{378}", &["\u{1100}", "\u{378}"]), + ("\u{1100}\u{308}\u{378}", &["\u{1100}\u{308}", "\u{378}"]), + ("\u{1160}\u{20}", &["\u{1160}", "\u{20}"]), + ("\u{1160}\u{308}\u{20}", &["\u{1160}\u{308}", "\u{20}"]), + ("\u{1160}\u{D}", &["\u{1160}", "\u{D}"]), + ("\u{1160}\u{308}\u{D}", &["\u{1160}\u{308}", "\u{D}"]), + ("\u{1160}\u{A}", &["\u{1160}", "\u{A}"]), + ("\u{1160}\u{308}\u{A}", &["\u{1160}\u{308}", "\u{A}"]), + ("\u{1160}\u{1}", &["\u{1160}", "\u{1}"]), + ("\u{1160}\u{308}\u{1}", &["\u{1160}\u{308}", "\u{1}"]), + ("\u{1160}\u{300}", &["\u{1160}\u{300}"]), + ("\u{1160}\u{308}\u{300}", &["\u{1160}\u{308}\u{300}"]), + ("\u{1160}\u{1100}", &["\u{1160}", "\u{1100}"]), + ("\u{1160}\u{308}\u{1100}", &["\u{1160}\u{308}", "\u{1100}"]), + ("\u{1160}\u{1160}", &["\u{1160}\u{1160}"]), + ("\u{1160}\u{308}\u{1160}", &["\u{1160}\u{308}", "\u{1160}"]), + ("\u{1160}\u{11A8}", &["\u{1160}\u{11A8}"]), + ("\u{1160}\u{308}\u{11A8}", &["\u{1160}\u{308}", "\u{11A8}"]), + ("\u{1160}\u{AC00}", &["\u{1160}", "\u{AC00}"]), + ("\u{1160}\u{308}\u{AC00}", &["\u{1160}\u{308}", "\u{AC00}"]), + ("\u{1160}\u{AC01}", &["\u{1160}", "\u{AC01}"]), + ("\u{1160}\u{308}\u{AC01}", &["\u{1160}\u{308}", "\u{AC01}"]), + ("\u{1160}\u{1F1E6}", &["\u{1160}", "\u{1F1E6}"]), + ("\u{1160}\u{308}\u{1F1E6}", &["\u{1160}\u{308}", "\u{1F1E6}"]), + ("\u{1160}\u{378}", &["\u{1160}", "\u{378}"]), + ("\u{1160}\u{308}\u{378}", &["\u{1160}\u{308}", "\u{378}"]), + ("\u{11A8}\u{20}", &["\u{11A8}", "\u{20}"]), + ("\u{11A8}\u{308}\u{20}", &["\u{11A8}\u{308}", "\u{20}"]), + ("\u{11A8}\u{D}", &["\u{11A8}", "\u{D}"]), + ("\u{11A8}\u{308}\u{D}", &["\u{11A8}\u{308}", "\u{D}"]), + ("\u{11A8}\u{A}", &["\u{11A8}", "\u{A}"]), + ("\u{11A8}\u{308}\u{A}", &["\u{11A8}\u{308}", "\u{A}"]), + ("\u{11A8}\u{1}", &["\u{11A8}", "\u{1}"]), + ("\u{11A8}\u{308}\u{1}", &["\u{11A8}\u{308}", "\u{1}"]), + ("\u{11A8}\u{300}", &["\u{11A8}\u{300}"]), + ("\u{11A8}\u{308}\u{300}", &["\u{11A8}\u{308}\u{300}"]), + ("\u{11A8}\u{1100}", &["\u{11A8}", "\u{1100}"]), + ("\u{11A8}\u{308}\u{1100}", &["\u{11A8}\u{308}", "\u{1100}"]), + ("\u{11A8}\u{1160}", &["\u{11A8}", "\u{1160}"]), + ("\u{11A8}\u{308}\u{1160}", &["\u{11A8}\u{308}", "\u{1160}"]), + ("\u{11A8}\u{11A8}", &["\u{11A8}\u{11A8}"]), + ("\u{11A8}\u{308}\u{11A8}", &["\u{11A8}\u{308}", "\u{11A8}"]), + ("\u{11A8}\u{AC00}", &["\u{11A8}", "\u{AC00}"]), + ("\u{11A8}\u{308}\u{AC00}", &["\u{11A8}\u{308}", "\u{AC00}"]), + ("\u{11A8}\u{AC01}", &["\u{11A8}", "\u{AC01}"]), + ("\u{11A8}\u{308}\u{AC01}", &["\u{11A8}\u{308}", "\u{AC01}"]), + ("\u{11A8}\u{1F1E6}", &["\u{11A8}", "\u{1F1E6}"]), + ("\u{11A8}\u{308}\u{1F1E6}", &["\u{11A8}\u{308}", "\u{1F1E6}"]), + ("\u{11A8}\u{378}", &["\u{11A8}", "\u{378}"]), + ("\u{11A8}\u{308}\u{378}", &["\u{11A8}\u{308}", "\u{378}"]), + ("\u{AC00}\u{20}", &["\u{AC00}", "\u{20}"]), + ("\u{AC00}\u{308}\u{20}", &["\u{AC00}\u{308}", "\u{20}"]), + ("\u{AC00}\u{D}", &["\u{AC00}", "\u{D}"]), + ("\u{AC00}\u{308}\u{D}", &["\u{AC00}\u{308}", "\u{D}"]), + ("\u{AC00}\u{A}", &["\u{AC00}", "\u{A}"]), + ("\u{AC00}\u{308}\u{A}", &["\u{AC00}\u{308}", "\u{A}"]), + ("\u{AC00}\u{1}", &["\u{AC00}", "\u{1}"]), + ("\u{AC00}\u{308}\u{1}", &["\u{AC00}\u{308}", "\u{1}"]), + ("\u{AC00}\u{300}", &["\u{AC00}\u{300}"]), + ("\u{AC00}\u{308}\u{300}", &["\u{AC00}\u{308}\u{300}"]), + ("\u{AC00}\u{1100}", &["\u{AC00}", "\u{1100}"]), + ("\u{AC00}\u{308}\u{1100}", &["\u{AC00}\u{308}", "\u{1100}"]), + ("\u{AC00}\u{1160}", &["\u{AC00}\u{1160}"]), + ("\u{AC00}\u{308}\u{1160}", &["\u{AC00}\u{308}", "\u{1160}"]), + ("\u{AC00}\u{11A8}", &["\u{AC00}\u{11A8}"]), + ("\u{AC00}\u{308}\u{11A8}", &["\u{AC00}\u{308}", "\u{11A8}"]), + ("\u{AC00}\u{AC00}", &["\u{AC00}", "\u{AC00}"]), + ("\u{AC00}\u{308}\u{AC00}", &["\u{AC00}\u{308}", "\u{AC00}"]), + ("\u{AC00}\u{AC01}", &["\u{AC00}", "\u{AC01}"]), + ("\u{AC00}\u{308}\u{AC01}", &["\u{AC00}\u{308}", "\u{AC01}"]), + ("\u{AC00}\u{1F1E6}", &["\u{AC00}", "\u{1F1E6}"]), + ("\u{AC00}\u{308}\u{1F1E6}", &["\u{AC00}\u{308}", "\u{1F1E6}"]), + ("\u{AC00}\u{378}", &["\u{AC00}", "\u{378}"]), + ("\u{AC00}\u{308}\u{378}", &["\u{AC00}\u{308}", "\u{378}"]), + ("\u{AC01}\u{20}", &["\u{AC01}", "\u{20}"]), + ("\u{AC01}\u{308}\u{20}", &["\u{AC01}\u{308}", "\u{20}"]), + ("\u{AC01}\u{D}", &["\u{AC01}", "\u{D}"]), + ("\u{AC01}\u{308}\u{D}", &["\u{AC01}\u{308}", "\u{D}"]), + ("\u{AC01}\u{A}", &["\u{AC01}", "\u{A}"]), + ("\u{AC01}\u{308}\u{A}", &["\u{AC01}\u{308}", "\u{A}"]), + ("\u{AC01}\u{1}", &["\u{AC01}", "\u{1}"]), + ("\u{AC01}\u{308}\u{1}", &["\u{AC01}\u{308}", "\u{1}"]), + ("\u{AC01}\u{300}", &["\u{AC01}\u{300}"]), + ("\u{AC01}\u{308}\u{300}", &["\u{AC01}\u{308}\u{300}"]), + ("\u{AC01}\u{1100}", &["\u{AC01}", "\u{1100}"]), + ("\u{AC01}\u{308}\u{1100}", &["\u{AC01}\u{308}", "\u{1100}"]), + ("\u{AC01}\u{1160}", &["\u{AC01}", "\u{1160}"]), + ("\u{AC01}\u{308}\u{1160}", &["\u{AC01}\u{308}", "\u{1160}"]), + ("\u{AC01}\u{11A8}", &["\u{AC01}\u{11A8}"]), + ("\u{AC01}\u{308}\u{11A8}", &["\u{AC01}\u{308}", "\u{11A8}"]), + ("\u{AC01}\u{AC00}", &["\u{AC01}", "\u{AC00}"]), + ("\u{AC01}\u{308}\u{AC00}", &["\u{AC01}\u{308}", "\u{AC00}"]), + ("\u{AC01}\u{AC01}", &["\u{AC01}", "\u{AC01}"]), + ("\u{AC01}\u{308}\u{AC01}", &["\u{AC01}\u{308}", "\u{AC01}"]), + ("\u{AC01}\u{1F1E6}", &["\u{AC01}", "\u{1F1E6}"]), + ("\u{AC01}\u{308}\u{1F1E6}", &["\u{AC01}\u{308}", "\u{1F1E6}"]), + ("\u{AC01}\u{378}", &["\u{AC01}", "\u{378}"]), + ("\u{AC01}\u{308}\u{378}", &["\u{AC01}\u{308}", "\u{378}"]), + ("\u{1F1E6}\u{20}", &["\u{1F1E6}", "\u{20}"]), + ("\u{1F1E6}\u{308}\u{20}", &["\u{1F1E6}\u{308}", "\u{20}"]), + ("\u{1F1E6}\u{D}", &["\u{1F1E6}", "\u{D}"]), + ("\u{1F1E6}\u{308}\u{D}", &["\u{1F1E6}\u{308}", "\u{D}"]), + ("\u{1F1E6}\u{A}", &["\u{1F1E6}", "\u{A}"]), + ("\u{1F1E6}\u{308}\u{A}", &["\u{1F1E6}\u{308}", "\u{A}"]), + ("\u{1F1E6}\u{1}", &["\u{1F1E6}", "\u{1}"]), + ("\u{1F1E6}\u{308}\u{1}", &["\u{1F1E6}\u{308}", "\u{1}"]), + ("\u{1F1E6}\u{300}", &["\u{1F1E6}\u{300}"]), + ("\u{1F1E6}\u{308}\u{300}", &["\u{1F1E6}\u{308}\u{300}"]), + ("\u{1F1E6}\u{1100}", &["\u{1F1E6}", "\u{1100}"]), + ("\u{1F1E6}\u{308}\u{1100}", &["\u{1F1E6}\u{308}", "\u{1100}"]), + ("\u{1F1E6}\u{1160}", &["\u{1F1E6}", "\u{1160}"]), + ("\u{1F1E6}\u{308}\u{1160}", &["\u{1F1E6}\u{308}", "\u{1160}"]), + ("\u{1F1E6}\u{11A8}", &["\u{1F1E6}", "\u{11A8}"]), + ("\u{1F1E6}\u{308}\u{11A8}", &["\u{1F1E6}\u{308}", "\u{11A8}"]), + ("\u{1F1E6}\u{AC00}", &["\u{1F1E6}", "\u{AC00}"]), + ("\u{1F1E6}\u{308}\u{AC00}", &["\u{1F1E6}\u{308}", "\u{AC00}"]), + ("\u{1F1E6}\u{AC01}", &["\u{1F1E6}", "\u{AC01}"]), + ("\u{1F1E6}\u{308}\u{AC01}", &["\u{1F1E6}\u{308}", "\u{AC01}"]), + ("\u{1F1E6}\u{1F1E6}", &["\u{1F1E6}\u{1F1E6}"]), + ("\u{1F1E6}\u{308}\u{1F1E6}", &["\u{1F1E6}\u{308}", "\u{1F1E6}"]), + ("\u{1F1E6}\u{378}", &["\u{1F1E6}", "\u{378}"]), + ("\u{1F1E6}\u{308}\u{378}", &["\u{1F1E6}\u{308}", "\u{378}"]), + ("\u{378}\u{20}", &["\u{378}", "\u{20}"]), + ("\u{378}\u{308}\u{20}", &["\u{378}\u{308}", "\u{20}"]), + ("\u{378}\u{D}", &["\u{378}", "\u{D}"]), + ("\u{378}\u{308}\u{D}", &["\u{378}\u{308}", "\u{D}"]), + ("\u{378}\u{A}", &["\u{378}", "\u{A}"]), + ("\u{378}\u{308}\u{A}", &["\u{378}\u{308}", "\u{A}"]), + ("\u{378}\u{1}", &["\u{378}", "\u{1}"]), + ("\u{378}\u{308}\u{1}", &["\u{378}\u{308}", "\u{1}"]), + ("\u{378}\u{300}", &["\u{378}\u{300}"]), + ("\u{378}\u{308}\u{300}", &["\u{378}\u{308}\u{300}"]), + ("\u{378}\u{1100}", &["\u{378}", "\u{1100}"]), + ("\u{378}\u{308}\u{1100}", &["\u{378}\u{308}", "\u{1100}"]), + ("\u{378}\u{1160}", &["\u{378}", "\u{1160}"]), + ("\u{378}\u{308}\u{1160}", &["\u{378}\u{308}", "\u{1160}"]), + ("\u{378}\u{11A8}", &["\u{378}", "\u{11A8}"]), + ("\u{378}\u{308}\u{11A8}", &["\u{378}\u{308}", "\u{11A8}"]), + ("\u{378}\u{AC00}", &["\u{378}", "\u{AC00}"]), + ("\u{378}\u{308}\u{AC00}", &["\u{378}\u{308}", "\u{AC00}"]), + ("\u{378}\u{AC01}", &["\u{378}", "\u{AC01}"]), + ("\u{378}\u{308}\u{AC01}", &["\u{378}\u{308}", "\u{AC01}"]), + ("\u{378}\u{1F1E6}", &["\u{378}", "\u{1F1E6}"]), + ("\u{378}\u{308}\u{1F1E6}", &["\u{378}\u{308}", "\u{1F1E6}"]), + ("\u{378}\u{378}", &["\u{378}", "\u{378}"]), + ("\u{378}\u{308}\u{378}", &["\u{378}\u{308}", "\u{378}"]), + ("\u{61}\u{1F1E6}\u{62}", &["\u{61}", "\u{1F1E6}", "\u{62}"]), + ("\u{1F1F7}\u{1F1FA}", &["\u{1F1F7}\u{1F1FA}"]), + ("\u{1F1F7}\u{1F1FA}\u{1F1F8}", &["\u{1F1F7}\u{1F1FA}\u{1F1F8}"]), + ("\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}", + &["\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}"]), + ("\u{1F1F7}\u{1F1FA}\u{200B}\u{1F1F8}\u{1F1EA}", + &["\u{1F1F7}\u{1F1FA}", "\u{200B}", "\u{1F1F8}\u{1F1EA}"]), + ("\u{1F1E6}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{1F1E7}\u{1F1E8}"]), + ("\u{1F1E6}\u{200D}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{200D}", + "\u{1F1E7}\u{1F1E8}"]), + ("\u{1F1E6}\u{1F1E7}\u{200D}\u{1F1E8}", + &["\u{1F1E6}\u{1F1E7}\u{200D}", "\u{1F1E8}"]), + ("\u{20}\u{200D}\u{646}", &["\u{20}\u{200D}", "\u{646}"]), + ("\u{646}\u{200D}\u{20}", &["\u{646}\u{200D}", "\u{20}"]), + ]; + + let test_diff: [(_, &[_], &[_]); 23] = [ + ("\u{20}\u{903}", &["\u{20}\u{903}"], &["\u{20}", "\u{903}"]), ("\u{20}\u{308}\u{903}", + &["\u{20}\u{308}\u{903}"], &["\u{20}\u{308}", "\u{903}"]), ("\u{D}\u{308}\u{903}", + &["\u{D}", "\u{308}\u{903}"], &["\u{D}", "\u{308}", "\u{903}"]), ("\u{A}\u{308}\u{903}", + &["\u{A}", "\u{308}\u{903}"], &["\u{A}", "\u{308}", "\u{903}"]), ("\u{1}\u{308}\u{903}", + &["\u{1}", "\u{308}\u{903}"], &["\u{1}", "\u{308}", "\u{903}"]), ("\u{300}\u{903}", + &["\u{300}\u{903}"], &["\u{300}", "\u{903}"]), ("\u{300}\u{308}\u{903}", + &["\u{300}\u{308}\u{903}"], &["\u{300}\u{308}", "\u{903}"]), ("\u{903}\u{903}", + &["\u{903}\u{903}"], &["\u{903}", "\u{903}"]), ("\u{903}\u{308}\u{903}", + &["\u{903}\u{308}\u{903}"], &["\u{903}\u{308}", "\u{903}"]), ("\u{1100}\u{903}", + &["\u{1100}\u{903}"], &["\u{1100}", "\u{903}"]), ("\u{1100}\u{308}\u{903}", + &["\u{1100}\u{308}\u{903}"], &["\u{1100}\u{308}", "\u{903}"]), ("\u{1160}\u{903}", + &["\u{1160}\u{903}"], &["\u{1160}", "\u{903}"]), ("\u{1160}\u{308}\u{903}", + &["\u{1160}\u{308}\u{903}"], &["\u{1160}\u{308}", "\u{903}"]), ("\u{11A8}\u{903}", + &["\u{11A8}\u{903}"], &["\u{11A8}", "\u{903}"]), ("\u{11A8}\u{308}\u{903}", + &["\u{11A8}\u{308}\u{903}"], &["\u{11A8}\u{308}", "\u{903}"]), ("\u{AC00}\u{903}", + &["\u{AC00}\u{903}"], &["\u{AC00}", "\u{903}"]), ("\u{AC00}\u{308}\u{903}", + &["\u{AC00}\u{308}\u{903}"], &["\u{AC00}\u{308}", "\u{903}"]), ("\u{AC01}\u{903}", + &["\u{AC01}\u{903}"], &["\u{AC01}", "\u{903}"]), ("\u{AC01}\u{308}\u{903}", + &["\u{AC01}\u{308}\u{903}"], &["\u{AC01}\u{308}", "\u{903}"]), ("\u{1F1E6}\u{903}", + &["\u{1F1E6}\u{903}"], &["\u{1F1E6}", "\u{903}"]), ("\u{1F1E6}\u{308}\u{903}", + &["\u{1F1E6}\u{308}\u{903}"], &["\u{1F1E6}\u{308}", "\u{903}"]), ("\u{378}\u{903}", + &["\u{378}\u{903}"], &["\u{378}", "\u{903}"]), ("\u{378}\u{308}\u{903}", + &["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]), + ]; + + for &(s, g) in &test_same[..] { + // test forward iterator + assert!(order::equals(s.graphemes(true), g.iter().cloned())); + assert!(order::equals(s.graphemes(false), g.iter().cloned())); + + // test reverse iterator + assert!(order::equals(s.graphemes(true).rev(), g.iter().rev().cloned())); + assert!(order::equals(s.graphemes(false).rev(), g.iter().rev().cloned())); + } + + for &(s, gt, gf) in &test_diff { + // test forward iterator + assert!(order::equals(s.graphemes(true), gt.iter().cloned())); + assert!(order::equals(s.graphemes(false), gf.iter().cloned())); + + // test reverse iterator + assert!(order::equals(s.graphemes(true).rev(), gt.iter().rev().cloned())); + assert!(order::equals(s.graphemes(false).rev(), gf.iter().rev().cloned())); + } + + // test the indices iterators + let s = "a̐éö̲\r\n"; + let gr_inds = s.grapheme_indices(true).collect::<Vec<(usize, &str)>>(); + let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + assert_eq!(gr_inds, b); + let gr_inds = s.grapheme_indices(true).rev().collect::<Vec<(usize, &str)>>(); + let b: &[_] = &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0, "a̐")]; + assert_eq!(gr_inds, b); + let mut gr_inds_iter = s.grapheme_indices(true); + { + let gr_inds = gr_inds_iter.by_ref(); + let e1 = gr_inds.size_hint(); + assert_eq!(e1, (1, Some(13))); + let c = gr_inds.count(); + assert_eq!(c, 4); + } + let e2 = gr_inds_iter.size_hint(); + assert_eq!(e2, (0, Some(0))); + + // make sure the reverse iterator does the right thing with "\n" at beginning of string + let s = "\n\r\n\r"; + let gr = s.graphemes(true).rev().collect::<Vec<&str>>(); + let b: &[_] = &["\r", "\r\n", "\n"]; + assert_eq!(gr, b); +} + +#[test] +fn test_split_strator() { + fn t(s: &str, sep: &str, u: &[&str]) { + let v: Vec<&str> = s.split_str(sep).collect(); + assert_eq!(v, u); + } + t("--1233345--", "12345", &["--1233345--"]); + t("abc::hello::there", "::", &["abc", "hello", "there"]); + t("::hello::there", "::", &["", "hello", "there"]); + t("hello::there::", "::", &["hello", "there", ""]); + t("::hello::there::", "::", &["", "hello", "there", ""]); + t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]); + t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]); + t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]); + t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]); + t("", ".", &[""]); + t("zz", "zz", &["",""]); + t("ok", "z", &["ok"]); + t("zzz", "zz", &["","z"]); + t("zzzzz", "zz", &["","","z"]); +} + +#[test] +fn test_str_default() { + use std::default::Default; + + fn t<S: Default + Str>() { + let s: S = Default::default(); + assert_eq!(s.as_slice(), ""); + } + + t::<&str>(); + t::<String>(); +} + +#[test] +fn test_str_container() { + fn sum_len(v: &[&str]) -> usize { + v.iter().map(|x| x.len()).sum() + } + + let s = String::from_str("01234"); + assert_eq!(5, sum_len(&["012", "", "34"])); + assert_eq!(5, sum_len(&[&String::from_str("01"), + &String::from_str("2"), + &String::from_str("34"), + &String::from_str("")])); + assert_eq!(5, sum_len(&[&s])); +} + +#[test] +fn test_str_from_utf8() { + let xs = b"hello"; + assert_eq!(from_utf8(xs), Ok("hello")); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); + + let xs = b"hello\xFF"; + assert_eq!(from_utf8(xs), Err(Utf8Error::TooShort)); +} + +mod bench { + use test::{Bencher, black_box}; + + #[bench] + fn char_iterator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().count()); + } + + #[bench] + fn char_iterator_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars() { black_box(ch); } + }); + } + + #[bench] + fn char_iterator_ascii(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().count()); + } + + #[bench] + fn char_iterator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().rev().count()); + } + + #[bench] + fn char_iterator_rev_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars().rev() { black_box(ch); } + }); + } + + #[bench] + fn char_indicesator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().count(), len)); + } + + #[bench] + fn char_indicesator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); + } + + #[bench] + fn split_unicode_ascii(b: &mut Bencher) { + let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; + + b.iter(|| assert_eq!(s.split('V').count(), 3)); + } + + #[bench] + fn split_ascii(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(' ').count(), len)); + } + + #[bench] + fn split_extern_fn(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + fn pred(c: char) -> bool { c == ' ' } + + b.iter(|| assert_eq!(s.split(pred).count(), len)); + } + + #[bench] + fn split_closure(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); + } + + #[bench] + fn split_slice(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + let c: &[char] = &[' ']; + b.iter(|| assert_eq!(s.split(c).count(), len)); + } + + #[bench] + fn bench_connect(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let sep = "→"; + let v = vec![s, s, s, s, s, s, s, s, s, s]; + b.iter(|| { + assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9); + }) + } + + #[bench] + fn bench_contains_short_short(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "sit"; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_short_long(b: &mut Bencher) { + let haystack = "\ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ +ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ +eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ +sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ +tempus vel, gravida nec quam. + +In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ +sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ +diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ +lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ +eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ +interdum. Curabitur ut nisi justo. + +Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ +mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ +lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ +est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ +felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ +ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ +feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ +Aliquam sit amet placerat lorem. + +Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ +mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ +Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ +lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ +suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ +cursus accumsan. + +Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ +feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ +vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ +leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ +malesuada sollicitudin quam eu fermentum."; + let needle = "english"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_bad_naive(b: &mut Bencher) { + let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let needle = "aaaaaaaab"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_equal(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) + } +} diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs new file mode 100644 index 00000000000..4768d5e92ac --- /dev/null +++ b/src/libcollectionstest/string.rs @@ -0,0 +1,453 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::IntoCow; +use std::iter::repeat; +use std::str::Utf8Error; +use std::string::{CowString, as_string}; + +use test::Bencher; + +#[test] +fn test_as_string() { + let x = "foo"; + assert_eq!(x, &**as_string(x)); +} + +#[test] +fn test_from_str() { + let owned: Option<::std::string::String> = "string".parse().ok(); + assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); +} + +#[test] +fn test_unsized_to_string() { + let s: &str = "abc"; + let _: String = (*s).to_string(); +} + +#[test] +fn test_from_utf8() { + let xs = b"hello".to_vec(); + assert_eq!(String::from_utf8(xs).unwrap(), + String::from_str("hello")); + + let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); + assert_eq!(String::from_utf8(xs).unwrap(), + String::from_str("ศไทย中华Việt Nam")); + + let xs = b"hello\xFF".to_vec(); + let err = String::from_utf8(xs).err().unwrap(); + assert_eq!(err.utf8_error(), Utf8Error::TooShort); + assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); +} + +#[test] +fn test_from_utf8_lossy() { + let xs = b"hello"; + let ys: CowString = "hello".into_cow(); + assert_eq!(String::from_utf8_lossy(xs), ys); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + let ys: CowString = "ศไทย中华Việt Nam".into_cow(); + assert_eq!(String::from_utf8_lossy(xs), ys); + + let xs = b"Hello\xC2 There\xFF Goodbye"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()); + + let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()); + + let xs = b"\xF5foo\xF5\x80bar"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()); + + let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()); + + let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()); + + let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; + assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\ + foo\u{10000}bar").into_cow()); + + // surrogates + let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; + assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}foo\ + \u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()); +} + +#[test] +fn test_from_utf16() { + let pairs = + [(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), + vec![0xd800, 0xdf45, 0xd800, 0xdf3f, + 0xd800, 0xdf3b, 0xd800, 0xdf46, + 0xd800, 0xdf39, 0xd800, 0xdf3b, + 0xd800, 0xdf30, 0x000a]), + + (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), + vec![0xd801, 0xdc12, 0xd801, + 0xdc49, 0xd801, 0xdc2e, 0xd801, + 0xdc40, 0xd801, 0xdc32, 0xd801, + 0xdc4b, 0x0020, 0xd801, 0xdc0f, + 0xd801, 0xdc32, 0xd801, 0xdc4d, + 0x000a]), + + (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), + vec![0xd800, 0xdf00, 0xd800, 0xdf16, + 0xd800, 0xdf0b, 0xd800, 0xdf04, + 0xd800, 0xdf11, 0xd800, 0xdf09, + 0x00b7, 0xd800, 0xdf0c, 0xd800, + 0xdf04, 0xd800, 0xdf15, 0xd800, + 0xdf04, 0xd800, 0xdf0b, 0xd800, + 0xdf09, 0xd800, 0xdf11, 0x000a ]), + + (String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), + vec![0xd801, 0xdc8b, 0xd801, 0xdc98, + 0xd801, 0xdc88, 0xd801, 0xdc91, + 0xd801, 0xdc9b, 0xd801, 0xdc92, + 0x0020, 0xd801, 0xdc95, 0xd801, + 0xdc93, 0x0020, 0xd801, 0xdc88, + 0xd801, 0xdc9a, 0xd801, 0xdc8d, + 0x0020, 0xd801, 0xdc8f, 0xd801, + 0xdc9c, 0xd801, 0xdc92, 0xd801, + 0xdc96, 0xd801, 0xdc86, 0x0020, + 0xd801, 0xdc95, 0xd801, 0xdc86, + 0x000a ]), + // Issue #12318, even-numbered non-BMP planes + (String::from_str("\u{20000}"), + vec![0xD840, 0xDC00])]; + + for p in &pairs { + let (s, u) = (*p).clone(); + let s_as_utf16 = s.utf16_units().collect::<Vec<u16>>(); + let u_as_string = String::from_utf16(&u).unwrap(); + + assert!(::unicode::str::is_utf16(&u)); + assert_eq!(s_as_utf16, u); + + assert_eq!(u_as_string, s); + assert_eq!(String::from_utf16_lossy(&u), s); + + assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s); + assert_eq!(u_as_string.utf16_units().collect::<Vec<u16>>(), u); + } +} + +#[test] +fn test_utf16_invalid() { + // completely positive cases tested above. + // lead + eof + assert!(String::from_utf16(&[0xD800]).is_err()); + // lead + lead + assert!(String::from_utf16(&[0xD800, 0xD800]).is_err()); + + // isolated trail + assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err()); + + // general + assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err()); +} + +#[test] +fn test_from_utf16_lossy() { + // completely positive cases tested above. + // lead + eof + assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from_str("\u{FFFD}")); + // lead + lead + assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), + String::from_str("\u{FFFD}\u{FFFD}")); + + // isolated trail + assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from_str("a\u{FFFD}")); + + // general + assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), + String::from_str("\u{FFFD}𐒋\u{FFFD}")); +} + +#[test] +fn test_push_bytes() { + let mut s = String::from_str("ABC"); + unsafe { + let mv = s.as_mut_vec(); + mv.push_all(&[b'D']); + } + assert_eq!(s, "ABCD"); +} + +#[test] +fn test_push_str() { + let mut s = String::new(); + s.push_str(""); + assert_eq!(&s[0..], ""); + s.push_str("abc"); + assert_eq!(&s[0..], "abc"); + s.push_str("ประเทศไทย中华Việt Nam"); + assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam"); +} + +#[test] +fn test_push() { + let mut data = String::from_str("ประเทศไทย中"); + data.push('华'); + data.push('b'); // 1 byte + data.push('¢'); // 2 byte + data.push('€'); // 3 byte + data.push('𤭢'); // 4 byte + assert_eq!(data, "ประเทศไทย中华b¢€𤭢"); +} + +#[test] +fn test_pop() { + let mut data = String::from_str("ประเทศไทย中华b¢€𤭢"); + assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes + assert_eq!(data.pop().unwrap(), '€'); // 3 bytes + assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes + assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes + assert_eq!(data.pop().unwrap(), '华'); + assert_eq!(data, "ประเทศไทย中"); +} + +#[test] +fn test_str_truncate() { + let mut s = String::from_str("12345"); + s.truncate(5); + assert_eq!(s, "12345"); + s.truncate(3); + assert_eq!(s, "123"); + s.truncate(0); + assert_eq!(s, ""); + + let mut s = String::from_str("12345"); + let p = s.as_ptr(); + s.truncate(3); + s.push_str("6"); + let p_ = s.as_ptr(); + assert_eq!(p_, p); +} + +#[test] +#[should_panic] +fn test_str_truncate_invalid_len() { + let mut s = String::from_str("12345"); + s.truncate(6); +} + +#[test] +#[should_panic] +fn test_str_truncate_split_codepoint() { + let mut s = String::from_str("\u{FC}"); // ü + s.truncate(1); +} + +#[test] +fn test_str_clear() { + let mut s = String::from_str("12345"); + s.clear(); + assert_eq!(s.len(), 0); + assert_eq!(s, ""); +} + +#[test] +fn test_str_add() { + let a = String::from_str("12345"); + let b = a + "2"; + let b = b + "2"; + assert_eq!(b.len(), 7); + assert_eq!(b, "1234522"); +} + +#[test] +fn remove() { + let mut s = "ศไทย中华Việt Nam; foobar".to_string();; + assert_eq!(s.remove(0), 'ศ'); + assert_eq!(s.len(), 33); + assert_eq!(s, "ไทย中华Việt Nam; foobar"); + assert_eq!(s.remove(17), 'ệ'); + assert_eq!(s, "ไทย中华Vit Nam; foobar"); +} + +#[test] #[should_panic] +fn remove_bad() { + "ศ".to_string().remove(1); +} + +#[test] +fn insert() { + let mut s = "foobar".to_string(); + s.insert(0, 'ệ'); + assert_eq!(s, "ệfoobar"); + s.insert(6, 'ย'); + assert_eq!(s, "ệfooยbar"); +} + +#[test] #[should_panic] fn insert_bad1() { "".to_string().insert(1, 't'); } +#[test] #[should_panic] fn insert_bad2() { "ệ".to_string().insert(1, 't'); } + +#[test] +fn test_slicing() { + let s = "foobar".to_string(); + assert_eq!("foobar", &s[..]); + assert_eq!("foo", &s[..3]); + assert_eq!("bar", &s[3..]); + assert_eq!("oob", &s[1..4]); +} + +#[test] +fn test_simple_types() { + assert_eq!(1.to_string(), "1"); + assert_eq!((-1).to_string(), "-1"); + assert_eq!(200.to_string(), "200"); + assert_eq!(2.to_string(), "2"); + assert_eq!(true.to_string(), "true"); + assert_eq!(false.to_string(), "false"); + assert_eq!(("hi".to_string()).to_string(), "hi"); +} + +#[test] +fn test_vectors() { + let x: Vec<i32> = vec![]; + assert_eq!(format!("{:?}", x), "[]"); + assert_eq!(format!("{:?}", vec![1]), "[1]"); + assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]"); + assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == + "[[], [1], [1, 1]]"); +} + +#[test] +fn test_from_iterator() { + let s = "ศไทย中华Việt Nam".to_string(); + let t = "ศไทย中华"; + let u = "Việt Nam"; + + let a: String = s.chars().collect(); + assert_eq!(s, a); + + let mut b = t.to_string(); + b.extend(u.chars()); + assert_eq!(s, b); + + let c: String = vec![t, u].into_iter().collect(); + assert_eq!(s, c); + + let mut d = t.to_string(); + d.extend(vec![u].into_iter()); + assert_eq!(s, d); +} + +#[bench] +fn bench_with_capacity(b: &mut Bencher) { + b.iter(|| { + String::with_capacity(100) + }); +} + +#[bench] +fn bench_push_str(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + b.iter(|| { + let mut r = String::new(); + r.push_str(s); + }); +} + +const REPETITIONS: u64 = 10_000; + +#[bench] +fn bench_push_str_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push_str("a") + } + }); +} + +#[bench] +fn bench_push_char_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('a') + } + }); +} + +#[bench] +fn bench_push_char_two_bytes(b: &mut Bencher) { + b.bytes = REPETITIONS * 2; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('â') + } + }); +} + +#[bench] +fn from_utf8_lossy_100_ascii(b: &mut Bencher) { + let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { + let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_invalid(b: &mut Bencher) { + let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_invalid(b: &mut Bencher) { + let s = repeat(0xf5).take(100).collect::<Vec<_>>(); + b.iter(|| { + let _ = String::from_utf8_lossy(&s); + }); +} + +#[bench] +fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { + let s = "Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + // ensure our operation produces an exact-size string before we benchmark it + let mut r = String::with_capacity(s.len()); + r.push_str(s); + assert_eq!(r.len(), r.capacity()); + b.iter(|| { + let mut r = String::with_capacity(s.len()); + r.push_str(s); + r.shrink_to_fit(); + r + }); +} diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs new file mode 100644 index 00000000000..2923bea9828 --- /dev/null +++ b/src/libcollectionstest/vec.rs @@ -0,0 +1,994 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iter::{FromIterator, repeat}; +use std::mem::size_of; +use std::vec::as_vec; + +use test::Bencher; + +struct DropCounter<'a> { + count: &'a mut u32 +} + +#[unsafe_destructor] +impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + *self.count += 1; + } +} + +#[test] +fn test_as_vec() { + let xs = [1u8, 2u8, 3u8]; + assert_eq!(&**as_vec(&xs), xs); +} + +#[test] +fn test_as_vec_dtor() { + let (mut count_x, mut count_y) = (0, 0); + { + let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }]; + assert_eq!(as_vec(xs).len(), 2); + } + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); +} + +#[test] +fn test_small_vec_struct() { + assert!(size_of::<Vec<u8>>() == size_of::<usize>() * 3); +} + +#[test] +fn test_double_drop() { + struct TwoVec<T> { + x: Vec<T>, + y: Vec<T> + } + + let (mut count_x, mut count_y) = (0, 0); + { + let mut tv = TwoVec { + x: Vec::new(), + y: Vec::new() + }; + tv.x.push(DropCounter {count: &mut count_x}); + tv.y.push(DropCounter {count: &mut count_y}); + + // If Vec had a drop flag, here is where it would be zeroed. + // Instead, it should rely on its internal state to prevent + // doing anything significant when dropped multiple times. + drop(tv.x); + + // Here tv goes out of scope, tv.y should be dropped, but not tv.x. + } + + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); +} + +#[test] +fn test_reserve() { + let mut v = Vec::new(); + assert_eq!(v.capacity(), 0); + + v.reserve(2); + assert!(v.capacity() >= 2); + + for i in 0..16 { + v.push(i); + } + + assert!(v.capacity() >= 16); + v.reserve(16); + assert!(v.capacity() >= 32); + + v.push(16); + + v.reserve(16); + assert!(v.capacity() >= 33) +} + +#[test] +fn test_extend() { + let mut v = Vec::new(); + let mut w = Vec::new(); + + v.extend(0..3); + for i in 0..3 { w.push(i) } + + assert_eq!(v, w); + + v.extend(3..10); + for i in 3..10 { w.push(i) } + + assert_eq!(v, w); +} + +#[test] +fn test_slice_from_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let slice = &mut values[2 ..]; + assert!(slice == [3, 4, 5]); + for p in slice { + *p += 2; + } + } + + assert!(values == [1, 2, 5, 6, 7]); +} + +#[test] +fn test_slice_to_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let slice = &mut values[.. 2]; + assert!(slice == [1, 2]); + for p in slice { + *p += 1; + } + } + + assert!(values == [2, 3, 3, 4, 5]); +} + +#[test] +fn test_split_at_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let (left, right) = values.split_at_mut(2); + { + let left: &[_] = left; + assert!(&left[..left.len()] == &[1, 2]); + } + for p in left { + *p += 1; + } + + { + let right: &[_] = right; + assert!(&right[..right.len()] == &[3, 4, 5]); + } + for p in right { + *p += 2; + } + } + + assert_eq!(values, [2, 3, 5, 6, 7]); +} + +#[test] +fn test_clone() { + let v: Vec<i32> = vec![]; + let w = vec!(1, 2, 3); + + assert_eq!(v, v.clone()); + + let z = w.clone(); + assert_eq!(w, z); + // they should be disjoint in memory. + assert!(w.as_ptr() != z.as_ptr()) +} + +#[test] +fn test_clone_from() { + let mut v = vec!(); + let three: Vec<Box<_>> = vec!(box 1, box 2, box 3); + let two: Vec<Box<_>> = vec!(box 4, box 5); + // zero, long + v.clone_from(&three); + assert_eq!(v, three); + + // equal + v.clone_from(&three); + assert_eq!(v, three); + + // long, short + v.clone_from(&two); + assert_eq!(v, two); + + // short, long + v.clone_from(&three); + assert_eq!(v, three) +} + +#[test] +fn test_retain() { + let mut vec = vec![1, 2, 3, 4]; + vec.retain(|&x| x % 2 == 0); + assert_eq!(vec, [2, 4]); +} + +#[test] +fn zero_sized_values() { + let mut v = Vec::new(); + assert_eq!(v.len(), 0); + v.push(()); + assert_eq!(v.len(), 1); + v.push(()); + assert_eq!(v.len(), 2); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), None); + + assert_eq!(v.iter().count(), 0); + v.push(()); + assert_eq!(v.iter().count(), 1); + v.push(()); + assert_eq!(v.iter().count(), 2); + + for &() in &v {} + + assert_eq!(v.iter_mut().count(), 2); + v.push(()); + assert_eq!(v.iter_mut().count(), 3); + v.push(()); + assert_eq!(v.iter_mut().count(), 4); + + for &mut () in &mut v {} + unsafe { v.set_len(0); } + assert_eq!(v.iter_mut().count(), 0); +} + +#[test] +fn test_partition() { + assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3])); +} + +#[test] +fn test_zip_unzip() { + let z1 = vec![(1, 4), (2, 5), (3, 6)]; + + let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip(); + + assert_eq!((1, 4), (left[0], right[0])); + assert_eq!((2, 5), (left[1], right[1])); + assert_eq!((3, 6), (left[2], right[2])); +} + +#[test] +fn test_unsafe_ptrs() { + unsafe { + // Test on-stack copy-from-buf. + let a = [1, 2, 3]; + let ptr = a.as_ptr(); + let b = Vec::from_raw_buf(ptr, 3); + assert_eq!(b, [1, 2, 3]); + + // Test on-heap copy-from-buf. + let c = vec![1, 2, 3, 4, 5]; + let ptr = c.as_ptr(); + let d = Vec::from_raw_buf(ptr, 5); + assert_eq!(d, [1, 2, 3, 4, 5]); + } +} + +#[test] +fn test_vec_truncate_drop() { + static mut drops: u32 = 0; + struct Elem(i32); + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; + assert_eq!(unsafe { drops }, 0); + v.truncate(3); + assert_eq!(unsafe { drops }, 2); + v.truncate(0); + assert_eq!(unsafe { drops }, 5); +} + +#[test] +#[should_panic] +fn test_vec_truncate_fail() { + struct BadElem(i32); + impl Drop for BadElem { + fn drop(&mut self) { + let BadElem(ref mut x) = *self; + if *x == 0xbadbeef { + panic!("BadElem panic: 0xbadbeef") + } + } + } + + let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)]; + v.truncate(0); +} + +#[test] +fn test_index() { + let vec = vec![1, 2, 3]; + assert!(vec[1] == 2); +} + +#[test] +#[should_panic] +fn test_index_out_of_bounds() { + let vec = vec![1, 2, 3]; + let _ = vec[3]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_1() { + let x = vec![1, 2, 3, 4, 5]; + &x[-1..]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_2() { + let x = vec![1, 2, 3, 4, 5]; + &x[..6]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_3() { + let x = vec![1, 2, 3, 4, 5]; + &x[-1..4]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_4() { + let x = vec![1, 2, 3, 4, 5]; + &x[1..6]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_5() { + let x = vec![1, 2, 3, 4, 5]; + &x[3..2]; +} + +#[test] +#[should_panic] +fn test_swap_remove_empty() { + let mut vec= Vec::<i32>::new(); + vec.swap_remove(0); +} + +#[test] +fn test_move_iter_unwrap() { + let mut vec = Vec::with_capacity(7); + vec.push(1); + vec.push(2); + let ptr = vec.as_ptr(); + vec = vec.into_iter().into_inner(); + assert_eq!(vec.as_ptr(), ptr); + assert_eq!(vec.capacity(), 7); + assert_eq!(vec.len(), 0); +} + +#[test] +#[should_panic] +fn test_map_in_place_incompatible_types_fail() { + let v = vec![0, 1, 2]; + v.map_in_place(|_| ()); +} + +#[test] +fn test_map_in_place() { + let v = vec![0, 1, 2]; + assert_eq!(v.map_in_place(|i: u32| i as i32 - 1), [-1, 0, 1]); +} + +#[test] +fn test_map_in_place_zero_sized() { + let v = vec![(), ()]; + #[derive(PartialEq, Debug)] + struct ZeroSized; + assert_eq!(v.map_in_place(|_| ZeroSized), [ZeroSized, ZeroSized]); +} + +#[test] +fn test_map_in_place_zero_drop_count() { + use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; + + #[derive(Clone, PartialEq, Debug)] + struct Nothing; + impl Drop for Nothing { fn drop(&mut self) { } } + + #[derive(Clone, PartialEq, Debug)] + struct ZeroSized; + impl Drop for ZeroSized { + fn drop(&mut self) { + DROP_COUNTER.fetch_add(1, Ordering::Relaxed); + } + } + const NUM_ELEMENTS: usize = 2; + static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + + let v = repeat(Nothing).take(NUM_ELEMENTS).collect::<Vec<_>>(); + + DROP_COUNTER.store(0, Ordering::Relaxed); + + let v = v.map_in_place(|_| ZeroSized); + assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), 0); + drop(v); + assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), NUM_ELEMENTS); +} + +#[test] +fn test_move_items() { + let vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec { + vec2.push(i); + } + assert_eq!(vec2, [1, 2, 3]); +} + +#[test] +fn test_move_items_reverse() { + let vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.into_iter().rev() { + vec2.push(i); + } + assert_eq!(vec2, [3, 2, 1]); +} + +#[test] +fn test_move_items_zero_sized() { + let vec = vec![(), (), ()]; + let mut vec2 = vec![]; + for i in vec { + vec2.push(i); + } + assert_eq!(vec2, [(), (), ()]); +} + +#[test] +fn test_drain_items() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.drain() { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [ 1, 2, 3 ]); +} + +#[test] +fn test_drain_items_reverse() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.drain().rev() { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [3, 2, 1]); +} + +#[test] +fn test_drain_items_zero_sized() { + let mut vec = vec![(), (), ()]; + let mut vec2 = vec![]; + for i in vec.drain() { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [(), (), ()]); +} + +#[test] +fn test_into_boxed_slice() { + let xs = vec![1, 2, 3]; + let ys = xs.into_boxed_slice(); + assert_eq!(&*ys, [1, 2, 3]); +} + +#[test] +fn test_append() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![4, 5, 6]; + vec.append(&mut vec2); + assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + assert_eq!(vec2, []); +} + +#[test] +fn test_split_off() { + let mut vec = vec![1, 2, 3, 4, 5, 6]; + let vec2 = vec.split_off(4); + assert_eq!(vec, [1, 2, 3, 4]); + assert_eq!(vec2, [5, 6]); +} + +#[bench] +fn bench_new(b: &mut Bencher) { + b.iter(|| { + let v: Vec<u32> = Vec::new(); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), 0); + }) +} + +fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let v: Vec<u32> = Vec::with_capacity(src_len); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), src_len); + }) +} + +#[bench] +fn bench_with_capacity_0000(b: &mut Bencher) { + do_bench_with_capacity(b, 0) +} + +#[bench] +fn bench_with_capacity_0010(b: &mut Bencher) { + do_bench_with_capacity(b, 10) +} + +#[bench] +fn bench_with_capacity_0100(b: &mut Bencher) { + do_bench_with_capacity(b, 100) +} + +#[bench] +fn bench_with_capacity_1000(b: &mut Bencher) { + do_bench_with_capacity(b, 1000) +} + +fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let dst = (0..src_len).collect::<Vec<_>>(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }) +} + +#[bench] +fn bench_from_fn_0000(b: &mut Bencher) { + do_bench_from_fn(b, 0) +} + +#[bench] +fn bench_from_fn_0010(b: &mut Bencher) { + do_bench_from_fn(b, 10) +} + +#[bench] +fn bench_from_fn_0100(b: &mut Bencher) { + do_bench_from_fn(b, 100) +} + +#[bench] +fn bench_from_fn_1000(b: &mut Bencher) { + do_bench_from_fn(b, 1000) +} + +fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let dst: Vec<usize> = repeat(5).take(src_len).collect(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().all(|x| *x == 5)); + }) +} + +#[bench] +fn bench_from_elem_0000(b: &mut Bencher) { + do_bench_from_elem(b, 0) +} + +#[bench] +fn bench_from_elem_0010(b: &mut Bencher) { + do_bench_from_elem(b, 10) +} + +#[bench] +fn bench_from_elem_0100(b: &mut Bencher) { + do_bench_from_elem(b, 100) +} + +#[bench] +fn bench_from_elem_1000(b: &mut Bencher) { + do_bench_from_elem(b, 1000) +} + +fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst = src.clone()[..].to_vec(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_from_slice_0000(b: &mut Bencher) { + do_bench_from_slice(b, 0) +} + +#[bench] +fn bench_from_slice_0010(b: &mut Bencher) { + do_bench_from_slice(b, 10) +} + +#[bench] +fn bench_from_slice_0100(b: &mut Bencher) { + do_bench_from_slice(b, 100) +} + +#[bench] +fn bench_from_slice_1000(b: &mut Bencher) { + do_bench_from_slice(b, 1000) +} + +fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst: Vec<_> = FromIterator::from_iter(src.clone().into_iter()); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_from_iter_0000(b: &mut Bencher) { + do_bench_from_iter(b, 0) +} + +#[bench] +fn bench_from_iter_0010(b: &mut Bencher) { + do_bench_from_iter(b, 10) +} + +#[bench] +fn bench_from_iter_0100(b: &mut Bencher) { + do_bench_from_iter(b, 100) +} + +#[bench] +fn bench_from_iter_1000(b: &mut Bencher) { + do_bench_from_iter(b, 1000) +} + +fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend(src.clone().into_iter()); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_extend_0000_0000(b: &mut Bencher) { + do_bench_extend(b, 0, 0) +} + +#[bench] +fn bench_extend_0000_0010(b: &mut Bencher) { + do_bench_extend(b, 0, 10) +} + +#[bench] +fn bench_extend_0000_0100(b: &mut Bencher) { + do_bench_extend(b, 0, 100) +} + +#[bench] +fn bench_extend_0000_1000(b: &mut Bencher) { + do_bench_extend(b, 0, 1000) +} + +#[bench] +fn bench_extend_0010_0010(b: &mut Bencher) { + do_bench_extend(b, 10, 10) +} + +#[bench] +fn bench_extend_0100_0100(b: &mut Bencher) { + do_bench_extend(b, 100, 100) +} + +#[bench] +fn bench_extend_1000_1000(b: &mut Bencher) { + do_bench_extend(b, 1000, 1000) +} + +fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.push_all(&src); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_push_all_0000_0000(b: &mut Bencher) { + do_bench_push_all(b, 0, 0) +} + +#[bench] +fn bench_push_all_0000_0010(b: &mut Bencher) { + do_bench_push_all(b, 0, 10) +} + +#[bench] +fn bench_push_all_0000_0100(b: &mut Bencher) { + do_bench_push_all(b, 0, 100) +} + +#[bench] +fn bench_push_all_0000_1000(b: &mut Bencher) { + do_bench_push_all(b, 0, 1000) +} + +#[bench] +fn bench_push_all_0010_0010(b: &mut Bencher) { + do_bench_push_all(b, 10, 10) +} + +#[bench] +fn bench_push_all_0100_0100(b: &mut Bencher) { + do_bench_push_all(b, 100, 100) +} + +#[bench] +fn bench_push_all_1000_1000(b: &mut Bencher) { + do_bench_push_all(b, 1000, 1000) +} + +fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend(src.clone().into_iter()); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_push_all_move_0000_0000(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 0) +} + +#[bench] +fn bench_push_all_move_0000_0010(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 10) +} + +#[bench] +fn bench_push_all_move_0000_0100(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 100) +} + +#[bench] +fn bench_push_all_move_0000_1000(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 1000) +} + +#[bench] +fn bench_push_all_move_0010_0010(b: &mut Bencher) { + do_bench_push_all_move(b, 10, 10) +} + +#[bench] +fn bench_push_all_move_0100_0100(b: &mut Bencher) { + do_bench_push_all_move(b, 100, 100) +} + +#[bench] +fn bench_push_all_move_1000_1000(b: &mut Bencher) { + do_bench_push_all_move(b, 1000, 1000) +} + +fn do_bench_clone(b: &mut Bencher, src_len: usize) { + let src: Vec<usize> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst = src.clone(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_clone_0000(b: &mut Bencher) { + do_bench_clone(b, 0) +} + +#[bench] +fn bench_clone_0010(b: &mut Bencher) { + do_bench_clone(b, 10) +} + +#[bench] +fn bench_clone_0100(b: &mut Bencher) { + do_bench_clone(b, 100) +} + +#[bench] +fn bench_clone_1000(b: &mut Bencher) { + do_bench_clone(b, 1000) +} + +fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..src_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = (times * src_len) as u64; + + b.iter(|| { + let mut dst = dst.clone(); + + for _ in 0..times { + dst.clone_from(&src); + + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); + } + }); +} + +#[bench] +fn bench_clone_from_01_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 0) +} + +#[bench] +fn bench_clone_from_01_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 10) +} + +#[bench] +fn bench_clone_from_01_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 100) +} + +#[bench] +fn bench_clone_from_01_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 10) +} + +#[bench] +fn bench_clone_from_01_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 100) +} + +#[bench] +fn bench_clone_from_01_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 100) +} + +#[bench] +fn bench_clone_from_01_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 0) +} + +#[bench] +fn bench_clone_from_01_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 10) +} + +#[bench] +fn bench_clone_from_01_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 100) +} + +#[bench] +fn bench_clone_from_10_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 0) +} + +#[bench] +fn bench_clone_from_10_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 10) +} + +#[bench] +fn bench_clone_from_10_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 100) +} + +#[bench] +fn bench_clone_from_10_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 10) +} + +#[bench] +fn bench_clone_from_10_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 100) +} + +#[bench] +fn bench_clone_from_10_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 100) +} + +#[bench] +fn bench_clone_from_10_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 0) +} + +#[bench] +fn bench_clone_from_10_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 10) +} + +#[bench] +fn bench_clone_from_10_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 100) +} diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs new file mode 100644 index 00000000000..38f358c1505 --- /dev/null +++ b/src/libcollectionstest/vec_deque.rs @@ -0,0 +1,888 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::VecDeque; +use std::fmt::Debug; +use std::hash::{SipHasher, self}; + +use test; + +use self::Taggy::*; +use self::Taggypar::*; + +#[test] +#[allow(deprecated)] +fn test_simple() { + let mut d = VecDeque::new(); + assert_eq!(d.len(), 0); + d.push_front(17); + d.push_front(42); + d.push_back(137); + assert_eq!(d.len(), 3); + d.push_back(137); + assert_eq!(d.len(), 4); + assert_eq!(*d.front().unwrap(), 42); + assert_eq!(*d.back().unwrap(), 137); + let mut i = d.pop_front(); + assert_eq!(i, Some(42)); + i = d.pop_back(); + assert_eq!(i, Some(137)); + i = d.pop_back(); + assert_eq!(i, Some(137)); + i = d.pop_back(); + assert_eq!(i, Some(17)); + assert_eq!(d.len(), 0); + d.push_back(3); + assert_eq!(d.len(), 1); + d.push_front(2); + assert_eq!(d.len(), 2); + d.push_back(4); + assert_eq!(d.len(), 3); + d.push_front(1); + assert_eq!(d.len(), 4); + debug!("{}", d[0]); + debug!("{}", d[1]); + debug!("{}", d[2]); + debug!("{}", d[3]); + assert_eq!(d[0], 1); + assert_eq!(d[1], 2); + assert_eq!(d[2], 3); + assert_eq!(d[3], 4); +} + +#[cfg(test)] +fn test_parameterized<T:Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) { + let mut deq = VecDeque::new(); + assert_eq!(deq.len(), 0); + deq.push_front(a.clone()); + deq.push_front(b.clone()); + deq.push_back(c.clone()); + assert_eq!(deq.len(), 3); + deq.push_back(d.clone()); + assert_eq!(deq.len(), 4); + assert_eq!((*deq.front().unwrap()).clone(), b.clone()); + assert_eq!((*deq.back().unwrap()).clone(), d.clone()); + assert_eq!(deq.pop_front().unwrap(), b.clone()); + assert_eq!(deq.pop_back().unwrap(), d.clone()); + assert_eq!(deq.pop_back().unwrap(), c.clone()); + assert_eq!(deq.pop_back().unwrap(), a.clone()); + assert_eq!(deq.len(), 0); + deq.push_back(c.clone()); + assert_eq!(deq.len(), 1); + deq.push_front(b.clone()); + assert_eq!(deq.len(), 2); + deq.push_back(d.clone()); + assert_eq!(deq.len(), 3); + deq.push_front(a.clone()); + assert_eq!(deq.len(), 4); + assert_eq!(deq[0].clone(), a.clone()); + assert_eq!(deq[1].clone(), b.clone()); + assert_eq!(deq[2].clone(), c.clone()); + assert_eq!(deq[3].clone(), d.clone()); +} + +#[test] +fn test_push_front_grow() { + let mut deq = VecDeque::new(); + for i in 0..66 { + deq.push_front(i); + } + assert_eq!(deq.len(), 66); + + for i in 0..66 { + assert_eq!(deq[i], 65 - i); + } + + let mut deq = VecDeque::new(); + for i in 0..66 { + deq.push_back(i); + } + + for i in 0..66 { + assert_eq!(deq[i], i); + } +} + +#[test] +fn test_index() { + let mut deq = VecDeque::new(); + for i in 1..4 { + deq.push_front(i); + } + assert_eq!(deq[1], 2); +} + +#[test] +#[should_panic] +fn test_index_out_of_bounds() { + let mut deq = VecDeque::new(); + for i in 1..4 { + deq.push_front(i); + } + deq[3]; +} + +#[bench] +fn bench_new(b: &mut test::Bencher) { + b.iter(|| { + let ring: VecDeque<i32> = VecDeque::new(); + test::black_box(ring); + }) +} + +#[bench] +fn bench_grow_1025(b: &mut test::Bencher) { + b.iter(|| { + let mut deq = VecDeque::new(); + for i in 0..1025 { + deq.push_front(i); + } + test::black_box(deq); + }) +} + +#[bench] +fn bench_iter_1000(b: &mut test::Bencher) { + let ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for &i in &ring { + sum += i; + } + test::black_box(sum); + }) +} + +#[bench] +fn bench_mut_iter_1000(b: &mut test::Bencher) { + let mut ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for i in &mut ring { + sum += *i; + } + test::black_box(sum); + }) +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggy { + One(i32), + Two(i32, i32), + Three(i32, i32, i32), +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggypar<T> { + Onepar(T), + Twopar(T, T), + Threepar(T, T, T), +} + +#[derive(Clone, PartialEq, Debug)] +struct RecCy { + x: i32, + y: i32, + t: Taggy +} + +#[test] +fn test_param_int() { + test_parameterized::<i32>(5, 72, 64, 175); +} + +#[test] +fn test_param_taggy() { + test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); +} + +#[test] +fn test_param_taggypar() { + test_parameterized::<Taggypar<i32>>(Onepar::<i32>(1), + Twopar::<i32>(1, 2), + Threepar::<i32>(1, 2, 3), + Twopar::<i32>(17, 42)); +} + +#[test] +fn test_param_reccy() { + let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; + let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; + let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; + let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; + test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4); +} + +#[test] +fn test_with_capacity() { + let mut d = VecDeque::with_capacity(0); + d.push_back(1); + assert_eq!(d.len(), 1); + let mut d = VecDeque::with_capacity(50); + d.push_back(1); + assert_eq!(d.len(), 1); +} + +#[test] +fn test_with_capacity_non_power_two() { + let mut d3 = VecDeque::with_capacity(3); + d3.push_back(1); + + // X = None, | = lo + // [|1, X, X] + assert_eq!(d3.pop_front(), Some(1)); + // [X, |X, X] + assert_eq!(d3.front(), None); + + // [X, |3, X] + d3.push_back(3); + // [X, |3, 6] + d3.push_back(6); + // [X, X, |6] + assert_eq!(d3.pop_front(), Some(3)); + + // Pushing the lo past half way point to trigger + // the 'B' scenario for growth + // [9, X, |6] + d3.push_back(9); + // [9, 12, |6] + d3.push_back(12); + + d3.push_back(15); + // There used to be a bug here about how the + // VecDeque made growth assumptions about the + // underlying Vec which didn't hold and lead + // to corruption. + // (Vec grows to next power of two) + //good- [9, 12, 15, X, X, X, X, |6] + //bug- [15, 12, X, X, X, |6, X, X] + assert_eq!(d3.pop_front(), Some(6)); + + // Which leads us to the following state which + // would be a failure case. + //bug- [15, 12, X, X, X, X, |X, X] + assert_eq!(d3.front(), Some(&9)); +} + +#[test] +fn test_reserve_exact() { + let mut d = VecDeque::new(); + d.push_back(0); + d.reserve_exact(50); + assert!(d.capacity() >= 51); +} + +#[test] +fn test_reserve() { + let mut d = VecDeque::new(); + d.push_back(0); + d.reserve(50); + assert!(d.capacity() >= 51); +} + +#[test] +fn test_swap() { + let mut d: VecDeque<_> = (0..5).collect(); + d.pop_front(); + d.swap(0, 3); + assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]); +} + +#[test] +fn test_iter() { + let mut d = VecDeque::new(); + assert_eq!(d.iter().next(), None); + assert_eq!(d.iter().size_hint(), (0, Some(0))); + + for i in 0..5 { + d.push_back(i); + } + { + let b: &[_] = &[&0,&1,&2,&3,&4]; + assert_eq!(d.iter().collect::<Vec<_>>(), b); + } + + for i in 6..9 { + d.push_front(i); + } + { + let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4]; + assert_eq!(d.iter().collect::<Vec<_>>(), b); + } + + let mut it = d.iter(); + let mut len = d.len(); + loop { + match it.next() { + None => break, + _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) } + } + } +} + +#[test] +fn test_rev_iter() { + let mut d = VecDeque::new(); + assert_eq!(d.iter().rev().next(), None); + + for i in 0..5 { + d.push_back(i); + } + { + let b: &[_] = &[&4,&3,&2,&1,&0]; + assert_eq!(d.iter().rev().collect::<Vec<_>>(), b); + } + + for i in 6..9 { + d.push_front(i); + } + let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8]; + assert_eq!(d.iter().rev().collect::<Vec<_>>(), b); +} + +#[test] +fn test_mut_rev_iter_wrap() { + let mut d = VecDeque::with_capacity(3); + assert!(d.iter_mut().rev().next().is_none()); + + d.push_back(1); + d.push_back(2); + d.push_back(3); + assert_eq!(d.pop_front(), Some(1)); + d.push_back(4); + + assert_eq!(d.iter_mut().rev().cloned().collect::<Vec<_>>(), + vec![4, 3, 2]); +} + +#[test] +fn test_mut_iter() { + let mut d = VecDeque::new(); + assert!(d.iter_mut().next().is_none()); + + for i in 0..3 { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().enumerate() { + assert_eq!(*elt, 2 - i); + *elt = i; + } + + { + let mut it = d.iter_mut(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } +} + +#[test] +fn test_mut_rev_iter() { + let mut d = VecDeque::new(); + assert!(d.iter_mut().rev().next().is_none()); + + for i in 0..3 { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().rev().enumerate() { + assert_eq!(*elt, i); + *elt = i; + } + + { + let mut it = d.iter_mut().rev(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } +} + +#[test] +fn test_into_iter() { + + // Empty iter + { + let d: VecDeque<i32> = VecDeque::new(); + let mut iter = d.into_iter(); + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + // simple iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + + let b = vec![0,1,2,3,4]; + assert_eq!(d.into_iter().collect::<Vec<_>>(), b); + } + + // wrapped iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + let b = vec![8,7,6,0,1,2,3,4]; + assert_eq!(d.into_iter().collect::<Vec<_>>(), b); + } + + // partially used + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + let mut it = d.into_iter(); + assert_eq!(it.size_hint(), (8, Some(8))); + assert_eq!(it.next(), Some(8)); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.next_back(), Some(4)); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.size_hint(), (5, Some(5))); + } +} + +#[test] +fn test_drain() { + + // Empty iter + { + let mut d: VecDeque<i32> = VecDeque::new(); + + { + let mut iter = d.drain(); + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert!(d.is_empty()); + } + + // simple iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + + assert_eq!(d.drain().collect::<Vec<_>>(), [0, 1, 2, 3, 4]); + assert!(d.is_empty()); + } + + // wrapped iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + assert_eq!(d.drain().collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]); + assert!(d.is_empty()); + } + + // partially used + { + let mut d: VecDeque<_> = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + { + let mut it = d.drain(); + assert_eq!(it.size_hint(), (8, Some(8))); + assert_eq!(it.next(), Some(8)); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.next_back(), Some(4)); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.size_hint(), (5, Some(5))); + } + assert!(d.is_empty()); + } +} + +#[test] +fn test_from_iter() { + use std::iter; + + let v = vec!(1,2,3,4,5,6,7); + let deq: VecDeque<_> = v.iter().cloned().collect(); + let u: Vec<_> = deq.iter().cloned().collect(); + assert_eq!(u, v); + + let seq = iter::count(0, 2).take(256); + let deq: VecDeque<_> = seq.collect(); + for (i, &x) in deq.iter().enumerate() { + assert_eq!(2*i, x); + } + assert_eq!(deq.len(), 256); +} + +#[test] +fn test_clone() { + let mut d = VecDeque::new(); + d.push_front(17); + d.push_front(42); + d.push_back(137); + d.push_back(137); + assert_eq!(d.len(), 4); + let mut e = d.clone(); + assert_eq!(e.len(), 4); + while !d.is_empty() { + assert_eq!(d.pop_back(), e.pop_back()); + } + assert_eq!(d.len(), 0); + assert_eq!(e.len(), 0); +} + +#[test] +fn test_eq() { + let mut d = VecDeque::new(); + assert!(d == VecDeque::with_capacity(0)); + d.push_front(137); + d.push_front(17); + d.push_front(42); + d.push_back(137); + let mut e = VecDeque::with_capacity(0); + e.push_back(42); + e.push_back(17); + e.push_back(137); + e.push_back(137); + assert!(&e == &d); + e.pop_back(); + e.push_back(0); + assert!(e != d); + e.clear(); + assert!(e == VecDeque::new()); +} + +#[test] +fn test_hash() { + let mut x = VecDeque::new(); + let mut y = VecDeque::new(); + + x.push_back(1); + x.push_back(2); + x.push_back(3); + + y.push_back(0); + y.push_back(1); + y.pop_front(); + y.push_back(2); + y.push_back(3); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +#[test] +fn test_ord() { + let x = VecDeque::new(); + let mut y = VecDeque::new(); + y.push_back(1); + y.push_back(2); + y.push_back(3); + assert!(x < y); + assert!(y > x); + assert!(x <= x); + assert!(x >= x); +} + +#[test] +fn test_show() { + let ringbuf: VecDeque<_> = (0..10).collect(); + assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter() + .cloned() + .collect(); + assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[test] +fn test_drop() { + static mut drops: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + drop(ring); + + assert_eq!(unsafe {drops}, 4); +} + +#[test] +fn test_drop_with_pop() { + static mut drops: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + + drop(ring.pop_back()); + drop(ring.pop_front()); + assert_eq!(unsafe {drops}, 2); + + drop(ring); + assert_eq!(unsafe {drops}, 4); +} + +#[test] +fn test_drop_clear() { + static mut drops: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + ring.clear(); + assert_eq!(unsafe {drops}, 4); + + drop(ring); + assert_eq!(unsafe {drops}, 4); +} + +#[test] +fn test_reserve_grow() { + // test growth path A + // [T o o H] -> [T o o H . . . . ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } + + // test growth path B + // [H T o o] -> [. T o o H . . . ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..1 { + ring.push_back(i); + assert_eq!(ring.pop_front(), Some(i)); + } + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } + + // test growth path C + // [o o H T] -> [o o H . . . . T ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..3 { + ring.push_back(i); + assert_eq!(ring.pop_front(), Some(i)); + } + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } +} + +#[test] +fn test_get() { + let mut ring = VecDeque::new(); + ring.push_back(0); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), None); + + ring.push_back(1); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), Some(&1)); + assert_eq!(ring.get(2), None); + + ring.push_back(2); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), Some(&1)); + assert_eq!(ring.get(2), Some(&2)); + assert_eq!(ring.get(3), None); + + assert_eq!(ring.pop_front(), Some(0)); + assert_eq!(ring.get(0), Some(&1)); + assert_eq!(ring.get(1), Some(&2)); + assert_eq!(ring.get(2), None); + + assert_eq!(ring.pop_front(), Some(1)); + assert_eq!(ring.get(0), Some(&2)); + assert_eq!(ring.get(1), None); + + assert_eq!(ring.pop_front(), Some(2)); + assert_eq!(ring.get(0), None); + assert_eq!(ring.get(1), None); +} + +#[test] +fn test_get_mut() { + let mut ring = VecDeque::new(); + for i in 0..3 { + ring.push_back(i); + } + + match ring.get_mut(1) { + Some(x) => *x = -1, + None => () + }; + + assert_eq!(ring.get_mut(0), Some(&mut 0)); + assert_eq!(ring.get_mut(1), Some(&mut -1)); + assert_eq!(ring.get_mut(2), Some(&mut 2)); + assert_eq!(ring.get_mut(3), None); + + assert_eq!(ring.pop_front(), Some(0)); + assert_eq!(ring.get_mut(0), Some(&mut -1)); + assert_eq!(ring.get_mut(1), Some(&mut 2)); + assert_eq!(ring.get_mut(2), None); +} + +#[test] +fn test_front() { + let mut ring = VecDeque::new(); + ring.push_back(10); + ring.push_back(20); + assert_eq!(ring.front(), Some(&10)); + ring.pop_front(); + assert_eq!(ring.front(), Some(&20)); + ring.pop_front(); + assert_eq!(ring.front(), None); +} + +#[test] +fn test_as_slices() { + let mut ring: VecDeque<i32> = VecDeque::with_capacity(127); + let cap = ring.capacity() as i32; + let first = cap/2; + let last = cap - first; + for i in 0..first { + ring.push_back(i); + + let (left, right) = ring.as_slices(); + let expected: Vec<_> = (0..i+1).collect(); + assert_eq!(left, expected); + assert_eq!(right, []); + } + + for j in -last..0 { + ring.push_front(j); + let (left, right) = ring.as_slices(); + let expected_left: Vec<_> = (-last..j+1).rev().collect(); + let expected_right: Vec<_> = (0..first).collect(); + assert_eq!(left, expected_left); + assert_eq!(right, expected_right); + } + + assert_eq!(ring.len() as i32, cap); + assert_eq!(ring.capacity() as i32, cap); +} + +#[test] +fn test_as_mut_slices() { + let mut ring: VecDeque<i32> = VecDeque::with_capacity(127); + let cap = ring.capacity() as i32; + let first = cap/2; + let last = cap - first; + for i in 0..first { + ring.push_back(i); + + let (left, right) = ring.as_mut_slices(); + let expected: Vec<_> = (0..i+1).collect(); + assert_eq!(left, expected); + assert_eq!(right, []); + } + + for j in -last..0 { + ring.push_front(j); + let (left, right) = ring.as_mut_slices(); + let expected_left: Vec<_> = (-last..j+1).rev().collect(); + let expected_right: Vec<_> = (0..first).collect(); + assert_eq!(left, expected_left); + assert_eq!(right, expected_right); + } + + assert_eq!(ring.len() as i32, cap); + assert_eq!(ring.capacity() as i32, cap); +} + +#[test] +fn test_append() { + let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect(); + + // normal append + a.append(&mut b); + assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []); + + // append nothing to something + a.append(&mut b); + assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []); + + // append something to nothing + b.append(&mut a); + assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []); +} diff --git a/src/libcollectionstest/vec_map.rs b/src/libcollectionstest/vec_map.rs new file mode 100644 index 00000000000..112b4c03e20 --- /dev/null +++ b/src/libcollectionstest/vec_map.rs @@ -0,0 +1,510 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::VecMap; +use std::collections::vec_map::Entry::{Occupied, Vacant}; +use std::hash::{SipHasher, hash}; + +#[test] +fn test_get_mut() { + let mut m = VecMap::new(); + assert!(m.insert(1, 12).is_none()); + assert!(m.insert(2, 8).is_none()); + assert!(m.insert(5, 14).is_none()); + let new = 100; + match m.get_mut(&5) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.get(&5), Some(&new)); +} + +#[test] +fn test_len() { + let mut map = VecMap::new(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert!(map.insert(5, 20).is_none()); + assert_eq!(map.len(), 1); + assert!(!map.is_empty()); + assert!(map.insert(11, 12).is_none()); + assert_eq!(map.len(), 2); + assert!(!map.is_empty()); + assert!(map.insert(14, 22).is_none()); + assert_eq!(map.len(), 3); + assert!(!map.is_empty()); +} + +#[test] +fn test_clear() { + let mut map = VecMap::new(); + assert!(map.insert(5, 20).is_none()); + assert!(map.insert(11, 12).is_none()); + assert!(map.insert(14, 22).is_none()); + map.clear(); + assert!(map.is_empty()); + assert!(map.get(&5).is_none()); + assert!(map.get(&11).is_none()); + assert!(map.get(&14).is_none()); +} + +#[test] +fn test_insert() { + let mut m = VecMap::new(); + assert_eq!(m.insert(1, 2), None); + assert_eq!(m.insert(1, 3), Some(2)); + assert_eq!(m.insert(1, 4), Some(3)); +} + +#[test] +fn test_remove() { + let mut m = VecMap::new(); + m.insert(1, 2); + assert_eq!(m.remove(&1), Some(2)); + assert_eq!(m.remove(&1), None); +} + +#[test] +fn test_keys() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let keys: Vec<_> = map.keys().collect(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); +} + +#[test] +fn test_values() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let values: Vec<_> = map.values().cloned().collect(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); +} + +#[test] +fn test_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + let mut it = m.iter(); + assert_eq!(it.size_hint(), (0, Some(11))); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.size_hint(), (0, Some(10))); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.size_hint(), (0, Some(9))); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.size_hint(), (0, Some(7))); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.size_hint(), (0, Some(4))); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_size_hints() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + assert_eq!(m.iter().size_hint(), (0, Some(11))); + assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); +} + +#[test] +fn test_mut_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + for (k, v) in &mut m { + *v += k as isize; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); +} + +#[test] +fn test_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + let mut it = m.iter().rev(); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.next().unwrap(), (0, &1)); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + for (k, v) in m.iter_mut().rev() { + *v += k as isize; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); +} + +#[test] +fn test_move_iter() { + let mut m: VecMap<Box<_>> = VecMap::new(); + m.insert(1, box 2); + let mut called = false; + for (k, v) in m { + assert!(!called); + called = true; + assert_eq!(k, 1); + assert_eq!(v, box 2); + } + assert!(called); +} + +#[test] +fn test_drain_iterator() { + let mut map = VecMap::new(); + map.insert(1, "a"); + map.insert(3, "c"); + map.insert(2, "b"); + + let vec: Vec<_> = map.drain().collect(); + + assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); + assert_eq!(map.len(), 0); +} + +#[test] +fn test_append() { + let mut a = VecMap::new(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + + let mut b = VecMap::new(); + b.insert(3, "d"); // Overwrite element from a + b.insert(4, "e"); + b.insert(5, "f"); + + a.append(&mut b); + + assert_eq!(a.len(), 5); + assert_eq!(b.len(), 0); + // Capacity shouldn't change for possible reuse + assert!(b.capacity() >= 4); + + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + assert_eq!(a[3], "d"); + assert_eq!(a[4], "e"); + assert_eq!(a[5], "f"); +} + +#[test] +fn test_split_off() { + // Split within the key range + let mut a = VecMap::new(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(3); + + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); + + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + + assert_eq!(b[3], "c"); + assert_eq!(b[4], "d"); + + // Split at 0 + a.clear(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(0); + + assert_eq!(a.len(), 0); + assert_eq!(b.len(), 4); + assert_eq!(b[1], "a"); + assert_eq!(b[2], "b"); + assert_eq!(b[3], "c"); + assert_eq!(b[4], "d"); + + // Split behind max_key + a.clear(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(5); + + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 0); + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + assert_eq!(a[3], "c"); + assert_eq!(a[4], "d"); +} + +#[test] +fn test_show() { + let mut map = VecMap::new(); + let empty = VecMap::<i32>::new(); + + map.insert(1, 2); + map.insert(3, 4); + + let map_str = format!("{:?}", map); + assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); + assert_eq!(format!("{:?}", empty), "{}"); +} + +#[test] +fn test_clone() { + let mut a = VecMap::new(); + + a.insert(1, 'x'); + a.insert(4, 'y'); + a.insert(6, 'z'); + + assert!(a.clone() == a); +} + +#[test] +fn test_eq() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a == b); + assert!(a.insert(0, 5).is_none()); + assert!(a != b); + assert!(b.insert(0, 4).is_none()); + assert!(a != b); + assert!(a.insert(5, 19).is_none()); + assert!(a != b); + assert!(!b.insert(0, 5).is_none()); + assert!(a != b); + assert!(b.insert(5, 19).is_none()); + assert!(a == b); + + a = VecMap::new(); + b = VecMap::with_capacity(1); + assert!(a == b); +} + +#[test] +fn test_lt() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(2, 5).is_none()); + assert!(a < b); + assert!(a.insert(2, 7).is_none()); + assert!(!(a < b) && b < a); + assert!(b.insert(1, 0).is_none()); + assert!(b < a); + assert!(a.insert(0, 6).is_none()); + assert!(a < b); + assert!(a.insert(6, 2).is_none()); + assert!(a < b && !(b < a)); +} + +#[test] +fn test_ord() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1, 1).is_none()); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2, 2).is_none()); + assert!(b > a && b >= a); + assert!(a < b && a <= b); +} + +#[test] +fn test_hash() { + let mut x = VecMap::new(); + let mut y = VecMap::new(); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); + x.insert(1, 'a'); + x.insert(2, 'b'); + x.insert(3, 'c'); + + y.insert(3, 'c'); + y.insert(2, 'b'); + y.insert(1, 'a'); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); + + x.insert(1000, 'd'); + x.remove(&1000); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); +} + +#[test] +fn test_from_iter() { + let xs = vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; + + let map: VecMap<_> = xs.iter().cloned().collect(); + + for &(k, v) in &xs { + assert_eq!(map.get(&k), Some(&v)); + } +} + +#[test] +fn test_index() { + let mut map = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + assert_eq!(map[3], 4); +} + +#[test] +#[should_panic] +fn test_index_nonexistent() { + let mut map = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + map[4]; +} + +#[test] +fn test_entry(){ + let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map: VecMap<_> = xs.iter().cloned().collect(); + + // Existing key (insert) + match map.entry(1) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.insert(100), 10); + } + } + assert_eq!(map.get(&1).unwrap(), &100); + assert_eq!(map.len(), 6); + + + // Existing key (update) + match map.entry(2) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + let v = view.get_mut(); + *v *= 10; + } + } + assert_eq!(map.get(&2).unwrap(), &200); + assert_eq!(map.len(), 6); + + // Existing key (take) + match map.entry(3) { + Vacant(_) => unreachable!(), + Occupied(view) => { + assert_eq!(view.remove(), 30); + } + } + assert_eq!(map.get(&3), None); + assert_eq!(map.len(), 5); + + + // Inexistent key (insert) + match map.entry(10) { + Occupied(_) => unreachable!(), + Vacant(view) => { + assert_eq!(*view.insert(1000), 1000); + } + } + assert_eq!(map.get(&10).unwrap(), &1000); + assert_eq!(map.len(), 6); +} + +mod bench { + use std::collections::VecMap; + + map_insert_rand_bench!{insert_rand_100, 100, VecMap} + map_insert_rand_bench!{insert_rand_10_000, 10_000, VecMap} + + map_insert_seq_bench!{insert_seq_100, 100, VecMap} + map_insert_seq_bench!{insert_seq_10_000, 10_000, VecMap} + + map_find_rand_bench!{find_rand_100, 100, VecMap} + map_find_rand_bench!{find_rand_10_000, 10_000, VecMap} + + map_find_seq_bench!{find_seq_100, 100, VecMap} + map_find_seq_bench!{find_seq_10_000, 10_000, VecMap} +} diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 237dbe492ba..8ebedb66851 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -65,7 +65,7 @@ use default::Default; use marker; use mem; use num::{ToPrimitive, Int}; -use ops::{Add, Deref, FnMut}; +use ops::{Add, Deref, FnMut, RangeFrom}; use option::Option; use option::Option::{Some, None}; use marker::Sized; @@ -2366,34 +2366,101 @@ impl<A, St, F> Iterator for Unfold<St, F> where F: FnMut(&mut St) -> Option<A> { } } +/// An adapter for stepping range iterators by a custom amount. +/// +/// The resulting iterator handles overflow by stopping. The `A` +/// parameter is the type being iterated over, while `R` is the range +/// type (usually one of `std::ops::{Range, RangeFrom}`. +#[derive(Clone)] +#[unstable(feature = "step_by", reason = "recent addition")] +pub struct StepBy<A, R> { + step_by: A, + range: R, +} + +impl<A: Add> RangeFrom<A> { + /// Creates an iterator starting at the same point, but stepping by + /// the given amount at each iteration. + /// + /// # Examples + /// + /// ```ignore + /// for i in (0u8..).step_by(2) { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints all even `u8` values. + #[unstable(feature = "step_by", reason = "recent addition")] + pub fn step_by(self, by: A) -> StepBy<A, Self> { + StepBy { + step_by: by, + range: self + } + } +} + +impl<A: Int> ::ops::Range<A> { + /// Creates an iterator with the same range, but stepping by the + /// given amount at each iteration. + /// + /// The resulting iterator handles overflow by stopping. + /// + /// # Examples + /// + /// ``` + /// # #![feature(step_by, core)] + /// for i in (0..10).step_by(2) { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// 0 + /// 2 + /// 4 + /// 6 + /// 8 + /// ``` + #[unstable(feature = "step_by", reason = "recent addition")] + pub fn step_by(self, by: A) -> StepBy<A, Self> { + StepBy { + step_by: by, + range: self + } + } +} + /// An infinite iterator starting at `start` and advancing by `step` with each /// iteration -#[derive(Clone)] #[unstable(feature = "core", reason = "may be renamed or replaced by range notation adapters")] -pub struct Counter<A> { - /// The current state the counter is at (next value to be yielded) - state: A, - /// The amount that this iterator is stepping by - step: A, -} +#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")] +pub type Counter<A> = StepBy<A, RangeFrom<A>>; -/// Creates a new counter with the specified start/step +/// Deprecated: use `(start..).step_by(step)` instead. #[inline] #[unstable(feature = "core", reason = "may be renamed or replaced by range notation adapters")] +#[deprecated(since = "1.0.0-beta", reason = "use (start..).step_by(step) instead")] +#[allow(deprecated)] pub fn count<A>(start: A, step: A) -> Counter<A> { - Counter{state: start, step: step} + StepBy { + range: RangeFrom { start: start }, + step_by: step, + } } #[stable(feature = "rust1", since = "1.0.0")] -impl<A: Add<Output=A> + Clone> Iterator for Counter<A> { +impl<A: Add<Output=A> + Clone> Iterator for StepBy<A, RangeFrom<A>> { type Item = A; #[inline] fn next(&mut self) -> Option<A> { - let result = self.state.clone(); - self.state = self.state.clone() + self.step.clone(); + let result = self.range.start.clone(); + self.range.start = result.clone() + self.step_by.clone(); Some(result) } @@ -2404,31 +2471,22 @@ impl<A: Add<Output=A> + Clone> Iterator for Counter<A> { } /// An iterator over the range [start, stop) +#[allow(deprecated)] #[derive(Clone)] #[unstable(feature = "core", reason = "will be replaced by range notation")] +#[deprecated(since = "1.0.0-beta", reason = "use range notation")] pub struct Range<A> { state: A, stop: A, one: A, } -/// Returns an iterator over the given range [start, stop) (that is, starting -/// at start (inclusive), and ending at stop (exclusive)). -/// -/// # Examples -/// -/// ``` -/// let array = [0, 1, 2, 3, 4]; -/// -/// for i in range(0, 5) { -/// println!("{}", i); -/// assert_eq!(i, array[i]); -/// } -/// ``` +/// Deprecated: use `(start..stop)` instead. #[inline] -#[unstable(feature = "core", - reason = "will be replaced by range notation")] +#[unstable(feature = "core", reason = "will be replaced by range notation")] +#[deprecated(since = "1.0.0-beta", reason = "use (start..stop) instead")] +#[allow(deprecated)] pub fn range<A: Int>(start: A, stop: A) -> Range<A> { Range { state: start, @@ -2440,6 +2498,8 @@ pub fn range<A: Int>(start: A, stop: A) -> Range<A> { // FIXME: #10414: Unfortunate type bound #[unstable(feature = "core", reason = "will be replaced by range notation")] +#[deprecated(since = "1.0.0-beta", reason = "use range notation")] +#[allow(deprecated)] impl<A: Int + ToPrimitive> Iterator for Range<A> { type Item = A; @@ -2491,6 +2551,8 @@ impl<A: Int + ToPrimitive> Iterator for Range<A> { /// the direction it is consumed. #[unstable(feature = "core", reason = "will be replaced by range notation")] +#[deprecated(since = "1.0.0-beta", reason = "use range notation")] +#[allow(deprecated)] impl<A: Int + ToPrimitive> DoubleEndedIterator for Range<A> { #[inline] fn next_back(&mut self) -> Option<A> { @@ -2507,6 +2569,7 @@ impl<A: Int + ToPrimitive> DoubleEndedIterator for Range<A> { #[derive(Clone)] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] +#[allow(deprecated)] pub struct RangeInclusive<A> { range: Range<A>, done: bool, @@ -2516,6 +2579,7 @@ pub struct RangeInclusive<A> { #[inline] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] +#[allow(deprecated)] pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> { RangeInclusive { range: range(start, stop), @@ -2525,6 +2589,7 @@ pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] +#[allow(deprecated)] impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> { type Item = A; @@ -2561,6 +2626,7 @@ impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] +#[allow(deprecated)] impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> { #[inline] fn next_back(&mut self) -> Option<A> { @@ -2578,61 +2644,39 @@ impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> { } /// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[derive(Clone)] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -pub struct RangeStep<A> { - state: A, - stop: A, - step: A, - rev: bool, -} +#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")] +pub type RangeStep<A> = StepBy<A, ::ops::Range<A>>; -/// Return an iterator over the range [start, stop) by `step`. -/// -/// It handles overflow by stopping. -/// -/// # Examples -/// -/// ``` -/// use std::iter::range_step; -/// -/// for i in range_step(0, 10, 2) { -/// println!("{}", i); -/// } -/// ``` -/// -/// This prints: -/// -/// ```text -/// 0 -/// 2 -/// 4 -/// 6 -/// 8 -/// ``` +/// Deprecated: use `(start..stop).step_by(step)` instead. #[inline] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] +#[deprecated(since = "1.0.0-beta", + reason = "use `(start..stop).step_by(step)` instead")] +#[allow(deprecated)] pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> { - let rev = step < Int::zero(); - RangeStep{state: start, stop: stop, step: step, rev: rev} + StepBy { + step_by: step, + range: ::ops::Range { start: start, end: stop }, + } } -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -impl<A: Int> Iterator for RangeStep<A> { +#[stable(feature = "rust1", since = "1.0.0")] +impl<A: Int> Iterator for StepBy<A, ::ops::Range<A>> { type Item = A; #[inline] fn next(&mut self) -> Option<A> { - if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) { - let result = self.state; - match self.state.checked_add(self.step) { - Some(x) => self.state = x, - None => self.state = self.stop.clone() + let rev = self.step_by < Int::zero(); + let start = self.range.start; + if (rev && start > self.range.end) || (!rev && start < self.range.end) { + match start.checked_add(self.step_by) { + Some(x) => self.range.start = x, + None => self.range.start = self.range.end.clone() } - Some(result) + Some(start) } else { None } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 18e20c02a1b..a77f9709600 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -708,6 +708,7 @@ signed_int_impl! { i32 } signed_int_impl! { i64 } signed_int_impl! { int } +#[cfg(stage0)] /// A built-in unsigned integer. #[stable(feature = "rust1", since = "1.0.0")] pub trait UnsignedInt: Int + WrappingOps { @@ -742,21 +743,1010 @@ pub trait UnsignedInt: Int + WrappingOps { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for uint {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u8 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u16 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u32 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u64 {} +// NB(japaric) I added this module to avoid adding several `cfg(not(stage0))`, and avoid name +// clashes between macros. We should move all the items inside this module into the outer scope +// once the `Int` trait is removed +#[cfg(not(stage0))] +mod inherent { + use intrinsics; + use mem::size_of; + use option::Option::{self, Some, None}; + + use super::wrapping::{OverflowingOps, WrappingOps}; + + // `Int` + `SignedInt` implemented for signed integers + macro_rules! int_impl { + ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr, + $add_with_overflow:path, + $sub_with_overflow:path, + $mul_with_overflow:path) => { + /// Returns the `0` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> $T { 0 } + + /// Returns the `1` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> $T { 1 } + + /// Returns the smallest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn min_value() -> $T { (-1 as $T) << ($BITS - 1) } + + /// Returns the largest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn max_value() -> $T { let min: $T = <$T>::min_value(); !min } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn leading_zeros(self) -> u32 { (self as $UnsignedT).leading_zeros() } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn trailing_zeros(self) -> u32 { (self as $UnsignedT).trailing_zeros() } + + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { (self as $UnsignedT).rotate_left(n) as $T } + + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { (self as $UnsignedT).rotate_right(n) as $T } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { (self as $UnsignedT).swap_bytes() as $T } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning `None` + /// if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` if + /// `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_div(-1), Some(127)); + /// assert_eq!((-128i8).checked_div(-1), None); + /// assert_eq!((1i8).checked_div(0), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + -1 if self == <$T>::min_value() + => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Computes the absolute value of `self`. `Int::min_value()` will be + /// returned if the number is `Int::min_value()`. + #[unstable(feature = "core", reason = "overflow in debug builds?")] + #[inline] + pub fn abs(self) -> $T { + if self.is_negative() { -self } else { self } + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> $T { + match self { + n if n > 0 => 1, + 0 => 0, + _ => -1, + } + } + + /// Returns `true` if `self` is positive and `false` if the number + /// is zero or negative. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { self > 0 } + + /// Returns `true` if `self` is negative and `false` if the number + /// is zero or positive. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { self < 0 } + } + } + + #[lang = "i8"] + impl i8 { + int_impl! { i8 = i8, u8, 8, + intrinsics::i8_add_with_overflow, + intrinsics::i8_sub_with_overflow, + intrinsics::i8_mul_with_overflow } + } + + #[lang = "i16"] + impl i16 { + int_impl! { i16 = i16, u16, 16, + intrinsics::i16_add_with_overflow, + intrinsics::i16_sub_with_overflow, + intrinsics::i16_mul_with_overflow } + } + + #[lang = "i32"] + impl i32 { + int_impl! { i32 = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } + } + + #[lang = "i64"] + impl i64 { + int_impl! { i64 = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } + } + + #[cfg(target_pointer_width = "32")] + #[lang = "isize"] + impl isize { + int_impl! { int = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } + } + + #[cfg(target_pointer_width = "64")] + #[lang = "isize"] + impl isize { + int_impl! { int = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } + } + + // `Int` + `UnsignedInt` implemented for signed integers + macro_rules! uint_impl { + ($T:ty = $ActualT:ty, $BITS:expr, + $ctpop:path, + $ctlz:path, + $cttz:path, + $bswap:path, + $add_with_overflow:path, + $sub_with_overflow:path, + $mul_with_overflow:path) => { + /// Returns the `0` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> $T { 0 } + + /// Returns the `1` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> $T { 1 } + + /// Returns the smallest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn min_value() -> $T { 0 } + + /// Returns the largest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn max_value() -> $T { -1 } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_ones(self) -> u32 { unsafe { $ctpop(self as $ActualT) as u32 } } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn leading_zeros(self) -> u32 { unsafe { $ctlz(self as $ActualT) as u32 } } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn trailing_zeros(self) -> u32 { unsafe { $cttz(self as $ActualT) as u32 } } + + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> (($BITS - n) % $BITS)) + } + + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << (($BITS - n) % $BITS)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { unsafe { $bswap(self as $ActualT) as $T } } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning `None` + /// if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` if + /// `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_div(-1), Some(127)); + /// assert_eq!((-128i8).checked_div(-1), None); + /// assert_eq!((1i8).checked_div(0), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Returns `true` iff `self == 2^k` for some `k`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_power_of_two(self) -> bool { + (self.wrapping_sub(<$T>::one())) & self == <$T>::zero() && !(self == <$T>::zero()) + } + + /// Returns the smallest power of two greater than or equal to `self`. + /// Unspecified behavior on overflow. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn next_power_of_two(self) -> $T { + let bits = size_of::<$T>() * 8; + let one: $T = <$T>::one(); + one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits) + } + + /// Returns the smallest power of two greater than or equal to `n`. If the + /// next power of two is greater than the type's maximum value, `None` is + /// returned, otherwise the power of two is wrapped in `Some`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn checked_next_power_of_two(self) -> Option<$T> { + let npot = self.next_power_of_two(); + if npot >= self { + Some(npot) + } else { + None + } + } + } + } + + /// Swapping a single byte is a no-op. This is marked as `unsafe` for + /// consistency with the other `bswap` intrinsics. + unsafe fn bswap8(x: u8) -> u8 { x } + + #[lang = "u8"] + impl u8 { + uint_impl! { u8 = u8, 8, + intrinsics::ctpop8, + intrinsics::ctlz8, + intrinsics::cttz8, + bswap8, + intrinsics::u8_add_with_overflow, + intrinsics::u8_sub_with_overflow, + intrinsics::u8_mul_with_overflow } + } + + #[lang = "u16"] + impl u16 { + uint_impl! { u16 = u16, 16, + intrinsics::ctpop16, + intrinsics::ctlz16, + intrinsics::cttz16, + intrinsics::bswap16, + intrinsics::u16_add_with_overflow, + intrinsics::u16_sub_with_overflow, + intrinsics::u16_mul_with_overflow } + } + + #[lang = "u32"] + impl u32 { + uint_impl! { u32 = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } + } + + + #[lang = "u64"] + impl u64 { + uint_impl! { u64 = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } + } + + #[cfg(target_pointer_width = "32")] + #[lang = "usize"] + impl usize { + uint_impl! { uint = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } + } + + #[cfg(target_pointer_width = "64")] + #[lang = "usize"] + impl usize { + uint_impl! { uint = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } + } +} + /// A generic trait for converting a value to a number. #[unstable(feature = "core", reason = "trait is likely to be removed")] pub trait ToPrimitive { diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index c1c8ac9cc1f..377b5b57ae1 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -35,8 +35,14 @@ use fmt; #[cold] #[inline(never)] // this is the slow path, always #[lang="panic"] pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { + // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially + // reduce size overhead. The format_args! macro uses str's Display trait to + // write expr, which calls Formatter::pad, which must accommodate string + // truncation and padding (even though none is used here). Using + // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the + // output binary, saving up to a few kilobytes. let (expr, file, line) = *expr_file_line; - panic_fmt(format_args!("{}", expr), &(file, line)) + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line)) } #[cold] #[inline(never)] diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index f4b1a0633de..fb793a62390 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -29,6 +29,7 @@ pub use marker::{Copy, Send, Sized, Sync}; pub use ops::{Drop, Fn, FnMut, FnOnce}; // Reexported functions +#[allow(deprecated)] pub use iter::range; pub use mem::drop; @@ -41,6 +42,7 @@ pub use iter::{Extend, IteratorExt}; pub use iter::{Iterator, DoubleEndedIterator}; pub use iter::{ExactSizeIterator}; pub use option::Option::{self, Some, None}; +#[cfg(stage0)] pub use ptr::{PtrExt, MutPtrExt}; pub use result::Result::{self, Ok, Err}; pub use slice::{AsSlice, SliceExt}; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 32123a8271c..f28c26d1798 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -262,6 +262,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { intrinsics::move_val_init(&mut *dst, src) } +#[cfg(stage0)] /// Methods on raw pointers #[stable(feature = "rust1", since = "1.0.0")] pub trait PtrExt { @@ -298,6 +299,7 @@ pub trait PtrExt { unsafe fn offset(self, count: isize) -> Self where Self::Target: Sized; } +#[cfg(stage0)] /// Methods on mutable raw pointers #[stable(feature = "rust1", since = "1.0.0")] pub trait MutPtrExt { @@ -317,6 +319,7 @@ pub trait MutPtrExt { unsafe fn as_mut<'a>(&self) -> Option<&'a mut Self::Target>; } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> PtrExt for *const T { type Target = T; @@ -344,6 +347,7 @@ impl<T: ?Sized> PtrExt for *const T { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> PtrExt for *mut T { type Target = T; @@ -371,6 +375,7 @@ impl<T: ?Sized> PtrExt for *mut T { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> MutPtrExt for *mut T { type Target = T; @@ -388,6 +393,119 @@ impl<T: ?Sized> MutPtrExt for *mut T { } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "const_ptr"] +impl<T: ?Sized> *const T { + /// Returns true if the pointer is null. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_null(self) -> bool { + self == 0 as *const T + } + + /// Returns `None` if the pointer is null, or else returns a reference to + /// the value wrapped in `Some`. + /// + /// # Safety + /// + /// While this method and its mutable counterpart are useful for + /// null-safety, it is important to note that this is still an unsafe + /// operation because the returned value could be pointing to invalid + /// memory. + #[unstable(feature = "core", + reason = "Option is not clearly the right return type, and we may want \ + to tie the return lifetime to a borrow of the raw pointer")] + #[inline] + pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> { + if self.is_null() { + None + } else { + Some(&**self) + } + } + + /// Calculates the offset from a pointer. `count` is in units of T; e.g. a + /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes. + /// + /// # Safety + /// + /// The offset must be in-bounds of the object, or one-byte-past-the-end. + /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether + /// the pointer is used. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn offset(self, count: isize) -> *const T where T: Sized { + intrinsics::offset(self, count) + } +} + +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "mut_ptr"] +impl<T: ?Sized> *mut T { + /// Returns true if the pointer is null. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_null(self) -> bool { + self == 0 as *mut T + } + + /// Returns `None` if the pointer is null, or else returns a reference to + /// the value wrapped in `Some`. + /// + /// # Safety + /// + /// While this method and its mutable counterpart are useful for + /// null-safety, it is important to note that this is still an unsafe + /// operation because the returned value could be pointing to invalid + /// memory. + #[unstable(feature = "core", + reason = "Option is not clearly the right return type, and we may want \ + to tie the return lifetime to a borrow of the raw pointer")] + #[inline] + pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> { + if self.is_null() { + None + } else { + Some(&**self) + } + } + + /// Calculates the offset from a pointer. `count` is in units of T; e.g. a + /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes. + /// + /// # Safety + /// + /// The offset must be in-bounds of the object, or one-byte-past-the-end. + /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether + /// the pointer is used. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn offset(self, count: isize) -> *mut T where T: Sized { + intrinsics::offset(self, count) as *mut T + } + + /// Returns `None` if the pointer is null, or else returns a mutable + /// reference to the value wrapped in `Some`. + /// + /// # Safety + /// + /// As with `as_ref`, this is unsafe because it cannot verify the validity + /// of the returned pointer. + #[unstable(feature = "core", + reason = "return value does not necessarily convey all possible \ + information")] + #[inline] + pub unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> { + if self.is_null() { + None + } else { + Some(&mut **self) + } + } +} + // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> PartialEq for *const T { diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index c61c0f36979..b1576c0d377 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -49,6 +49,7 @@ use option::Option::{None, Some}; use result::Result; use result::Result::{Ok, Err}; use ptr; +#[cfg(stage0)] use ptr::PtrExt; use mem; use mem::size_of; @@ -520,10 +521,10 @@ impl<T> ops::Index<ops::Range<usize>> for [T] { assert!(index.start <= index.end); assert!(index.end <= self.len()); unsafe { - transmute(RawSlice { - data: self.as_ptr().offset(index.start as isize), - len: index.end - index.start - }) + from_raw_parts ( + self.as_ptr().offset(index.start as isize), + index.end - index.start + ) } } } @@ -559,10 +560,10 @@ impl<T> ops::IndexMut<ops::Range<usize>> for [T] { assert!(index.start <= index.end); assert!(index.end <= self.len()); unsafe { - transmute(RawSlice { - data: self.as_ptr().offset(index.start as isize), - len: index.end - index.start - }) + from_raw_parts_mut( + self.as_mut_ptr().offset(index.start as isize), + index.end - index.start + ) } } } @@ -731,7 +732,21 @@ macro_rules! make_slice { diff / mem::size_of::<$t>() }; unsafe { - transmute::<_, $result>(RawSlice { data: $start, len: len }) + from_raw_parts($start, len) + } + }} +} + +macro_rules! make_mut_slice { + ($t: ty => $result: ty: $start: expr, $end: expr) => {{ + let diff = $end as usize - $start as usize; + let len = if mem::size_of::<T>() == 0 { + diff + } else { + diff / mem::size_of::<$t>() + }; + unsafe { + from_raw_parts_mut($start, len) } }} } @@ -898,7 +913,7 @@ impl<'a, T> ops::IndexMut<ops::RangeFrom<usize>> for IterMut<'a, T> { impl<'a, T> ops::IndexMut<RangeFull> for IterMut<'a, T> { #[inline] fn index_mut(&mut self, _index: &RangeFull) -> &mut [T] { - make_slice!(T => &mut [T]: self.ptr, self.end) + make_mut_slice!(T => &mut [T]: self.ptr, self.end) } } @@ -912,7 +927,7 @@ impl<'a, T> IterMut<'a, T> { /// restricted lifetimes that do not consume the iterator. #[unstable(feature = "core")] pub fn into_slice(self) -> &'a mut [T] { - make_slice!(T => &'a mut [T]: self.ptr, self.end) + make_mut_slice!(T => &'a mut [T]: self.ptr, self.end) } } @@ -1404,7 +1419,7 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} #[unstable(feature = "core")] pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { unsafe { - transmute(RawSlice { data: s, len: 1 }) + from_raw_parts(s, 1) } } @@ -1412,8 +1427,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { #[unstable(feature = "core")] pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { unsafe { - let ptr: *const A = transmute(s); - transmute(RawSlice { data: ptr, len: 1 }) + from_raw_parts_mut(s, 1) } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 75e5657573e..bd46b093b76 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -30,6 +30,7 @@ use mem; use num::Int; use ops::{Fn, FnMut}; use option::Option::{self, None, Some}; +#[cfg(stage0)] use ptr::PtrExt; use raw::{Repr, Slice}; use result::Result::{self, Ok, Err}; diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 72b2d5dc188..ba6a7c4a5fe 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -10,18 +10,12 @@ //! Operations on tuples //! -//! To access a single element of a tuple one can use the following -//! methods: +//! To access a single element of a tuple one can use the `.0` +//! field access syntax. //! -//! * `valN` - returns a value of _N_-th element -//! * `refN` - returns a reference to _N_-th element -//! * `mutN` - returns a mutable reference to _N_-th element -//! -//! Indexing starts from zero, so `val0` returns first value, `val1` -//! returns second value, and so on. In general, a tuple with _S_ -//! elements provides aforementioned methods suffixed with numbers -//! from `0` to `S-1`. Traits which contain these methods are -//! implemented for tuples with up to 12 elements. +//! Indexing starts from zero, so `.0` returns first value, `.1` +//! returns second value, and so on. In general, a tuple with *N* +//! elements has field accessors from 0 to *N* - 1. //! //! If every type inside a tuple implements one of the following //! traits, then a tuple itself also implements it. @@ -52,7 +46,7 @@ macro_rules! e { macro_rules! tuple_impls { ($( $Tuple:ident { - $(($valN:ident, $refN:ident, $mutN:ident, $idx:tt) -> $T:ident)+ + $(($idx:tt) -> $T:ident)+ } )+) => { $( @@ -156,105 +150,105 @@ macro_rules! lexical_cmp { tuple_impls! { Tuple1 { - (val0, ref0, mut0, 0) -> A + (0) -> A } Tuple2 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B + (0) -> A + (1) -> B } Tuple3 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C + (0) -> A + (1) -> B + (2) -> C } Tuple4 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D + (0) -> A + (1) -> B + (2) -> C + (3) -> D } Tuple5 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E } Tuple6 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F } Tuple7 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G } Tuple8 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H } Tuple9 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I } Tuple10 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I - (val9, ref9, mut9, 9) -> J + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I + (9) -> J } Tuple11 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I - (val9, ref9, mut9, 9) -> J - (val10, ref10, mut10, 10) -> K + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I + (9) -> J + (10) -> K } Tuple12 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I - (val9, ref9, mut9, 9) -> J - (val10, ref10, mut10, 10) -> K - (val11, ref11, mut11, 11) -> L + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I + (9) -> J + (10) -> K + (11) -> L } } diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 0f4e7fcdda5..52cc2519add 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -775,12 +775,12 @@ fn test_range_inclusive() { #[test] fn test_range_step() { - assert_eq!(range_step(0, 20, 5).collect::<Vec<int>>(), [0, 5, 10, 15]); - assert_eq!(range_step(20, 0, -5).collect::<Vec<int>>(), [20, 15, 10, 5]); - assert_eq!(range_step(20, 0, -6).collect::<Vec<int>>(), [20, 14, 8, 2]); - assert_eq!(range_step(200, 255, 50).collect::<Vec<u8>>(), [200, 250]); - assert_eq!(range_step(200, -5, 1).collect::<Vec<int>>(), []); - assert_eq!(range_step(200, 200, 1).collect::<Vec<int>>(), []); + assert_eq!((0..20).step_by(5).collect::<Vec<int>>(), [0, 5, 10, 15]); + assert_eq!((20..0).step_by(-5).collect::<Vec<int>>(), [20, 15, 10, 5]); + assert_eq!((20..0).step_by(-6).collect::<Vec<int>>(), [20, 14, 8, 2]); + assert_eq!((200..255).step_by(50).collect::<Vec<u8>>(), [200, 250]); + assert_eq!((200..-5).step_by(1).collect::<Vec<int>>(), []); + assert_eq!((200..200).step_by(1).collect::<Vec<int>>(), []); } #[test] diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 100a9e36e86..695c71c73ed 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -25,7 +25,6 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(int_uint)] #![feature(libc)] #![feature(staged_api)] #![feature(unique)] @@ -35,13 +34,33 @@ extern crate libc; use libc::{c_void, size_t, c_int}; +use std::fmt; use std::ops::Deref; use std::ptr::Unique; use std::slice; +#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Error { + _unused: (), +} + +impl Error { + fn new() -> Error { + Error { + _unused: (), + } + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "decompression error".fmt(f) + } +} + pub struct Bytes { ptr: Unique<u8>, - len: uint, + len: usize, } impl Deref for Bytes { @@ -78,55 +97,56 @@ const LZ_NORM: c_int = 0x80; // LZ with 128 probes, "normal" const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32 checksum -fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> { +fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes { unsafe { - let mut outsz : size_t = 0; + let mut outsz: size_t = 0; let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, bytes.len() as size_t, &mut outsz, flags); - if !res.is_null() { - let res = Unique::new(res as *mut u8); - Some(Bytes { ptr: res, len: outsz as uint }) - } else { - None + assert!(!res.is_null()); + Bytes { + ptr: Unique::new(res as *mut u8), + len: outsz as usize, } } } /// Compress a buffer, without writing any sort of header on the output. -pub fn deflate_bytes(bytes: &[u8]) -> Option<Bytes> { +pub fn deflate_bytes(bytes: &[u8]) -> Bytes { deflate_bytes_internal(bytes, LZ_NORM) } /// Compress a buffer, using a header that zlib can understand. -pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> { +pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes { deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER) } -fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> { +fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes,Error> { unsafe { - let mut outsz : size_t = 0; + let mut outsz: size_t = 0; let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _, bytes.len() as size_t, &mut outsz, flags); if !res.is_null() { - let res = Unique::new(res as *mut u8); - Some(Bytes { ptr: res, len: outsz as uint }) + Ok(Bytes { + ptr: Unique::new(res as *mut u8), + len: outsz as usize, + }) } else { - None + Err(Error::new()) } } } /// Decompress a buffer, without parsing any sort of header on the input. -pub fn inflate_bytes(bytes: &[u8]) -> Option<Bytes> { +pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes,Error> { inflate_bytes_internal(bytes, 0) } /// Decompress a buffer that starts with a zlib header. -pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> { +pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result<Bytes,Error> { inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER) } @@ -140,7 +160,7 @@ mod tests { #[test] fn test_flate_round_trip() { let mut r = rand::thread_rng(); - let mut words = vec!(); + let mut words = vec![]; for _ in 0..20 { let range = r.gen_range(1, 10); let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>(); @@ -153,8 +173,8 @@ mod tests { } debug!("de/inflate of {} bytes of random word-sequences", input.len()); - let cmp = deflate_bytes(&input).expect("deflation failed"); - let out = inflate_bytes(&cmp).expect("inflation failed"); + let cmp = deflate_bytes(&input); + let out = inflate_bytes(&cmp).unwrap(); debug!("{} bytes deflated to {} ({:.1}% size)", input.len(), cmp.len(), 100.0 * ((cmp.len() as f64) / (input.len() as f64))); @@ -164,9 +184,9 @@ mod tests { #[test] fn test_zlib_flate() { - let bytes = vec!(1, 2, 3, 4, 5); - let deflated = deflate_bytes(&bytes).expect("deflation failed"); - let inflated = inflate_bytes(&deflated).expect("inflation failed"); + let bytes = vec![1, 2, 3, 4, 5]; + let deflated = deflate_bytes(&bytes); + let inflated = inflate_bytes(&deflated).unwrap(); assert_eq!(&*inflated, &*bytes); } } diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 11aba40afad..82c54004e99 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -3298,7 +3298,7 @@ pub mod consts { pub const MAP_DENYWRITE : c_int = 0x0800; pub const MAP_EXECUTABLE : c_int = 0x01000; pub const MAP_LOCKED : c_int = 0x02000; - pub const MAP_NONRESERVE : c_int = 0x04000; + pub const MAP_NORESERVE : c_int = 0x04000; pub const MAP_POPULATE : c_int = 0x08000; pub const MAP_NONBLOCK : c_int = 0x010000; pub const MAP_STACK : c_int = 0x020000; @@ -3325,7 +3325,7 @@ pub mod consts { pub const MAP_DENYWRITE : c_int = 0x02000; pub const MAP_EXECUTABLE : c_int = 0x04000; pub const MAP_LOCKED : c_int = 0x08000; - pub const MAP_NONRESERVE : c_int = 0x0400; + pub const MAP_NORESERVE : c_int = 0x0400; pub const MAP_POPULATE : c_int = 0x010000; pub const MAP_NONBLOCK : c_int = 0x020000; pub const MAP_STACK : c_int = 0x040000; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index b03d77db4ec..c634a46888e 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -175,7 +175,6 @@ #![feature(int_uint)] #![feature(core)] #![feature(std_misc)] -#![feature(io)] use std::boxed; use std::cell::RefCell; diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 4a0807bf099..a46709932e2 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -17,8 +17,6 @@ //! internally. The `IndependentSample` trait is for generating values //! that do not need to record state. -#![unstable(feature = "rand")] - use core::prelude::*; use core::num::{Float, Int}; use core::marker::PhantomData; @@ -125,7 +123,7 @@ impl<'a, T: Clone> WeightedChoice<'a, T> { // strictly speaking, this is subsumed by the total weight == 0 case assert!(!items.is_empty(), "WeightedChoice::new called with no items"); - let mut running_total = 0; + let mut running_total = 0_usize; // we convert the list from individual weights to cumulative // weights so we can binary search. This *could* drop elements diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 8486bf782b0..e466dc8a3a0 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -784,8 +784,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo csz - vlen); let bytes = slice::from_raw_parts(cvbuf1, csz - vlen); match flate::inflate_bytes(bytes) { - Some(inflated) => return Ok(MetadataVec(inflated)), - None => {} + Ok(inflated) => return Ok(MetadataVec(inflated)), + Err(_) => {} } } llvm::LLVMMoveToNextSection(si.llsi); diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 40bba6fb0ac..313f034021f 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -27,6 +27,7 @@ use middle::ty; use std::cmp::Ordering; use std::fmt; use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat}; +#[cfg(stage0)] use std::num::Float; use std::slice; use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat}; @@ -646,6 +647,7 @@ fn is_useful(cx: &MatchCheckCtxt, if rows[0].len() == 0 { return NotUseful; } + assert!(rows.iter().all(|r| r.len() == v.len())); let real_pat = match rows.iter().find(|r| (*r)[0].id != DUMMY_NODE_ID) { Some(r) => raw_pat(r[0]), None if v.len() == 0 => return NotUseful, @@ -654,7 +656,12 @@ fn is_useful(cx: &MatchCheckCtxt, let left_ty = if real_pat.id == DUMMY_NODE_ID { ty::mk_nil(cx.tcx) } else { - ty::pat_ty(cx.tcx, &*real_pat) + let left_ty = ty::pat_ty(cx.tcx, &*real_pat); + + match real_pat.node { + ast::PatIdent(ast::BindByRef(..), _, _) => ty::deref(left_ty, false).unwrap().ty, + _ => left_ty, + } }; let max_slice_length = rows.iter().filter_map(|row| match row[0].node { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 09378f2c973..5efea66ab0c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -47,7 +47,6 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { struct_has_extern_repr: bool, ignore_non_const_paths: bool, inherited_pub_visibility: bool, - ignore_variant_stack: Vec<ast::NodeId>, } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { @@ -60,7 +59,6 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { struct_has_extern_repr: false, ignore_non_const_paths: false, inherited_pub_visibility: false, - ignore_variant_stack: vec![], } } @@ -81,9 +79,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { def::DefPrimTy(_) => (), def::DefVariant(enum_id, variant_id, _) => { self.check_def_id(enum_id); - if !self.ignore_variant_stack.contains(&variant_id.node) { - self.check_def_id(variant_id); - } + self.check_def_id(variant_id); } _ => { self.check_def_id(def.def_id()); @@ -282,23 +278,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { visit::walk_expr(self, expr); } - fn visit_arm(&mut self, arm: &ast::Arm) { - if arm.pats.len() == 1 { - let pat = &*arm.pats[0]; - let variants = pat_util::necessary_variants(&self.tcx.def_map, pat); - - // Inside the body, ignore constructions of variants - // necessary for the pattern to match. Those construction sites - // can't be reached unless the variant is constructed elsewhere. - let len = self.ignore_variant_stack.len(); - self.ignore_variant_stack.push_all(&*variants); - visit::walk_arm(self, arm); - self.ignore_variant_stack.truncate(len); - } else { - visit::walk_arm(self, arm); - } - } - fn visit_pat(&mut self, pat: &ast::Pat) { let def_map = &self.tcx.def_map; match pat.node { @@ -418,11 +397,6 @@ fn create_and_seed_worklist(tcx: &ty::ctxt, worklist.push(*id); } for id in reachable_symbols { - // Reachable variants can be dead, because we warn about - // variants never constructed, not variants never used. - if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) { - continue; - } worklist.push(*id); } diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index be94a73df37..9add236d54b 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -154,7 +154,7 @@ pub trait Combine<'tcx> : Sized { b_tys.len()))); } - range(0, a_tys.len()).map(|i| { + (0.. a_tys.len()).map(|i| { let a_ty = a_tys[i]; let b_ty = b_tys[i]; let v = variances.map_or(ty::Invariant, |v| v[i]); diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3525d46a1f2..1ad4611dc9e 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -239,6 +239,24 @@ pub fn collect_language_items(krate: &ast::Crate, lets_do_this! { // Variant name, Name, Method name; + CharImplItem, "char", char_impl; + StrImplItem, "str", str_impl; + SliceImplItem, "slice", slice_impl; + ConstPtrImplItem, "const_ptr", const_ptr_impl; + MutPtrImplItem, "mut_ptr", mut_ptr_impl; + I8ImplItem, "i8", i8_impl; + I16ImplItem, "i16", i16_impl; + I32ImplItem, "i32", i32_impl; + I64ImplItem, "i64", i64_impl; + IsizeImplItem, "isize", isize_impl; + U8ImplItem, "u8", u8_impl; + U16ImplItem, "u16", u16_impl; + U32ImplItem, "u32", u32_impl; + U64ImplItem, "u64", u64_impl; + UsizeImplItem, "usize", usize_impl; + F32ImplItem, "f32", f32_impl; + F64ImplItem, "f64", f64_impl; + SendTraitLangItem, "send", send_trait; SizedTraitLangItem, "sized", sized_trait; CopyTraitLangItem, "copy", copy_trait; diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index eca3296e65c..c5abff3b963 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -155,27 +155,3 @@ pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path { span: DUMMY_SP, }) } - -/// Return variants that are necessary to exist for the pattern to match. -pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> { - let mut variants = vec![]; - walk_pat(pat, |p| { - match p.node { - ast::PatEnum(_, _) | - ast::PatIdent(_, _, None) | - ast::PatStruct(..) => { - match dm.borrow().get(&p.id) { - Some(&PathResolution {base_def: DefVariant(_, id, _), ..}) => { - variants.push(id.node); - } - _ => () - } - } - _ => () - } - true - }); - variants.sort(); - variants.dedup(); - variants -} diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8705e56b094..c3e1879fca8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -788,6 +788,9 @@ pub struct ctxt<'tcx> { /// is used for lazy resolution of traits. pub populated_external_traits: RefCell<DefIdSet>, + /// The set of external primitive inherent implementations that have been read. + pub populated_external_primitive_impls: RefCell<DefIdSet>, + /// Borrows pub upvar_capture_map: RefCell<UpvarCaptureMap>, @@ -2599,6 +2602,7 @@ pub fn mk_ctxt<'tcx>(s: Session, used_mut_nodes: RefCell::new(NodeSet()), populated_external_types: RefCell::new(DefIdSet()), populated_external_traits: RefCell::new(DefIdSet()), + populated_external_primitive_impls: RefCell::new(DefIdSet()), upvar_capture_map: RefCell::new(FnvHashMap()), extern_const_statics: RefCell::new(DefIdMap()), extern_const_variants: RefCell::new(DefIdMap()), @@ -5988,6 +5992,25 @@ pub fn record_trait_implementation(tcx: &ctxt, tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id)))); } +/// Load primitive inherent implementations if necessary +pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt, lang_def_id: ast::DefId) { + if lang_def_id.krate == LOCAL_CRATE { + return + } + if tcx.populated_external_primitive_impls.borrow().contains(&lang_def_id) { + return + } + + debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", lang_def_id); + + let impl_items = csearch::get_impl_items(&tcx.sess.cstore, lang_def_id); + + // Store the implementation info. + tcx.impl_items.borrow_mut().insert(lang_def_id, impl_items); + + tcx.populated_external_primitive_impls.borrow_mut().insert(lang_def_id); +} + /// Populates the type context with all the implementations for the given type /// if necessary. pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index f85fb303910..3c5d9744505 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -10,6 +10,7 @@ use std::slice; use std::path::{Path, PathBuf}; +use session::early_error; #[derive(Clone, Debug)] pub struct SearchPaths { @@ -50,6 +51,9 @@ impl SearchPaths { } else { (PathKind::All, path) }; + if path.is_empty() { + early_error("empty search path given via `-L`"); + } self.paths.push((kind, PathBuf::new(path))); } diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 77338dddefa..99d24a60130 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -48,6 +48,7 @@ #![feature(path_ext)] #![feature(std_misc)] #![feature(path_relative_from)] +#![feature(step_by)] extern crate syntax; extern crate serialize; diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 467b7c1ca38..5aae0e9dbdc 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -48,7 +48,6 @@ use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; -use std::iter::range_step; use syntax::ast; use syntax::visit; @@ -103,7 +102,7 @@ impl Svh { let hash = state.finish(); return Svh { - hash: range_step(0, 64, 4).map(|i| hex(hash >> i)).collect() + hash: (0..64).step_by(4).map(|i| hex(hash >> i)).collect() }; fn hex(b: u64) -> char { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e0261606ef1..e132e9833c1 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -37,7 +37,7 @@ #![feature(staged_api)] #![feature(exit_status)] #![feature(io)] -#![feature(set_panic)] +#![feature(set_stdio)] extern crate arena; extern crate flate; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 074591fb927..f6f82c65374 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -811,7 +811,7 @@ impl NonCamelCaseTypes { if i == 0 { c.to_uppercase().collect::<String>() } else { - c.to_string() + c.to_lowercase().collect() } )).collect::<Vec<_>>().concat() } diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index f54480e3e52..0728d5b46e2 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -14,8 +14,7 @@ use libc; use ArchiveRef; use std::ffi::CString; -use std::mem; -use std::raw; +use std::slice; use std::path::Path; pub struct ArchiveRO { @@ -62,10 +61,7 @@ impl ArchiveRO { if ptr.is_null() { None } else { - Some(mem::transmute(raw::Slice { - data: ptr, - len: size as uint, - })) + Some(slice::from_raw_parts(ptr as *const u8, size as uint)) } } } diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 71233ff5003..506bf4a058f 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -26,7 +26,6 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] #![feature(int_uint)] #![feature(libc)] #![feature(link_args)] @@ -58,7 +57,7 @@ pub use self::Linkage::*; use std::ffi::CString; use std::cell::RefCell; -use std::{raw, mem}; +use std::{slice, mem}; use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char}; use libc::{c_longlong, c_ulonglong, c_void}; use debuginfo::{DIBuilderRef, DIDescriptor, @@ -2226,10 +2225,7 @@ type RustStringRepr = *mut RefCell<Vec<u8>>; pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef, ptr: *const c_char, size: size_t) { - let slice: &[u8] = mem::transmute(raw::Slice { - data: ptr as *const u8, - len: size as uint, - }); + let slice = slice::from_raw_parts(ptr as *const u8, size as uint); let sr: RustStringRepr = mem::transmute(sr); (*sr).borrow_mut().push_all(slice); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1cbbcad9550..e62300098f6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -14,16 +14,17 @@ //! any imports resolved. use {DefModifiers, PUBLIC, IMPORTABLE}; -use ImportDirective; -use ImportDirectiveSubclass::{self, SingleImport, GlobImport}; -use ImportResolution; +use resolve_imports::ImportDirective; +use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport}; +use resolve_imports::ImportResolution; use Module; use ModuleKind::*; use Namespace::{TypeNS, ValueNS}; use NameBindings; +use {names_to_string, module_to_string}; use ParentLink::{self, ModuleParentLink, BlockParentLink}; use Resolver; -use Shadowable; +use resolve_imports::Shadowable; use TypeNsDef; use self::DuplicateCheckingMode::*; @@ -371,8 +372,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { ItemExternCrate(_) => { // n.b. we don't need to look at the path option here, because cstore already did - for &crate_id in self.session.cstore - .find_extern_mod_stmt_cnum(item.id).iter() { + if let Some(crate_id) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) { let def_id = DefId { krate: crate_id, node: 0 }; self.external_exports.insert(def_id); let parent_link = ModuleParentLink(parent.downgrade(), name); @@ -382,7 +382,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { false, true)); debug!("(build reduced graph for item) found extern `{}`", - self.module_to_string(&*external_module)); + module_to_string(&*external_module)); self.check_for_conflicts_between_external_crates(&**parent, name, sp); parent.external_module_children.borrow_mut() .insert(name, external_module.clone()); @@ -400,7 +400,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(def_id), NormalModuleKind, false, - item.vis == ast::Public, + is_public, sp); name_bindings.get_module() @@ -432,8 +432,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // These items live in the type namespace. ItemTy(..) => { let name_bindings = - self.add_child(name, parent, ForbidDuplicateTypesAndModules, - sp); + self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers); @@ -517,7 +516,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(local_def(item.id)), TraitModuleKind, false, - item.vis == ast::Public, + is_public, sp); let module_parent = name_bindings.get_module(); @@ -636,8 +635,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { name: Name, new_parent: &Rc<Module>) { debug!("(building reduced graph for \ - external crate) building external def, priv {:?}", - vis); + external crate) building external def {}, priv {:?}", + final_ident, vis); let is_public = vis == ast::Public; let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; let is_exported = is_public && match new_parent.def_id.get() { @@ -667,7 +666,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(_) | None => { debug!("(building reduced graph for \ external crate) building module \ - {}", final_ident); + {} {}", final_ident, is_public); let parent_link = self.get_parent_link(new_parent, name); child_name_bindings.define_module(parent_link, @@ -838,7 +837,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Builds the reduced graph rooted at the given external module. fn populate_external_module(&mut self, module: &Rc<Module>) { debug!("(populating external module) attempting to populate {}", - self.module_to_string(&**module)); + module_to_string(&**module)); let def_id = match module.def_id.get() { None => { @@ -904,18 +903,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { match subclass { SingleImport(target, _) => { - debug!("(building import directive) building import \ - directive: {}::{}", - self.names_to_string(&module_.imports.borrow().last().unwrap(). - module_path), + debug!("(building import directive) building import directive: {}::{}", + names_to_string(&module_.imports.borrow().last().unwrap().module_path), token::get_name(target)); - let mut import_resolutions = module_.import_resolutions - .borrow_mut(); + let mut import_resolutions = module_.import_resolutions.borrow_mut(); match import_resolutions.get_mut(&target) { Some(resolution) => { - debug!("(building import directive) bumping \ - reference"); + debug!("(building import directive) bumping reference"); resolution.outstanding_references += 1; // the source of this name is different now diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 124aa392435..c586faae6e8 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -24,7 +24,9 @@ register_diagnostics! { E0258, // import conflicts with existing submodule E0259, // an extern crate has already been imported into this module E0260, // name conflicts with an external crate that has been imported into this module - E0317 // user-defined types or type parameters cannot shadow the primitive types + E0317, // user-defined types or type parameters cannot shadow the primitive types + E0364, // item is private + E0365 // item is private } __build_diagnostic_array! { DIAGNOSTICS } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e49fdc9c5d3..67e9f71551a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -38,7 +38,6 @@ use self::PatternBindingMode::*; use self::Namespace::*; use self::NamespaceResult::*; use self::NameDefinition::*; -use self::ImportDirectiveSubclass::*; use self::ResolveResult::*; use self::FallbackSuggestion::*; use self::TypeParameters::*; @@ -98,6 +97,10 @@ use std::mem::replace; use std::rc::{Rc, Weak}; use std::usize; +use resolve_imports::{Target, ImportDirective, ImportResolution}; +use resolve_imports::Shadowable; + + // NB: This module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostics; @@ -105,6 +108,7 @@ pub mod diagnostics; mod check_unused; mod record_exports; mod build_reduced_graph; +mod resolve_imports; #[derive(Copy)] struct BindingInfo { @@ -253,13 +257,6 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { } } -/// Contains data for specific types of import directives. -#[derive(Copy,Debug)] -enum ImportDirectiveSubclass { - SingleImport(Name /* target */, Name /* source */), - GlobImport -} - type ErrorMessage = Option<(Span, String)>; enum ResolveResult<T> { @@ -366,144 +363,6 @@ impl Rib { } } -/// Whether an import can be shadowed by another import. -#[derive(Debug,PartialEq,Clone,Copy)] -enum Shadowable { - Always, - Never -} - -/// One import directive. -#[derive(Debug)] -struct ImportDirective { - module_path: Vec<Name>, - subclass: ImportDirectiveSubclass, - span: Span, - id: NodeId, - is_public: bool, // see note in ImportResolution about how to use this - shadowable: Shadowable, -} - -impl ImportDirective { - fn new(module_path: Vec<Name> , - subclass: ImportDirectiveSubclass, - span: Span, - id: NodeId, - is_public: bool, - shadowable: Shadowable) - -> ImportDirective { - ImportDirective { - module_path: module_path, - subclass: subclass, - span: span, - id: id, - is_public: is_public, - shadowable: shadowable, - } - } -} - -/// The item that an import resolves to. -#[derive(Clone,Debug)] -struct Target { - target_module: Rc<Module>, - bindings: Rc<NameBindings>, - shadowable: Shadowable, -} - -impl Target { - fn new(target_module: Rc<Module>, - bindings: Rc<NameBindings>, - shadowable: Shadowable) - -> Target { - Target { - target_module: target_module, - bindings: bindings, - shadowable: shadowable, - } - } -} - -/// An ImportResolution represents a particular `use` directive. -#[derive(Debug)] -struct ImportResolution { - /// Whether this resolution came from a `use` or a `pub use`. Note that this - /// should *not* be used whenever resolution is being performed, this is - /// only looked at for glob imports statements currently. Privacy testing - /// occurs during a later phase of compilation. - is_public: bool, - - // The number of outstanding references to this name. When this reaches - // zero, outside modules can count on the targets being correct. Before - // then, all bets are off; future imports could override this name. - outstanding_references: uint, - - /// The value that this `use` directive names, if there is one. - value_target: Option<Target>, - /// The source node of the `use` directive leading to the value target - /// being non-none - value_id: NodeId, - - /// The type that this `use` directive names, if there is one. - type_target: Option<Target>, - /// The source node of the `use` directive leading to the type target - /// being non-none - type_id: NodeId, -} - -impl ImportResolution { - fn new(id: NodeId, is_public: bool) -> ImportResolution { - ImportResolution { - type_id: id, - value_id: id, - outstanding_references: 0, - value_target: None, - type_target: None, - is_public: is_public, - } - } - - fn target_for_namespace(&self, namespace: Namespace) - -> Option<Target> { - match namespace { - TypeNS => self.type_target.clone(), - ValueNS => self.value_target.clone(), - } - } - - fn id(&self, namespace: Namespace) -> NodeId { - match namespace { - TypeNS => self.type_id, - ValueNS => self.value_id, - } - } - - fn shadowable(&self, namespace: Namespace) -> Shadowable { - let target = self.target_for_namespace(namespace); - if target.is_none() { - return Shadowable::Always; - } - - target.unwrap().shadowable - } - - fn set_target_and_id(&mut self, - namespace: Namespace, - target: Option<Target>, - id: NodeId) { - match namespace { - TypeNS => { - self.type_target = target; - self.type_id = id; - } - ValueNS => { - self.value_target = target; - self.value_id = id; - } - } - } -} - /// The link from a module up to its nearest parent node. #[derive(Clone,Debug)] enum ParentLink { @@ -855,6 +714,19 @@ impl NameBindings { None } } + + fn is_public(&self, namespace: Namespace) -> bool { + match namespace { + TypeNS => { + let type_def = self.type_def.borrow(); + type_def.as_ref().unwrap().modifiers.contains(PUBLIC) + } + ValueNS => { + let value_def = self.value_def.borrow(); + value_def.as_ref().unwrap().modifiers.contains(PUBLIC) + } + } + } } /// Interns the names of the primitive types. @@ -963,7 +835,6 @@ enum FallbackChecks { OnlyTraitAndStatics } - impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new(session: &'a Session, ast_map: &'a ast_map::Map<'tcx>, @@ -1023,151 +894,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - // Import resolution - // - // This is a fixed-point algorithm. We resolve imports until our efforts - // are stymied by an unresolved import; then we bail out of the current - // module and continue. We terminate successfully once no more imports - // remain or unsuccessfully when no forward progress in resolving imports - // is made. - - /// Resolves all imports for the crate. This method performs the fixed- - /// point iteration. - fn resolve_imports(&mut self) { - let mut i = 0; - let mut prev_unresolved_imports = 0; - loop { - debug!("(resolving imports) iteration {}, {} imports left", - i, self.unresolved_imports); - - let module_root = self.graph_root.get_module(); - self.resolve_imports_for_module_subtree(module_root.clone()); - - if self.unresolved_imports == 0 { - debug!("(resolving imports) success"); - break; - } - - if self.unresolved_imports == prev_unresolved_imports { - self.report_unresolved_imports(module_root); - break; - } - - i += 1; - prev_unresolved_imports = self.unresolved_imports; - } - } - - /// Attempts to resolve imports for the given module and all of its - /// submodules. - fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) { - debug!("(resolving imports for module subtree) resolving {}", - self.module_to_string(&*module_)); - let orig_module = replace(&mut self.current_module, module_.clone()); - self.resolve_imports_for_module(module_.clone()); - self.current_module = orig_module; - - build_reduced_graph::populate_module_if_necessary(self, &module_); - for (_, child_node) in &*module_.children.borrow() { - match child_node.get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.resolve_imports_for_module_subtree(child_module); - } - } - } - - for (_, child_module) in &*module_.anonymous_children.borrow() { - self.resolve_imports_for_module_subtree(child_module.clone()); - } - } - - /// Attempts to resolve imports for the given module only. - fn resolve_imports_for_module(&mut self, module: Rc<Module>) { - if module.all_imports_resolved() { - debug!("(resolving imports for module) all imports resolved for \ - {}", - self.module_to_string(&*module)); - return; - } - - let imports = module.imports.borrow(); - let import_count = imports.len(); - while module.resolved_import_count.get() < import_count { - let import_index = module.resolved_import_count.get(); - let import_directive = &(*imports)[import_index]; - match self.resolve_import_for_module(module.clone(), - import_directive) { - Failed(err) => { - let (span, help) = match err { - Some((span, msg)) => (span, format!(". {}", msg)), - None => (import_directive.span, String::new()) - }; - let msg = format!("unresolved import `{}`{}", - self.import_path_to_string( - &import_directive.module_path, - import_directive.subclass), - help); - self.resolve_error(span, &msg[..]); - } - Indeterminate => break, // Bail out. We'll come around next time. - Success(()) => () // Good. Continue. - } - - module.resolved_import_count - .set(module.resolved_import_count.get() + 1); - } - } - - fn names_to_string(&self, names: &[Name]) -> String { - let mut first = true; - let mut result = String::new(); - for name in names { - if first { - first = false - } else { - result.push_str("::") - } - result.push_str(&token::get_name(*name)); - }; - result - } - - fn path_names_to_string(&self, path: &Path, depth: usize) -> String { - let names: Vec<ast::Name> = path.segments[..path.segments.len()-depth] - .iter() - .map(|seg| seg.identifier.name) - .collect(); - self.names_to_string(&names[..]) - } - - fn import_directive_subclass_to_string(&mut self, - subclass: ImportDirectiveSubclass) - -> String { - match subclass { - SingleImport(_, source) => { - token::get_name(source).to_string() - } - GlobImport => "*".to_string() - } - } - - fn import_path_to_string(&mut self, - names: &[Name], - subclass: ImportDirectiveSubclass) - -> String { - if names.is_empty() { - self.import_directive_subclass_to_string(subclass) - } else { - (format!("{}::{}", - self.names_to_string(names), - self.import_directive_subclass_to_string( - subclass))).to_string() - } - } - #[inline] fn record_import_use(&mut self, import_id: NodeId, name: Name) { if !self.make_glob_map { @@ -1191,102 +917,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - /// Attempts to resolve the given import. The return value indicates - /// failure if we're certain the name does not exist, indeterminate if we - /// don't know whether the name exists at the moment due to other - /// currently-unresolved imports, or success if we know the name exists. - /// If successful, the resolved bindings are written into the module. - fn resolve_import_for_module(&mut self, - module_: Rc<Module>, - import_directive: &ImportDirective) - -> ResolveResult<()> { - let mut resolution_result = Failed(None); - let module_path = &import_directive.module_path; - - debug!("(resolving import for module) resolving import `{}::...` in `{}`", - self.names_to_string(&module_path[..]), - self.module_to_string(&*module_)); - - // First, resolve the module path for the directive, if necessary. - let container = if module_path.len() == 0 { - // Use the crate root. - Some((self.graph_root.get_module(), LastMod(AllPublic))) - } else { - match self.resolve_module_path(module_.clone(), - &module_path[..], - DontUseLexicalScope, - import_directive.span, - ImportSearch) { - Failed(err) => { - resolution_result = Failed(err); - None - }, - Indeterminate => { - resolution_result = Indeterminate; - None - } - Success(container) => Some(container), - } - }; - - match container { - None => {} - Some((containing_module, lp)) => { - // We found the module that the target is contained - // within. Attempt to resolve the import within it. - - match import_directive.subclass { - SingleImport(target, source) => { - resolution_result = - self.resolve_single_import(&*module_, - containing_module, - target, - source, - import_directive, - lp); - } - GlobImport => { - resolution_result = - self.resolve_glob_import(&*module_, - containing_module, - import_directive, - lp); - } - } - } - } - - // Decrement the count of unresolved imports. - match resolution_result { - Success(()) => { - assert!(self.unresolved_imports >= 1); - self.unresolved_imports -= 1; - } - _ => { - // Nothing to do here; just return the error. - } - } - - // Decrement the count of unresolved globs if necessary. But only if - // the resolution result is indeterminate -- otherwise we'll stop - // processing imports here. (See the loop in - // resolve_imports_for_module.) - - if !resolution_result.indeterminate() { - match import_directive.subclass { - GlobImport => { - assert!(module_.glob_count.get() >= 1); - module_.glob_count.set(module_.glob_count.get() - 1); - } - SingleImport(..) => { - // Ignore. - } - } - } - - return resolution_result; - } - fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings { NameBindings { type_def: RefCell::new(Some(TypeNsDef { @@ -1299,604 +929,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_single_import(&mut self, - module_: &Module, - containing_module: Rc<Module>, - target: Name, - source: Name, - directive: &ImportDirective, - lp: LastPrivate) - -> ResolveResult<()> { - debug!("(resolving single import) resolving `{}` = `{}::{}` from \ - `{}` id {}, last private {:?}", - token::get_name(target), - self.module_to_string(&*containing_module), - token::get_name(source), - self.module_to_string(module_), - directive.id, - lp); - - let lp = match lp { - LastMod(lp) => lp, - LastImport {..} => { - self.session - .span_bug(directive.span, - "not expecting Import here, must be LastMod") - } - }; - - // We need to resolve both namespaces for this to succeed. - // - - let mut value_result = UnknownResult; - let mut type_result = UnknownResult; - - // Search for direct children of the containing module. - build_reduced_graph::populate_module_if_necessary(self, &containing_module); - - match containing_module.children.borrow().get(&source) { - None => { - // Continue. - } - Some(ref child_name_bindings) => { - if child_name_bindings.defined_in_namespace(ValueNS) { - debug!("(resolving single import) found value binding"); - value_result = BoundResult(containing_module.clone(), - (*child_name_bindings).clone()); - } - if child_name_bindings.defined_in_namespace(TypeNS) { - debug!("(resolving single import) found type binding"); - type_result = BoundResult(containing_module.clone(), - (*child_name_bindings).clone()); - } - } - } - - // Unless we managed to find a result in both namespaces (unlikely), - // search imports as well. - let mut value_used_reexport = false; - let mut type_used_reexport = false; - match (value_result.clone(), type_result.clone()) { - (BoundResult(..), BoundResult(..)) => {} // Continue. - _ => { - // If there is an unresolved glob at this point in the - // containing module, bail out. We don't know enough to be - // able to resolve this import. - - if containing_module.glob_count.get() > 0 { - debug!("(resolving single import) unresolved glob; \ - bailing out"); - return Indeterminate; - } - - // Now search the exported imports within the containing module. - match containing_module.import_resolutions.borrow().get(&source) { - None => { - debug!("(resolving single import) no import"); - // The containing module definitely doesn't have an - // exported import with the name in question. We can - // therefore accurately report that the names are - // unbound. - - if value_result.is_unknown() { - value_result = UnboundResult; - } - if type_result.is_unknown() { - type_result = UnboundResult; - } - } - Some(import_resolution) - if import_resolution.outstanding_references == 0 => { - - fn get_binding(this: &mut Resolver, - import_resolution: &ImportResolution, - namespace: Namespace, - source: &Name) - -> NamespaceResult { - - // Import resolutions must be declared with "pub" - // in order to be exported. - if !import_resolution.is_public { - return UnboundResult; - } - - match import_resolution. - target_for_namespace(namespace) { - None => { - return UnboundResult; - } - Some(Target { - target_module, - bindings, - shadowable: _ - }) => { - debug!("(resolving single import) found \ - import in ns {:?}", namespace); - let id = import_resolution.id(namespace); - // track used imports and extern crates as well - this.used_imports.insert((id, namespace)); - this.record_import_use(id, *source); - match target_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { - this.used_crates.insert(kid); - }, - _ => {} - } - return BoundResult(target_module, bindings); - } - } - } - - // The name is an import which has been fully - // resolved. We can, therefore, just follow it. - if value_result.is_unknown() { - value_result = get_binding(self, - import_resolution, - ValueNS, - &source); - value_used_reexport = import_resolution.is_public; - } - if type_result.is_unknown() { - type_result = get_binding(self, - import_resolution, - TypeNS, - &source); - type_used_reexport = import_resolution.is_public; - } - - } - Some(_) => { - // If containing_module is the same module whose import we are resolving - // and there it has an unresolved import with the same name as `source`, - // then the user is actually trying to import an item that is declared - // in the same scope - // - // e.g - // use self::submodule; - // pub mod submodule; - // - // In this case we continue as if we resolved the import and let the - // check_for_conflicts_between_imports_and_items call below handle - // the conflict - match (module_.def_id.get(), containing_module.def_id.get()) { - (Some(id1), Some(id2)) if id1 == id2 => { - if value_result.is_unknown() { - value_result = UnboundResult; - } - if type_result.is_unknown() { - type_result = UnboundResult; - } - } - _ => { - // The import is unresolved. Bail out. - debug!("(resolving single import) unresolved import; \ - bailing out"); - return Indeterminate; - } - } - } - } - } - } - - // If we didn't find a result in the type namespace, search the - // external modules. - let mut value_used_public = false; - let mut type_used_public = false; - match type_result { - BoundResult(..) => {} - _ => { - match containing_module.external_module_children.borrow_mut() - .get(&source).cloned() { - None => {} // Continue. - Some(module) => { - debug!("(resolving single import) found external \ - module"); - // track the module as used. - match module.def_id.get() { - Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); }, - _ => {} - } - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module( - module)); - type_result = BoundResult(containing_module.clone(), - name_bindings); - type_used_public = true; - } - } - } - } - - // We've successfully resolved the import. Write the results in. - let mut import_resolutions = module_.import_resolutions.borrow_mut(); - let import_resolution = &mut (*import_resolutions)[target]; - { - let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| { - let namespace_name = match namespace { - TypeNS => "type", - ValueNS => "value", - }; - - match *result { - BoundResult(ref target_module, ref name_bindings) => { - debug!("(resolving single import) found {:?} target: {:?}", - namespace_name, - name_bindings.def_for_namespace(namespace)); - self.check_for_conflicting_import( - &import_resolution.target_for_namespace(namespace), - directive.span, - target, - namespace); - - self.check_that_import_is_importable( - &**name_bindings, - directive.span, - target, - namespace); - - let target = Some(Target::new(target_module.clone(), - name_bindings.clone(), - directive.shadowable)); - import_resolution.set_target_and_id(namespace, target, directive.id); - import_resolution.is_public = directive.is_public; - *used_public = name_bindings.defined_in_public_namespace(namespace); - } - UnboundResult => { /* Continue. */ } - UnknownResult => { - panic!("{:?} result should be known at this point", namespace_name); - } - } - }; - check_and_write_import(ValueNS, &value_result, &mut value_used_public); - check_and_write_import(TypeNS, &type_result, &mut type_used_public); - } - - self.check_for_conflicts_between_imports_and_items( - module_, - import_resolution, - directive.span, - target); - - if value_result.is_unbound() && type_result.is_unbound() { - let msg = format!("There is no `{}` in `{}`", - token::get_name(source), - self.module_to_string(&*containing_module)); - return Failed(Some((directive.span, msg))); - } - let value_used_public = value_used_reexport || value_used_public; - let type_used_public = type_used_reexport || type_used_public; - - assert!(import_resolution.outstanding_references >= 1); - import_resolution.outstanding_references -= 1; - - // record what this import resolves to for later uses in documentation, - // this may resolve to either a value or a type, but for documentation - // purposes it's good enough to just favor one over the other. - let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| { - let def = target.bindings.def_for_namespace(ValueNS).unwrap(); - (def, if value_used_public { lp } else { DependsOn(def.def_id()) }) - }); - let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| { - let def = target.bindings.def_for_namespace(TypeNS).unwrap(); - (def, if type_used_public { lp } else { DependsOn(def.def_id()) }) - }); - - let import_lp = LastImport { - value_priv: value_def_and_priv.map(|(_, p)| p), - value_used: Used, - type_priv: type_def_and_priv.map(|(_, p)| p), - type_used: Used - }; - - if let Some((def, _)) = value_def_and_priv { - self.def_map.borrow_mut().insert(directive.id, PathResolution { - base_def: def, - last_private: import_lp, - depth: 0 - }); - } - if let Some((def, _)) = type_def_and_priv { - self.def_map.borrow_mut().insert(directive.id, PathResolution { - base_def: def, - last_private: import_lp, - depth: 0 - }); - } - - debug!("(resolving single import) successfully resolved import"); - return Success(()); - } - - // Resolves a glob import. Note that this function cannot fail; it either - // succeeds or bails out (as importing * from an empty module or a module - // that exports nothing is valid). containing_module is the module we are - // actually importing, i.e., `foo` in `use foo::*`. - fn resolve_glob_import(&mut self, - module_: &Module, - containing_module: Rc<Module>, - import_directive: &ImportDirective, - lp: LastPrivate) - -> ResolveResult<()> { - let id = import_directive.id; - let is_public = import_directive.is_public; - - // This function works in a highly imperative manner; it eagerly adds - // everything it can to the list of import resolutions of the module - // node. - debug!("(resolving glob import) resolving glob import {}", id); - - // We must bail out if the node has unresolved imports of any kind - // (including globs). - if !(*containing_module).all_imports_resolved() { - debug!("(resolving glob import) target module has unresolved \ - imports; bailing out"); - return Indeterminate; - } - - assert_eq!(containing_module.glob_count.get(), 0); - - // Add all resolved imports from the containing module. - let import_resolutions = containing_module.import_resolutions.borrow(); - for (ident, target_import_resolution) in &*import_resolutions { - debug!("(resolving glob import) writing module resolution \ - {} into `{}`", - token::get_name(*ident), - self.module_to_string(module_)); - - if !target_import_resolution.is_public { - debug!("(resolving glob import) nevermind, just kidding"); - continue - } - - // Here we merge two import resolutions. - let mut import_resolutions = module_.import_resolutions.borrow_mut(); - match import_resolutions.get_mut(ident) { - Some(dest_import_resolution) => { - // Merge the two import resolutions at a finer-grained - // level. - - match target_import_resolution.value_target { - None => { - // Continue. - } - Some(ref value_target) => { - self.check_for_conflicting_import(&dest_import_resolution.value_target, - import_directive.span, - *ident, - ValueNS); - dest_import_resolution.value_target = Some(value_target.clone()); - } - } - match target_import_resolution.type_target { - None => { - // Continue. - } - Some(ref type_target) => { - self.check_for_conflicting_import(&dest_import_resolution.type_target, - import_directive.span, - *ident, - TypeNS); - dest_import_resolution.type_target = Some(type_target.clone()); - } - } - dest_import_resolution.is_public = is_public; - continue; - } - None => {} - } - - // Simple: just copy the old import resolution. - let mut new_import_resolution = ImportResolution::new(id, is_public); - new_import_resolution.value_target = - target_import_resolution.value_target.clone(); - new_import_resolution.type_target = - target_import_resolution.type_target.clone(); - - import_resolutions.insert(*ident, new_import_resolution); - } - - // Add all children from the containing module. - build_reduced_graph::populate_module_if_necessary(self, &containing_module); - - for (&name, name_bindings) in &*containing_module.children.borrow() { - self.merge_import_resolution(module_, - containing_module.clone(), - import_directive, - name, - name_bindings.clone()); - - } - - // Add external module children from the containing module. - for (&name, module) in &*containing_module.external_module_children.borrow() { - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module(module.clone())); - self.merge_import_resolution(module_, - containing_module.clone(), - import_directive, - name, - name_bindings); - } - - // Record the destination of this import - if let Some(did) = containing_module.def_id.get() { - self.def_map.borrow_mut().insert(id, PathResolution { - base_def: DefMod(did), - last_private: lp, - depth: 0 - }); - } - - debug!("(resolving glob import) successfully resolved import"); - return Success(()); - } - - fn merge_import_resolution(&mut self, - module_: &Module, - containing_module: Rc<Module>, - import_directive: &ImportDirective, - name: Name, - name_bindings: Rc<NameBindings>) { - let id = import_directive.id; - let is_public = import_directive.is_public; - - let mut import_resolutions = module_.import_resolutions.borrow_mut(); - let dest_import_resolution = import_resolutions.entry(name).get().unwrap_or_else( - |vacant_entry| { - // Create a new import resolution from this child. - vacant_entry.insert(ImportResolution::new(id, is_public)) - }); - - debug!("(resolving glob import) writing resolution `{}` in `{}` \ - to `{}`", - &token::get_name(name), - self.module_to_string(&*containing_module), - self.module_to_string(module_)); - - // Merge the child item into the import resolution. - { - let mut merge_child_item = |namespace| { - if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) { - let namespace_name = match namespace { - TypeNS => "type", - ValueNS => "value", - }; - debug!("(resolving glob import) ... for {} target", namespace_name); - if dest_import_resolution.shadowable(namespace) == Shadowable::Never { - let msg = format!("a {} named `{}` has already been imported \ - in this module", - namespace_name, - &token::get_name(name)); - span_err!(self.session, import_directive.span, E0251, "{}", msg); - } else { - let target = Target::new(containing_module.clone(), - name_bindings.clone(), - import_directive.shadowable); - dest_import_resolution.set_target_and_id(namespace, - Some(target), - id); - } - } - }; - merge_child_item(ValueNS); - merge_child_item(TypeNS); - } - - dest_import_resolution.is_public = is_public; - - self.check_for_conflicts_between_imports_and_items( - module_, - dest_import_resolution, - import_directive.span, - name); - } - - /// Checks that imported names and items don't have the same name. - fn check_for_conflicting_import(&mut self, - target: &Option<Target>, - import_span: Span, - name: Name, - namespace: Namespace) { - debug!("check_for_conflicting_import: {}; target exists: {}", - &token::get_name(name), - target.is_some()); - - match *target { - Some(ref target) if target.shadowable != Shadowable::Always => { - let msg = format!("a {} named `{}` has already been imported \ - in this module", - match namespace { - TypeNS => "type", - ValueNS => "value", - }, - &token::get_name(name)); - span_err!(self.session, import_span, E0252, "{}", &msg[..]); - } - Some(_) | None => {} - } - } - - /// Checks that an import is actually importable - fn check_that_import_is_importable(&mut self, - name_bindings: &NameBindings, - import_span: Span, - name: Name, - namespace: Namespace) { - if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) { - let msg = format!("`{}` is not directly importable", - token::get_name(name)); - span_err!(self.session, import_span, E0253, "{}", &msg[..]); - } - } - - /// Checks that imported names and items don't have the same name. - fn check_for_conflicts_between_imports_and_items(&mut self, - module: &Module, - import_resolution: - &ImportResolution, - import_span: Span, - name: Name) { - // First, check for conflicts between imports and `extern crate`s. - if module.external_module_children - .borrow() - .contains_key(&name) { - match import_resolution.type_target { - Some(ref target) if target.shadowable != Shadowable::Always => { - let msg = format!("import `{0}` conflicts with imported \ - crate in this module \ - (maybe you meant `use {0}::*`?)", - &token::get_name(name)); - span_err!(self.session, import_span, E0254, "{}", &msg[..]); - } - Some(_) | None => {} - } - } - - // Check for item conflicts. - let children = module.children.borrow(); - let name_bindings = match children.get(&name) { - None => { - // There can't be any conflicts. - return - } - Some(ref name_bindings) => (*name_bindings).clone(), - }; - - match import_resolution.value_target { - Some(ref target) if target.shadowable != Shadowable::Always => { - if let Some(ref value) = *name_bindings.value_def.borrow() { - span_err!(self.session, import_span, E0255, - "import `{}` conflicts with value in this module", - &token::get_name(name)); - if let Some(span) = value.value_span { - self.session.span_note(span, "conflicting value here"); - } - } - } - Some(_) | None => {} - } - - match import_resolution.type_target { - Some(ref target) if target.shadowable != Shadowable::Always => { - if let Some(ref ty) = *name_bindings.type_def.borrow() { - let (what, note) = if ty.module_def.is_some() { - ("existing submodule", "note conflicting module here") - } else { - ("type in this module", "note conflicting type here") - }; - span_err!(self.session, import_span, E0256, - "import `{}` conflicts with {}", - &token::get_name(name), what); - if let Some(span) = ty.type_span { - self.session.span_note(span, note); - } - } - } - Some(_) | None => {} - } - } - /// Checks that the names of external crates don't collide with other /// external crates. fn check_for_conflicts_between_external_crates(&self, @@ -1964,7 +996,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false) { Failed(None) => { let segment_name = token::get_name(name); - let module_name = self.module_to_string(&*search_module); + let module_name = module_to_string(&*search_module); let mut span = span; let msg = if "???" == &module_name[..] { span.hi = span.lo + Pos::from_usize(segment_name.len()); @@ -1972,10 +1004,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match search_parent_externals(name, &self.current_module) { Some(module) => { - let path_str = self.names_to_string(module_path); - let target_mod_str = self.module_to_string(&*module); + let path_str = names_to_string(module_path); + let target_mod_str = module_to_string(&*module); let current_mod_str = - self.module_to_string(&*self.current_module); + module_to_string(&*self.current_module); let prefix = if target_mod_str == current_mod_str { "self::".to_string() @@ -2066,8 +1098,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { assert!(module_path_len > 0); debug!("(resolving module path for import) processing `{}` rooted at `{}`", - self.names_to_string(module_path), - self.module_to_string(&*module_)); + names_to_string(module_path), + module_to_string(&*module_)); // Resolve the module prefix, if any. let module_prefix_result = self.resolve_module_prefix(module_.clone(), @@ -2078,7 +1110,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let last_private; match module_prefix_result { Failed(None) => { - let mpath = self.names_to_string(module_path); + let mpath = names_to_string(module_path); let mpath = &mpath[..]; match mpath.rfind(':') { Some(idx) => { @@ -2161,7 +1193,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { namespace {:?} in `{}`", token::get_name(name), namespace, - self.module_to_string(&*module_)); + module_to_string(&*module_)); // The current module node is handled specially. First, check for // its immediate children. @@ -2398,7 +1430,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { break } debug!("(resolving module prefix) resolving `super` at {}", - self.module_to_string(&*containing_module)); + module_to_string(&*containing_module)); match self.get_nearest_normal_module_parent(containing_module) { None => return Failed(None), Some(new_module) => { @@ -2409,7 +1441,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } debug!("(resolving module prefix) finished resolving prefix at {}", - self.module_to_string(&*containing_module)); + module_to_string(&*containing_module)); return Success(PrefixFound(containing_module, i)); } @@ -2429,7 +1461,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { -> ResolveResult<(Target, bool)> { debug!("(resolving name in module) resolving `{}` in `{}`", &token::get_name(name), - self.module_to_string(&*module_)); + module_to_string(&*module_)); // First, check the direct children of the module. build_reduced_graph::populate_module_if_necessary(self, &module_); @@ -2583,7 +1615,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { debug!("!!! (with scope) didn't find `{}` in `{}`", token::get_name(name), - self.module_to_string(&*orig_module)); + module_to_string(&*orig_module)); } Some(name_bindings) => { match (*name_bindings).get_module_if_available() { @@ -2591,7 +1623,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("!!! (with scope) didn't find module \ for `{}` in `{}`", token::get_name(name), - self.module_to_string(&*orig_module)); + module_to_string(&*orig_module)); } Some(module_) => { self.current_module = module_; @@ -2970,7 +2002,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } else { self.resolve_error(trait_path.span, &format!("`{}` is not a trait", - self.path_names_to_string(trait_path, path_depth))); + path_names_to_string(trait_path, path_depth))); // If it's a typedef, give a note if let DefTy(..) = path_res.base_def { @@ -2981,7 +2013,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } else { let msg = format!("use of undeclared trait name `{}`", - self.path_names_to_string(trait_path, path_depth)); + path_names_to_string(trait_path, path_depth)); self.resolve_error(trait_path.span, &msg); Err(()) } @@ -3097,7 +2129,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If there is a TraitRef in scope for an impl, then the method must be in the trait. if let Some((did, ref trait_ref)) = self.current_trait_ref { if !self.trait_item_map.contains_key(&(name, did)) { - let path_str = self.path_names_to_string(&trait_ref.path, 0); + let path_str = path_names_to_string(&trait_ref.path, 0); self.resolve_error(span, &format!("method `{}` is not a member of trait `{}`", token::get_name(name), @@ -3279,7 +2311,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ (id {}) = {:?}", - self.path_names_to_string(path, 0), + path_names_to_string(path, 0), ty.id, def); self.record_def(ty.id, def); } @@ -3294,7 +2326,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; let msg = format!("use of undeclared {} `{}`", kind, - self.path_names_to_string(path, 0)); + path_names_to_string(path, 0)); self.resolve_error(ty.span, &msg[..]); } } @@ -3465,7 +2497,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path, 0)); + path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } @@ -3718,7 +2750,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some((span, msg)) => (span, msg), None => { let msg = format!("Use of undeclared type or module `{}`", - self.names_to_string(&module_path)); + names_to_string(&module_path)); (span, msg) } }; @@ -3778,7 +2810,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some((span, msg)) => (span, msg), None => { let msg = format!("Use of undeclared module `::{}`", - self.names_to_string(&module_path[..])); + names_to_string(&module_path[..])); (span, msg) } }; @@ -3998,7 +3030,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(binding) = module.children.borrow().get(&name) { if let Some(DefMethod(did, _)) = binding.def_for_namespace(ValueNS) { if is_static_method(self, did) { - return StaticMethod(self.path_names_to_string(&path, 0)) + return StaticMethod(path_names_to_string(&path, 0)) } if self.current_trait_ref.is_some() { return TraitItem; @@ -4013,7 +3045,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some((trait_did, ref trait_ref)) = self.current_trait_ref { if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) { if is_static_method(self, did) { - return TraitMethod(self.path_names_to_string(&trait_ref.path, 0)); + return TraitMethod(path_names_to_string(&trait_ref.path, 0)); } else { return TraitItem; } @@ -4105,7 +3137,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(path_res) = resolution { // Check if struct variant if let DefVariant(_, _, true) = path_res.base_def { - let path_name = self.path_names_to_string(path, 0); + let path_name = path_names_to_string(path, 0); self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ this expression \ @@ -4123,7 +3155,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } else { // Write the result into the def map. debug!("(resolving expr) resolved `{}`", - self.path_names_to_string(path, 0)); + path_names_to_string(path, 0)); // Partial resolutions will need the set of traits in scope, // so they can be completed during typeck. @@ -4140,7 +3172,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // (The pattern matching def_tys where the id is in self.structs // matches on regular structs while excluding tuple- and enum-like // structs, which wouldn't result in this error.) - let path_name = self.path_names_to_string(path, 0); + let path_name = path_names_to_string(path, 0); let type_res = self.with_no_errors(|this| { this.resolve_path(expr.id, path, 0, TypeNS, false) }); @@ -4227,7 +3259,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { debug!("(resolving expression) didn't find struct def",); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path, 0)); + path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } @@ -4417,36 +3449,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // hit. // - /// A somewhat inefficient routine to obtain the name of a module. - fn module_to_string(&self, module: &Module) -> String { - let mut names = Vec::new(); - - fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) { - match module.parent_link { - NoParentLink => {} - ModuleParentLink(ref module, name) => { - names.push(name); - collect_mod(names, &*module.upgrade().unwrap()); - } - BlockParentLink(ref module, _) => { - // danger, shouldn't be ident? - names.push(special_idents::opaque.name); - collect_mod(names, &*module.upgrade().unwrap()); - } - } - } - collect_mod(&mut names, module); - - if names.len() == 0 { - return "???".to_string(); - } - self.names_to_string(&names.into_iter().rev() - .collect::<Vec<ast::Name>>()) - } - #[allow(dead_code)] // useful for debugging fn dump_module(&mut self, module_: Rc<Module>) { - debug!("Dump of module `{}`:", self.module_to_string(&*module_)); + debug!("Dump of module `{}`:", module_to_string(&*module_)); debug!("Children:"); build_reduced_graph::populate_module_if_necessary(self, &module_); @@ -4480,6 +3485,56 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } + +fn names_to_string(names: &[Name]) -> String { + let mut first = true; + let mut result = String::new(); + for name in names { + if first { + first = false + } else { + result.push_str("::") + } + result.push_str(&token::get_name(*name)); + }; + result +} + +fn path_names_to_string(path: &Path, depth: usize) -> String { + let names: Vec<ast::Name> = path.segments[..path.segments.len()-depth] + .iter() + .map(|seg| seg.identifier.name) + .collect(); + names_to_string(&names[..]) +} + +/// A somewhat inefficient routine to obtain the name of a module. +fn module_to_string(module: &Module) -> String { + let mut names = Vec::new(); + + fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) { + match module.parent_link { + NoParentLink => {} + ModuleParentLink(ref module, name) => { + names.push(name); + collect_mod(names, &*module.upgrade().unwrap()); + } + BlockParentLink(ref module, _) => { + // danger, shouldn't be ident? + names.push(special_idents::opaque.name); + collect_mod(names, &*module.upgrade().unwrap()); + } + } + } + collect_mod(&mut names, module); + + if names.len() == 0 { + return "???".to_string(); + } + names_to_string(&names.into_iter().rev().collect::<Vec<ast::Name>>()) +} + + pub struct CrateMap { pub def_map: DefMap, pub freevars: RefCell<FreevarMap>, @@ -4507,7 +3562,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, build_reduced_graph::build_reduced_graph(&mut resolver, krate); session.abort_if_errors(); - resolver.resolve_imports(); + resolve_imports::resolve_imports(&mut resolver); session.abort_if_errors(); record_exports::record(&mut resolver); diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 5d025f40d32..e953b6398f9 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -22,6 +22,7 @@ use {Module, NameBindings, Resolver}; use Namespace::{self, TypeNS, ValueNS}; use build_reduced_graph; +use module_to_string; use rustc::middle::def::Export; use syntax::ast; @@ -60,19 +61,19 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { // OK. Continue. debug!("(recording exports for module subtree) recording \ exports for local module `{}`", - self.module_to_string(&*module_)); + module_to_string(&*module_)); } None => { // Record exports for the root module. debug!("(recording exports for module subtree) recording \ exports for root module `{}`", - self.module_to_string(&*module_)); + module_to_string(&*module_)); } Some(_) => { // Bail out. debug!("(recording exports for module subtree) not recording \ exports for `{}`", - self.module_to_string(&*module_)); + module_to_string(&*module_)); return; } } @@ -133,13 +134,13 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, module_: &Module) { - for (name, importresolution) in &*module_.import_resolutions.borrow() { - if !importresolution.is_public { + for (name, import_resolution) in &*module_.import_resolutions.borrow() { + if !import_resolution.is_public { continue } let xs = [TypeNS, ValueNS]; for &ns in &xs { - match importresolution.target_for_namespace(ns) { + match import_resolution.target_for_namespace(ns) { Some(target) => { debug!("(computing exports) maybe export '{}'", token::get_name(*name)); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs new file mode 100644 index 00000000000..737ec71cab3 --- /dev/null +++ b/src/librustc_resolve/resolve_imports.rs @@ -0,0 +1,1021 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use self::ImportDirectiveSubclass::*; + +use {PUBLIC, IMPORTABLE}; +use Module; +use Namespace::{self, TypeNS, ValueNS}; +use NameBindings; +use NamespaceResult::{BoundResult, UnboundResult, UnknownResult}; +use NamespaceResult; +use NameSearchType; +use ResolveResult; +use Resolver; +use UseLexicalScopeFlag; +use {names_to_string, module_to_string}; + +use build_reduced_graph; + +use rustc::middle::def::*; +use rustc::middle::privacy::*; + +use syntax::ast::{DefId, NodeId, Name}; +use syntax::attr::AttrMetaMethods; +use syntax::parse::token; +use syntax::codemap::Span; + +use std::mem::replace; +use std::rc::Rc; + + +/// Contains data for specific types of import directives. +#[derive(Copy,Debug)] +pub enum ImportDirectiveSubclass { + SingleImport(Name /* target */, Name /* source */), + GlobImport +} + +/// Whether an import can be shadowed by another import. +#[derive(Debug,PartialEq,Clone,Copy)] +pub enum Shadowable { + Always, + Never +} + +/// One import directive. +#[derive(Debug)] +pub struct ImportDirective { + pub module_path: Vec<Name>, + pub subclass: ImportDirectiveSubclass, + pub span: Span, + pub id: NodeId, + pub is_public: bool, // see note in ImportResolution about how to use this + pub shadowable: Shadowable, +} + +impl ImportDirective { + pub fn new(module_path: Vec<Name> , + subclass: ImportDirectiveSubclass, + span: Span, + id: NodeId, + is_public: bool, + shadowable: Shadowable) + -> ImportDirective { + ImportDirective { + module_path: module_path, + subclass: subclass, + span: span, + id: id, + is_public: is_public, + shadowable: shadowable, + } + } +} + +/// The item that an import resolves to. +#[derive(Clone,Debug)] +pub struct Target { + pub target_module: Rc<Module>, + pub bindings: Rc<NameBindings>, + pub shadowable: Shadowable, +} + +impl Target { + pub fn new(target_module: Rc<Module>, + bindings: Rc<NameBindings>, + shadowable: Shadowable) + -> Target { + Target { + target_module: target_module, + bindings: bindings, + shadowable: shadowable, + } + } +} + +/// An ImportResolution represents a particular `use` directive. +#[derive(Debug)] +pub struct ImportResolution { + /// Whether this resolution came from a `use` or a `pub use`. Note that this + /// should *not* be used whenever resolution is being performed. Privacy + /// testing occurs during a later phase of compilation. + pub is_public: bool, + + // The number of outstanding references to this name. When this reaches + // zero, outside modules can count on the targets being correct. Before + // then, all bets are off; future imports could override this name. + // Note that this is usually either 0 or 1 - shadowing is forbidden the only + // way outstanding_references is > 1 in a legal program is if the name is + // used in both namespaces. + pub outstanding_references: uint, + + /// The value that this `use` directive names, if there is one. + pub value_target: Option<Target>, + /// The source node of the `use` directive leading to the value target + /// being non-none + pub value_id: NodeId, + + /// The type that this `use` directive names, if there is one. + pub type_target: Option<Target>, + /// The source node of the `use` directive leading to the type target + /// being non-none + pub type_id: NodeId, +} + +impl ImportResolution { + pub fn new(id: NodeId, is_public: bool) -> ImportResolution { + ImportResolution { + type_id: id, + value_id: id, + outstanding_references: 0, + value_target: None, + type_target: None, + is_public: is_public, + } + } + + pub fn target_for_namespace(&self, namespace: Namespace) + -> Option<Target> { + match namespace { + TypeNS => self.type_target.clone(), + ValueNS => self.value_target.clone(), + } + } + + pub fn id(&self, namespace: Namespace) -> NodeId { + match namespace { + TypeNS => self.type_id, + ValueNS => self.value_id, + } + } + + pub fn shadowable(&self, namespace: Namespace) -> Shadowable { + let target = self.target_for_namespace(namespace); + if target.is_none() { + return Shadowable::Always; + } + + target.unwrap().shadowable + } + + pub fn set_target_and_id(&mut self, + namespace: Namespace, + target: Option<Target>, + id: NodeId) { + match namespace { + TypeNS => { + self.type_target = target; + self.type_id = id; + } + ValueNS => { + self.value_target = target; + self.value_id = id; + } + } + } +} + + +struct ImportResolver<'a, 'b:'a, 'tcx:'b> { + resolver: &'a mut Resolver<'b, 'tcx> +} + +impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { + // Import resolution + // + // This is a fixed-point algorithm. We resolve imports until our efforts + // are stymied by an unresolved import; then we bail out of the current + // module and continue. We terminate successfully once no more imports + // remain or unsuccessfully when no forward progress in resolving imports + // is made. + + /// Resolves all imports for the crate. This method performs the fixed- + /// point iteration. + fn resolve_imports(&mut self) { + let mut i = 0; + let mut prev_unresolved_imports = 0; + loop { + debug!("(resolving imports) iteration {}, {} imports left", + i, self.resolver.unresolved_imports); + + let module_root = self.resolver.graph_root.get_module(); + self.resolve_imports_for_module_subtree(module_root.clone()); + + if self.resolver.unresolved_imports == 0 { + debug!("(resolving imports) success"); + break; + } + + if self.resolver.unresolved_imports == prev_unresolved_imports { + self.resolver.report_unresolved_imports(module_root); + break; + } + + i += 1; + prev_unresolved_imports = self.resolver.unresolved_imports; + } + } + + /// Attempts to resolve imports for the given module and all of its + /// submodules. + fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) { + debug!("(resolving imports for module subtree) resolving {}", + module_to_string(&*module_)); + let orig_module = replace(&mut self.resolver.current_module, module_.clone()); + self.resolve_imports_for_module(module_.clone()); + self.resolver.current_module = orig_module; + + build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); + for (_, child_node) in &*module_.children.borrow() { + match child_node.get_module_if_available() { + None => { + // Nothing to do. + } + Some(child_module) => { + self.resolve_imports_for_module_subtree(child_module); + } + } + } + + for (_, child_module) in &*module_.anonymous_children.borrow() { + self.resolve_imports_for_module_subtree(child_module.clone()); + } + } + + /// Attempts to resolve imports for the given module only. + fn resolve_imports_for_module(&mut self, module: Rc<Module>) { + if module.all_imports_resolved() { + debug!("(resolving imports for module) all imports resolved for \ + {}", + module_to_string(&*module)); + return; + } + + let imports = module.imports.borrow(); + let import_count = imports.len(); + while module.resolved_import_count.get() < import_count { + let import_index = module.resolved_import_count.get(); + let import_directive = &(*imports)[import_index]; + match self.resolve_import_for_module(module.clone(), + import_directive) { + ResolveResult::Failed(err) => { + let (span, help) = match err { + Some((span, msg)) => (span, format!(". {}", msg)), + None => (import_directive.span, String::new()) + }; + let msg = format!("unresolved import `{}`{}", + import_path_to_string( + &import_directive.module_path, + import_directive.subclass), + help); + self.resolver.resolve_error(span, &msg[..]); + } + ResolveResult::Indeterminate => break, // Bail out. We'll come around next time. + ResolveResult::Success(()) => () // Good. Continue. + } + + module.resolved_import_count + .set(module.resolved_import_count.get() + 1); + } + } + + /// Attempts to resolve the given import. The return value indicates + /// failure if we're certain the name does not exist, indeterminate if we + /// don't know whether the name exists at the moment due to other + /// currently-unresolved imports, or success if we know the name exists. + /// If successful, the resolved bindings are written into the module. + fn resolve_import_for_module(&mut self, + module_: Rc<Module>, + import_directive: &ImportDirective) + -> ResolveResult<()> { + let mut resolution_result = ResolveResult::Failed(None); + let module_path = &import_directive.module_path; + + debug!("(resolving import for module) resolving import `{}::...` in `{}`", + names_to_string(&module_path[..]), + module_to_string(&*module_)); + + // First, resolve the module path for the directive, if necessary. + let container = if module_path.len() == 0 { + // Use the crate root. + Some((self.resolver.graph_root.get_module(), LastMod(AllPublic))) + } else { + match self.resolver.resolve_module_path(module_.clone(), + &module_path[..], + UseLexicalScopeFlag::DontUseLexicalScope, + import_directive.span, + NameSearchType::ImportSearch) { + ResolveResult::Failed(err) => { + resolution_result = ResolveResult::Failed(err); + None + }, + ResolveResult::Indeterminate => { + resolution_result = ResolveResult::Indeterminate; + None + } + ResolveResult::Success(container) => Some(container), + } + }; + + match container { + None => {} + Some((containing_module, lp)) => { + // We found the module that the target is contained + // within. Attempt to resolve the import within it. + + match import_directive.subclass { + SingleImport(target, source) => { + resolution_result = + self.resolve_single_import(&module_, + containing_module, + target, + source, + import_directive, + lp); + } + GlobImport => { + resolution_result = + self.resolve_glob_import(&module_, + containing_module, + import_directive, + lp); + } + } + } + } + + // Decrement the count of unresolved imports. + match resolution_result { + ResolveResult::Success(()) => { + assert!(self.resolver.unresolved_imports >= 1); + self.resolver.unresolved_imports -= 1; + } + _ => { + // Nothing to do here; just return the error. + } + } + + // Decrement the count of unresolved globs if necessary. But only if + // the resolution result is indeterminate -- otherwise we'll stop + // processing imports here. (See the loop in + // resolve_imports_for_module). + + if !resolution_result.indeterminate() { + match import_directive.subclass { + GlobImport => { + assert!(module_.glob_count.get() >= 1); + module_.glob_count.set(module_.glob_count.get() - 1); + } + SingleImport(..) => { + // Ignore. + } + } + } + + return resolution_result; + } + + fn resolve_single_import(&mut self, + module_: &Module, + target_module: Rc<Module>, + target: Name, + source: Name, + directive: &ImportDirective, + lp: LastPrivate) + -> ResolveResult<()> { + debug!("(resolving single import) resolving `{}` = `{}::{}` from \ + `{}` id {}, last private {:?}", + token::get_name(target), + module_to_string(&*target_module), + token::get_name(source), + module_to_string(module_), + directive.id, + lp); + + let lp = match lp { + LastMod(lp) => lp, + LastImport {..} => { + self.resolver.session + .span_bug(directive.span, + "not expecting Import here, must be LastMod") + } + }; + + // We need to resolve both namespaces for this to succeed. + // + + let mut value_result = UnknownResult; + let mut type_result = UnknownResult; + + // Search for direct children of the containing module. + build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module); + + match target_module.children.borrow().get(&source) { + None => { + // Continue. + } + Some(ref child_name_bindings) => { + // pub_err makes sure we don't give the same error twice. + let mut pub_err = false; + if child_name_bindings.defined_in_namespace(ValueNS) { + debug!("(resolving single import) found value binding"); + value_result = BoundResult(target_module.clone(), + (*child_name_bindings).clone()); + if directive.is_public && !child_name_bindings.is_public(ValueNS) { + let msg = format!("`{}` is private", token::get_name(source)); + span_err!(self.resolver.session, directive.span, E0364, "{}", &msg); + pub_err = true; + } + } + if child_name_bindings.defined_in_namespace(TypeNS) { + debug!("(resolving single import) found type binding"); + type_result = BoundResult(target_module.clone(), + (*child_name_bindings).clone()); + if !pub_err && directive.is_public && !child_name_bindings.is_public(TypeNS) { + let msg = format!("`{}` is private", token::get_name(source)); + span_err!(self.resolver.session, directive.span, E0365, "{}", &msg); + } + } + } + } + + // Unless we managed to find a result in both namespaces (unlikely), + // search imports as well. + let mut value_used_reexport = false; + let mut type_used_reexport = false; + match (value_result.clone(), type_result.clone()) { + (BoundResult(..), BoundResult(..)) => {} // Continue. + _ => { + // If there is an unresolved glob at this point in the + // containing module, bail out. We don't know enough to be + // able to resolve this import. + + if target_module.glob_count.get() > 0 { + debug!("(resolving single import) unresolved glob; \ + bailing out"); + return ResolveResult::Indeterminate; + } + + // Now search the exported imports within the containing module. + match target_module.import_resolutions.borrow().get(&source) { + None => { + debug!("(resolving single import) no import"); + // The containing module definitely doesn't have an + // exported import with the name in question. We can + // therefore accurately report that the names are + // unbound. + + if value_result.is_unknown() { + value_result = UnboundResult; + } + if type_result.is_unknown() { + type_result = UnboundResult; + } + } + Some(import_resolution) + if import_resolution.outstanding_references == 0 => { + + fn get_binding(this: &mut Resolver, + import_resolution: &ImportResolution, + namespace: Namespace, + source: &Name) + -> NamespaceResult { + + // Import resolutions must be declared with "pub" + // in order to be exported. + if !import_resolution.is_public { + return UnboundResult; + } + + match import_resolution.target_for_namespace(namespace) { + None => { + return UnboundResult; + } + Some(Target { + target_module, + bindings, + shadowable: _ + }) => { + debug!("(resolving single import) found \ + import in ns {:?}", namespace); + let id = import_resolution.id(namespace); + // track used imports and extern crates as well + this.used_imports.insert((id, namespace)); + this.record_import_use(id, *source); + match target_module.def_id.get() { + Some(DefId{krate: kid, ..}) => { + this.used_crates.insert(kid); + }, + _ => {} + } + return BoundResult(target_module, bindings); + } + } + } + + // The name is an import which has been fully + // resolved. We can, therefore, just follow it. + if value_result.is_unknown() { + value_result = get_binding(self.resolver, + import_resolution, + ValueNS, + &source); + value_used_reexport = import_resolution.is_public; + } + if type_result.is_unknown() { + type_result = get_binding(self.resolver, + import_resolution, + TypeNS, + &source); + type_used_reexport = import_resolution.is_public; + } + + } + Some(_) => { + // If target_module is the same module whose import we are resolving + // and there it has an unresolved import with the same name as `source`, + // then the user is actually trying to import an item that is declared + // in the same scope + // + // e.g + // use self::submodule; + // pub mod submodule; + // + // In this case we continue as if we resolved the import and let the + // check_for_conflicts_between_imports_and_items call below handle + // the conflict + match (module_.def_id.get(), target_module.def_id.get()) { + (Some(id1), Some(id2)) if id1 == id2 => { + if value_result.is_unknown() { + value_result = UnboundResult; + } + if type_result.is_unknown() { + type_result = UnboundResult; + } + } + _ => { + // The import is unresolved. Bail out. + debug!("(resolving single import) unresolved import; \ + bailing out"); + return ResolveResult::Indeterminate; + } + } + } + } + } + } + + let mut value_used_public = false; + let mut type_used_public = false; + + // If we didn't find a result in the type namespace, search the + // external modules. + match type_result { + BoundResult(..) => {} + _ => { + match target_module.external_module_children.borrow_mut().get(&source).cloned() { + None => {} // Continue. + Some(module) => { + debug!("(resolving single import) found external module"); + // track the module as used. + match module.def_id.get() { + Some(DefId{krate: kid, ..}) => { + self.resolver.used_crates.insert(kid); + } + _ => {} + } + let name_bindings = + Rc::new(Resolver::create_name_bindings_from_module(module)); + type_result = BoundResult(target_module.clone(), name_bindings); + type_used_public = true; + } + } + } + } + + // We've successfully resolved the import. Write the results in. + let mut import_resolutions = module_.import_resolutions.borrow_mut(); + let import_resolution = &mut (*import_resolutions)[target]; + + { + let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| { + let namespace_name = match namespace { + TypeNS => "type", + ValueNS => "value", + }; + + match *result { + BoundResult(ref target_module, ref name_bindings) => { + debug!("(resolving single import) found {:?} target: {:?}", + namespace_name, + name_bindings.def_for_namespace(namespace)); + self.check_for_conflicting_import( + &import_resolution.target_for_namespace(namespace), + directive.span, + target, + namespace); + + self.check_that_import_is_importable( + &**name_bindings, + directive.span, + target, + namespace); + + let target = Some(Target::new(target_module.clone(), + name_bindings.clone(), + directive.shadowable)); + import_resolution.set_target_and_id(namespace, target, directive.id); + import_resolution.is_public = directive.is_public; + *used_public = name_bindings.defined_in_public_namespace(namespace); + } + UnboundResult => { /* Continue. */ } + UnknownResult => { + panic!("{:?} result should be known at this point", namespace_name); + } + } + }; + check_and_write_import(ValueNS, &value_result, &mut value_used_public); + check_and_write_import(TypeNS, &type_result, &mut type_used_public); + } + + self.check_for_conflicts_between_imports_and_items( + module_, + import_resolution, + directive.span, + target); + + if value_result.is_unbound() && type_result.is_unbound() { + let msg = format!("There is no `{}` in `{}`", + token::get_name(source), + module_to_string(&target_module)); + return ResolveResult::Failed(Some((directive.span, msg))); + } + let value_used_public = value_used_reexport || value_used_public; + let type_used_public = type_used_reexport || type_used_public; + + assert!(import_resolution.outstanding_references >= 1); + import_resolution.outstanding_references -= 1; + + // Record what this import resolves to for later uses in documentation, + // this may resolve to either a value or a type, but for documentation + // purposes it's good enough to just favor one over the other. + let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| { + let def = target.bindings.def_for_namespace(ValueNS).unwrap(); + (def, if value_used_public { lp } else { DependsOn(def.def_id()) }) + }); + let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| { + let def = target.bindings.def_for_namespace(TypeNS).unwrap(); + (def, if type_used_public { lp } else { DependsOn(def.def_id()) }) + }); + + let import_lp = LastImport { + value_priv: value_def_and_priv.map(|(_, p)| p), + value_used: Used, + type_priv: type_def_and_priv.map(|(_, p)| p), + type_used: Used + }; + + if let Some((def, _)) = value_def_and_priv { + self.resolver.def_map.borrow_mut().insert(directive.id, PathResolution { + base_def: def, + last_private: import_lp, + depth: 0 + }); + } + if let Some((def, _)) = type_def_and_priv { + self.resolver.def_map.borrow_mut().insert(directive.id, PathResolution { + base_def: def, + last_private: import_lp, + depth: 0 + }); + } + + debug!("(resolving single import) successfully resolved import"); + return ResolveResult::Success(()); + } + + // Resolves a glob import. Note that this function cannot fail; it either + // succeeds or bails out (as importing * from an empty module or a module + // that exports nothing is valid). target_module is the module we are + // actually importing, i.e., `foo` in `use foo::*`. + fn resolve_glob_import(&mut self, + module_: &Module, + target_module: Rc<Module>, + import_directive: &ImportDirective, + lp: LastPrivate) + -> ResolveResult<()> { + let id = import_directive.id; + let is_public = import_directive.is_public; + + // This function works in a highly imperative manner; it eagerly adds + // everything it can to the list of import resolutions of the module + // node. + debug!("(resolving glob import) resolving glob import {}", id); + + // We must bail out if the node has unresolved imports of any kind + // (including globs). + if !(*target_module).all_imports_resolved() { + debug!("(resolving glob import) target module has unresolved \ + imports; bailing out"); + return ResolveResult::Indeterminate; + } + + assert_eq!(target_module.glob_count.get(), 0); + + // Add all resolved imports from the containing module. + let import_resolutions = target_module.import_resolutions.borrow(); + for (ident, target_import_resolution) in &*import_resolutions { + debug!("(resolving glob import) writing module resolution \ + {} into `{}`", + token::get_name(*ident), + module_to_string(module_)); + + if !target_import_resolution.is_public { + debug!("(resolving glob import) nevermind, just kidding"); + continue + } + + // Here we merge two import resolutions. + let mut import_resolutions = module_.import_resolutions.borrow_mut(); + match import_resolutions.get_mut(ident) { + Some(dest_import_resolution) => { + // Merge the two import resolutions at a finer-grained + // level. + + match target_import_resolution.value_target { + None => { + // Continue. + } + Some(ref value_target) => { + self.check_for_conflicting_import(&dest_import_resolution.value_target, + import_directive.span, + *ident, + ValueNS); + dest_import_resolution.value_target = Some(value_target.clone()); + } + } + match target_import_resolution.type_target { + None => { + // Continue. + } + Some(ref type_target) => { + self.check_for_conflicting_import(&dest_import_resolution.type_target, + import_directive.span, + *ident, + TypeNS); + dest_import_resolution.type_target = Some(type_target.clone()); + } + } + dest_import_resolution.is_public = is_public; + continue; + } + None => {} + } + + // Simple: just copy the old import resolution. + let mut new_import_resolution = ImportResolution::new(id, is_public); + new_import_resolution.value_target = + target_import_resolution.value_target.clone(); + new_import_resolution.type_target = + target_import_resolution.type_target.clone(); + + import_resolutions.insert(*ident, new_import_resolution); + } + + // Add all children from the containing module. + build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module); + + for (&name, name_bindings) in &*target_module.children.borrow() { + self.merge_import_resolution(module_, + target_module.clone(), + import_directive, + name, + name_bindings.clone()); + + } + + // Add external module children from the containing module. + for (&name, module) in &*target_module.external_module_children.borrow() { + let name_bindings = + Rc::new(Resolver::create_name_bindings_from_module(module.clone())); + self.merge_import_resolution(module_, + target_module.clone(), + import_directive, + name, + name_bindings); + } + + // Record the destination of this import + if let Some(did) = target_module.def_id.get() { + self.resolver.def_map.borrow_mut().insert(id, PathResolution { + base_def: DefMod(did), + last_private: lp, + depth: 0 + }); + } + + debug!("(resolving glob import) successfully resolved import"); + return ResolveResult::Success(()); + } + + fn merge_import_resolution(&mut self, + module_: &Module, + containing_module: Rc<Module>, + import_directive: &ImportDirective, + name: Name, + name_bindings: Rc<NameBindings>) { + let id = import_directive.id; + let is_public = import_directive.is_public; + + let mut import_resolutions = module_.import_resolutions.borrow_mut(); + let dest_import_resolution = import_resolutions.entry(name).get().unwrap_or_else( + |vacant_entry| { + // Create a new import resolution from this child. + vacant_entry.insert(ImportResolution::new(id, is_public)) + }); + + debug!("(resolving glob import) writing resolution `{}` in `{}` \ + to `{}`", + &token::get_name(name), + module_to_string(&*containing_module), + module_to_string(module_)); + + // Merge the child item into the import resolution. + { + let mut merge_child_item = |namespace| { + if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) { + let namespace_name = match namespace { + TypeNS => "type", + ValueNS => "value", + }; + debug!("(resolving glob import) ... for {} target", namespace_name); + if dest_import_resolution.shadowable(namespace) == Shadowable::Never { + let msg = format!("a {} named `{}` has already been imported \ + in this module", + namespace_name, + &token::get_name(name)); + span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg); + } else { + let target = Target::new(containing_module.clone(), + name_bindings.clone(), + import_directive.shadowable); + dest_import_resolution.set_target_and_id(namespace, + Some(target), + id); + } + } + }; + merge_child_item(ValueNS); + merge_child_item(TypeNS); + } + + dest_import_resolution.is_public = is_public; + + self.check_for_conflicts_between_imports_and_items( + module_, + dest_import_resolution, + import_directive.span, + name); + } + + /// Checks that imported names and items don't have the same name. + fn check_for_conflicting_import(&mut self, + target: &Option<Target>, + import_span: Span, + name: Name, + namespace: Namespace) { + debug!("check_for_conflicting_import: {}; target exists: {}", + &token::get_name(name), + target.is_some()); + + match *target { + Some(ref target) if target.shadowable != Shadowable::Always => { + let msg = format!("a {} named `{}` has already been imported \ + in this module", + match namespace { + TypeNS => "type", + ValueNS => "value", + }, + &token::get_name(name)); + span_err!(self.resolver.session, import_span, E0252, "{}", &msg[..]); + } + Some(_) | None => {} + } + } + + /// Checks that an import is actually importable + fn check_that_import_is_importable(&mut self, + name_bindings: &NameBindings, + import_span: Span, + name: Name, + namespace: Namespace) { + if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) { + let msg = format!("`{}` is not directly importable", + token::get_name(name)); + span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]); + } + } + + /// Checks that imported names and items don't have the same name. + fn check_for_conflicts_between_imports_and_items(&mut self, + module: &Module, + import_resolution: + &ImportResolution, + import_span: Span, + name: Name) { + // First, check for conflicts between imports and `extern crate`s. + if module.external_module_children + .borrow() + .contains_key(&name) { + match import_resolution.type_target { + Some(ref target) if target.shadowable != Shadowable::Always => { + let msg = format!("import `{0}` conflicts with imported \ + crate in this module \ + (maybe you meant `use {0}::*`?)", + &token::get_name(name)); + span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]); + } + Some(_) | None => {} + } + } + + // Check for item conflicts. + let children = module.children.borrow(); + let name_bindings = match children.get(&name) { + None => { + // There can't be any conflicts. + return + } + Some(ref name_bindings) => (*name_bindings).clone(), + }; + + match import_resolution.value_target { + Some(ref target) if target.shadowable != Shadowable::Always => { + if let Some(ref value) = *name_bindings.value_def.borrow() { + span_err!(self.resolver.session, import_span, E0255, + "import `{}` conflicts with value in this module", + &token::get_name(name)); + if let Some(span) = value.value_span { + self.resolver.session.span_note(span, "conflicting value here"); + } + } + } + Some(_) | None => {} + } + + match import_resolution.type_target { + Some(ref target) if target.shadowable != Shadowable::Always => { + if let Some(ref ty) = *name_bindings.type_def.borrow() { + let (what, note) = if ty.module_def.is_some() { + ("existing submodule", "note conflicting module here") + } else { + ("type in this module", "note conflicting type here") + }; + span_err!(self.resolver.session, import_span, E0256, + "import `{}` conflicts with {}", + &token::get_name(name), what); + if let Some(span) = ty.type_span { + self.resolver.session.span_note(span, note); + } + } + } + Some(_) | None => {} + } + } +} + +fn import_path_to_string(names: &[Name], + subclass: ImportDirectiveSubclass) + -> String { + if names.is_empty() { + import_directive_subclass_to_string(subclass) + } else { + (format!("{}::{}", + names_to_string(names), + import_directive_subclass_to_string(subclass))).to_string() + } +} + +fn import_directive_subclass_to_string(subclass: ImportDirectiveSubclass) -> String { + match subclass { + SingleImport(_, source) => { + token::get_name(source).to_string() + } + GlobImport => "*".to_string() + } +} + +pub fn resolve_imports(resolver: &mut Resolver) { + let mut import_resolver = ImportResolver { + resolver: resolver, + }; + import_resolver.resolve_imports(); +} diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 3087a8ea45d..34a23f3efac 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -626,12 +626,7 @@ fn link_rlib<'a>(sess: &'a Session, e)) } - let bc_data_deflated = match flate::deflate_bytes(&bc_data[..]) { - Some(compressed) => compressed, - None => sess.fatal(&format!("failed to compress bytecode \ - from {}", - bc_filename.display())) - }; + let bc_data_deflated = flate::deflate_bytes(&bc_data[..]); let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) { Ok(file) => file, diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index db9966e0548..a3ab863c4ec 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -21,7 +21,6 @@ use libc; use flate; use std::ffi::CString; -use std::iter; use std::mem; use std::num::Int; @@ -62,7 +61,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let file = path.file_name().unwrap().to_str().unwrap(); let file = &file[3..file.len() - 5]; // chop off lib/.rlib debug!("reading {}", file); - for i in iter::count(0, 1) { + for i in 0.. { let bc_encoded = time(sess.time_passes(), &format!("check for {}.{}.bytecode.deflate", name, i), (), @@ -96,8 +95,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint)]; match flate::inflate_bytes(compressed_data) { - Some(inflated) => inflated, - None => { + Ok(inflated) => inflated, + Err(_) => { sess.fatal(&format!("failed to decompress bc of `{}`", name)) } @@ -112,8 +111,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, // the object must be in the old, pre-versioning format, so simply // inflate everything and let LLVM decide if it can make sense of it match flate::inflate_bytes(bc_encoded) { - Some(bc) => bc, - None => { + Ok(bc) => bc, + Err(_) => { sess.fatal(&format!("failed to decompress bc of `{}`", name)) } @@ -213,4 +212,3 @@ fn read_from_le_bytes<T: Int>(bytes: &[u8], position_in_bytes: uint) -> T { Int::from_le(data) } - diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index ccf24f7e859..e9f58ec53df 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2974,10 +2974,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> { let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item); let metadata = encoder::encode_metadata(encode_parms, krate); let mut compressed = encoder::metadata_encoding_version.to_vec(); - compressed.push_all(&match flate::deflate_bytes(&metadata) { - Some(compressed) => compressed, - None => cx.sess().fatal("failed to compress metadata"), - }); + compressed.push_all(&flate::deflate_bytes(&metadata)); let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]); let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false); let name = format!("rust_metadata_{}_{}", diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index a5c3923336a..2fd79c1ddb4 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -293,7 +293,7 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } SaveIn(lldest) => { match ty::eval_repeat_count(bcx.tcx(), &**count_expr) { - 0 => bcx, + 0 => expr::trans_into(bcx, &**element, Ignore), 1 => expr::trans_into(bcx, &**element, SaveIn(lldest)), count => { let elem = unpack_datum!(bcx, expr::trans(bcx, &**element)); @@ -410,8 +410,12 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>, { let _icx = push_ctxt("tvec::iter_vec_loop"); - let fcx = bcx.fcx; + if bcx.unreachable.get() { + return bcx; + } + + let fcx = bcx.fcx; let loop_bcx = fcx.new_temp_block("expr_repeat"); let next_bcx = fcx.new_temp_block("expr_repeat: next"); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 718804d317f..1f7cc3bb647 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -289,11 +289,87 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { ty::ty_param(p) => { self.assemble_inherent_candidates_from_param(self_ty, p); } + ty::ty_char => { + let lang_def_id = self.tcx().lang_items.char_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_str => { + let lang_def_id = self.tcx().lang_items.str_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_vec(_, None) => { + let lang_def_id = self.tcx().lang_items.slice_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => { + let lang_def_id = self.tcx().lang_items.const_ptr_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => { + let lang_def_id = self.tcx().lang_items.mut_ptr_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI8) => { + let lang_def_id = self.tcx().lang_items.i8_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI16) => { + let lang_def_id = self.tcx().lang_items.i16_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI32) => { + let lang_def_id = self.tcx().lang_items.i32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI64) => { + let lang_def_id = self.tcx().lang_items.i64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyIs(_)) => { + let lang_def_id = self.tcx().lang_items.isize_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU8) => { + let lang_def_id = self.tcx().lang_items.u8_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU16) => { + let lang_def_id = self.tcx().lang_items.u16_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU32) => { + let lang_def_id = self.tcx().lang_items.u32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU64) => { + let lang_def_id = self.tcx().lang_items.u64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyUs(_)) => { + let lang_def_id = self.tcx().lang_items.usize_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_float(ast::TyF32) => { + let lang_def_id = self.tcx().lang_items.f32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_float(ast::TyF64) => { + let lang_def_id = self.tcx().lang_items.f64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } _ => { } } } + fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<ast::DefId>) { + if let Some(impl_def_id) = lang_def_id { + ty::populate_implementations_for_primitive_if_necessary(self.tcx(), impl_def_id); + + self.assemble_inherent_impl_probe(impl_def_id); + } + } + fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) { // Read the inherent implementation candidates for this type from the // metadata if necessary. diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 5dfe80cfcb2..ab694d26b15 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -16,6 +16,7 @@ use middle::ty; use syntax::ast::{Item, ItemImpl}; use syntax::ast; use syntax::ast_util; +use syntax::codemap::Span; use syntax::visit; use util::ppaux::{Repr, UserString}; @@ -38,6 +39,23 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { } } + fn check_primitive_impl(&self, + impl_def_id: ast::DefId, + lang_def_id: Option<ast::DefId>, + lang: &str, + ty: &str, + span: Span) { + match lang_def_id { + Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ }, + _ => { + self.tcx.sess.span_err( + span, + &format!("only a single inherent implementation marked with `#[lang = \"{}\"]` \ + is allowed for the `{}` primitive", lang, ty)); + } + } + } + /// Checks exactly one impl for orphan rules and other such /// restrictions. In this fn, it can happen that multiple errors /// apply to a specific impl, so just return after reporting one @@ -62,6 +80,125 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { ty::ty_uniq(..) => { self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap()); } + ty::ty_char => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.char_impl(), + "char", + "char", + item.span); + } + ty::ty_str => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.str_impl(), + "str", + "str", + item.span); + } + ty::ty_vec(_, None) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.slice_impl(), + "slice", + "[T]", + item.span); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.const_ptr_impl(), + "const_ptr", + "*const T", + item.span); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.mut_ptr_impl(), + "mut_ptr", + "*mut T", + item.span); + } + ty::ty_int(ast::TyI8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i8_impl(), + "i8", + "i8", + item.span); + } + ty::ty_int(ast::TyI16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i16_impl(), + "i16", + "i16", + item.span); + } + ty::ty_int(ast::TyI32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i32_impl(), + "i32", + "i32", + item.span); + } + ty::ty_int(ast::TyI64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i64_impl(), + "i64", + "i64", + item.span); + } + ty::ty_int(ast::TyIs(_)) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.isize_impl(), + "isize", + "isize", + item.span); + } + ty::ty_uint(ast::TyU8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u8_impl(), + "u8", + "u8", + item.span); + } + ty::ty_uint(ast::TyU16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u16_impl(), + "u16", + "u16", + item.span); + } + ty::ty_uint(ast::TyU32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u32_impl(), + "u32", + "u32", + item.span); + } + ty::ty_uint(ast::TyU64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u64_impl(), + "u64", + "u64", + item.span); + } + ty::ty_uint(ast::TyUs(_)) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.usize_impl(), + "usize", + "usize", + item.span); + } + ty::ty_float(ast::TyF32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f32_impl(), + "f32", + "f32", + item.span); + } + ty::ty_float(ast::TyF64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f64_impl(), + "f64", + "f64", + item.span); + } _ => { span_err!(self.tcx.sess, item.span, E0118, "no base type found for inherent implementation; \ diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index dba7b16ecee..f97470dbaed 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -34,6 +34,7 @@ //! both occur before the crate is rendered. pub use self::ExternalLocation::*; +use std::ascii::OwnedAsciiExt; use std::cell::RefCell; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; @@ -239,6 +240,51 @@ struct IndexItem { path: String, desc: String, parent: Option<ast::DefId>, + search_type: Option<IndexItemFunctionType>, +} + +/// A type used for the search index. +struct Type { + name: Option<String>, +} + +impl fmt::Display for Type { + /// Formats type as {name: $name}. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Wrapping struct fmt should never call us when self.name is None, + // but just to be safe we write `null` in that case. + match self.name { + Some(ref n) => write!(f, "{{\"name\":\"{}\"}}", n), + None => write!(f, "null") + } + } +} + +/// Full type of functions/methods in the search index. +struct IndexItemFunctionType { + inputs: Vec<Type>, + output: Option<Type> +} + +impl fmt::Display for IndexItemFunctionType { + /// Formats a full fn type as a JSON {inputs: [Type], outputs: Type/null}. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // If we couldn't figure out a type, just write `null`. + if self.inputs.iter().any(|ref i| i.name.is_none()) || + (self.output.is_some() && self.output.as_ref().unwrap().name.is_none()) { + return write!(f, "null") + } + + let inputs: Vec<String> = self.inputs.iter().map(|ref t| format!("{}", t)).collect(); + try!(write!(f, "{{\"inputs\":[{}],\"output\":", inputs.connect(","))); + + match self.output { + Some(ref t) => try!(write!(f, "{}", t)), + None => try!(write!(f, "null")) + }; + + Ok(try!(write!(f, "}}"))) + } } // TLS keys used to carry information around during rendering. @@ -407,8 +453,9 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> { ty: shortty(item), name: item.name.clone().unwrap(), path: fqp[..fqp.len() - 1].connect("::"), - desc: shorter(item.doc_value()).to_string(), + desc: shorter(item.doc_value()), parent: Some(did), + search_type: None, }); }, None => {} @@ -458,7 +505,11 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> { let pathid = *nodeid_to_pathid.get(&nodeid).unwrap(); try!(write!(&mut w, ",{}", pathid)); } - None => {} + None => try!(write!(&mut w, ",null")) + } + match item.search_type { + Some(ref t) => try!(write!(&mut w, ",{}", t)), + None => try!(write!(&mut w, ",null")) } try!(write!(&mut w, "]")); } @@ -872,12 +923,21 @@ impl DocFolder for Cache { match parent { (parent, Some(path)) if is_method || (!self.privmod && !hidden_field) => { + // Needed to determine `self` type. + let parent_basename = self.parent_stack.first().and_then(|parent| { + match self.paths.get(parent) { + Some(&(ref fqp, _)) => Some(fqp[fqp.len() - 1].clone()), + _ => None + } + }); + self.search_index.push(IndexItem { ty: shortty(&item), name: s.to_string(), path: path.connect("::").to_string(), - desc: shorter(item.doc_value()).to_string(), + desc: shorter(item.doc_value()), parent: parent, + search_type: get_index_search_type(&item, parent_basename), }); } (Some(parent), None) if is_method || (!self.privmod && !hidden_field)=> { @@ -1467,13 +1527,14 @@ fn full_path(cx: &Context, item: &clean::Item) -> String { return s } -fn shorter<'a>(s: Option<&'a str>) -> &'a str { +fn shorter<'a>(s: Option<&'a str>) -> String { match s { - Some(s) => match s.find("\n\n") { - Some(pos) => &s[..pos], - None => s, - }, - None => "" + Some(s) => s.lines().take_while(|line|{ + (*line).chars().any(|chr|{ + !chr.is_whitespace() + }) + }).collect::<Vec<_>>().connect("\n"), + None => "".to_string() } } @@ -1603,7 +1664,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, </tr> ", *myitem.name.as_ref().unwrap(), - Markdown(shorter(myitem.doc_value())), + Markdown(&shorter(myitem.doc_value())[..]), class = shortty(myitem), href = item_path(myitem), title = full_path(cx, myitem), @@ -2307,6 +2368,52 @@ fn make_item_keywords(it: &clean::Item) -> String { format!("{}, {}", get_basic_keywords(), it.name.as_ref().unwrap()) } +fn get_index_search_type(item: &clean::Item, + parent: Option<String>) -> Option<IndexItemFunctionType> { + let decl = match item.inner { + clean::FunctionItem(ref f) => &f.decl, + clean::MethodItem(ref m) => &m.decl, + clean::TyMethodItem(ref m) => &m.decl, + _ => return None + }; + + let mut inputs = Vec::new(); + + // Consider `self` an argument as well. + if let Some(name) = parent { + inputs.push(Type { name: Some(name.into_ascii_lowercase()) }); + } + + inputs.extend(&mut decl.inputs.values.iter().map(|arg| { + get_index_type(&arg.type_) + })); + + let output = match decl.output { + clean::FunctionRetTy::Return(ref return_type) => Some(get_index_type(return_type)), + _ => None + }; + + Some(IndexItemFunctionType { inputs: inputs, output: output }) +} + +fn get_index_type(clean_type: &clean::Type) -> Type { + Type { name: get_index_type_name(clean_type).map(|s| s.into_ascii_lowercase()) } +} + +fn get_index_type_name(clean_type: &clean::Type) -> Option<String> { + match *clean_type { + clean::ResolvedPath { ref path, .. } => { + let segments = &path.segments; + Some(segments[segments.len() - 1].name.clone()) + }, + clean::Generic(ref s) => Some(s.clone()), + clean::Primitive(ref p) => Some(format!("{:?}", p)), + clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_), + // FIXME: add all from clean::Type. + _ => None + } +} + pub fn cache() -> Arc<Cache> { CACHE_KEY.with(|c| c.borrow().clone()) } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 9fa8cf7941e..ca6d9441957 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -209,6 +209,33 @@ break; } } + // searching by type + } else if (val.search("->") > -1) { + var trimmer = function (s) { return s.trim(); }; + var parts = val.split("->").map(trimmer); + var input = parts[0]; + // sort inputs so that order does not matter + var inputs = input.split(",").map(trimmer).sort(); + var output = parts[1]; + + for (var i = 0; i < nSearchWords; ++i) { + var type = searchIndex[i].type; + if (!type) { + continue; + } + + // sort index inputs so that order does not matter + var typeInputs = type.inputs.map(function (input) { + return input.name; + }).sort(); + + // allow searching for void (no output) functions as well + var typeOutput = type.output ? type.output.name : ""; + if (inputs.toString() === typeInputs.toString() && + output == typeOutput) { + results.push({id: i, index: -1, dontValidate: true}); + } + } } else { // gather matching search results up to a certain maximum val = val.replace(/\_/g, ""); @@ -329,6 +356,11 @@ path = result.item.path.toLowerCase(), parent = result.item.parent; + // this validation does not make sense when searching by types + if (result.dontValidate) { + continue; + } + var valid = validateResult(name, path, split, parent); if (!valid) { result.id = -1; @@ -573,7 +605,8 @@ // (String) name, // (String) full path or empty string for previous path, // (String) description, - // (optional Number) the parent path index to `paths`] + // (Number | null) the parent path index to `paths`] + // (Object | null) the type of the function (if any) var items = rawSearchIndex[crate].items; // an array of [(Number) item type, // (String) name] @@ -598,7 +631,7 @@ var rawRow = items[i]; var row = {crate: crate, ty: rawRow[0], name: rawRow[1], path: rawRow[2] || lastPath, desc: rawRow[3], - parent: paths[rawRow[4]]}; + parent: paths[rawRow[4]], type: rawRow[5]}; searchIndex.push(row); if (typeof row.name === "string") { var word = row.name.toLowerCase(); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 152b6f5c80a..bd4177861dd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -26,7 +26,7 @@ #![feature(core)] #![feature(exit_status)] #![feature(int_uint)] -#![feature(set_panic)] +#![feature(set_stdio)] #![feature(libc)] #![feature(old_path)] #![feature(rustc_private)] diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index d0ef89e811b..366b90cfbfd 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -204,6 +204,7 @@ use std::io::prelude::*; use std::io; use std::mem::{swap}; use std::num::FpCategory as Fp; +#[cfg(stage0)] use std::num::{Float, Int}; use std::ops::Index; use std::str::FromStr; @@ -2622,7 +2623,6 @@ mod tests { StackElement, Stack, Decoder, Encoder, EncoderError}; use std::{i64, u64, f32, f64}; use std::collections::BTreeMap; - use std::num::Float; use std::string; #[derive(RustcDecodable, Eq, PartialEq, Debug)] diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 8b275d1bc4a..93215090d95 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -16,8 +16,8 @@ use prelude::v1::*; +use ops::Range; use mem; -use iter::Range; /// Extension methods for ASCII-subset only operations on owned strings #[unstable(feature = "std_misc", @@ -270,7 +270,7 @@ pub fn escape_default(c: u8) -> EscapeDefault { _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), }; - return EscapeDefault { range: range(0, len), data: data }; + return EscapeDefault { range: (0.. len), data: data }; fn hexify(b: u8) -> u8 { match b { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 18f86901b8f..6f8151c2b9f 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -23,6 +23,7 @@ use hash::{Hash, SipHasher}; use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map}; use marker::Sized; use mem::{self, replace}; +#[cfg(stage0)] use num::{Int, UnsignedInt}; use ops::{Deref, FnMut, Index, IndexMut}; use option::Option::{self, Some, None}; @@ -217,6 +218,11 @@ fn test_resize_policy() { /// It is required that the keys implement the `Eq` and `Hash` traits, although /// this can frequently be achieved by using `#[derive(Eq, Hash)]`. /// +/// It is a logic error for a key to be modified in such a way that the key's +/// hash, as determined by the `Hash` trait, or its equality, as determined by +/// the `Eq` trait, changes while it is in the map. This is normally only +/// possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. +/// /// Relevant papers/articles: /// /// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf) diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 35115ad77fe..de3f080de82 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -38,6 +38,12 @@ use super::state::HashState; /// HashMap where the value is (). As with the `HashMap` type, a `HashSet` /// requires that the elements implement the `Eq` and `Hash` traits. /// +/// It is a logic error for an item to be modified in such a way that the +/// item's hash, as determined by the `Hash` trait, or its equality, as +/// determined by the `Eq` trait, changes while it is in the set. This is +/// normally only possible through `Cell`, `RefCell`, global state, I/O, or +/// unsafe code. +/// /// # Examples /// /// ``` diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 69fd0a57d5f..cba46859f34 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -19,12 +19,16 @@ use iter::{Iterator, IteratorExt, ExactSizeIterator, count}; use marker::{Copy, Send, Sync, Sized, self}; use mem::{min_align_of, size_of}; use mem; +#[cfg(stage0)] use num::{Int, UnsignedInt}; use num::wrapping::{OverflowingOps, WrappingOps}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{Some, None}; +#[cfg(stage0)] use ptr::{self, PtrExt, Unique}; +#[cfg(not(stage0))] +use ptr::{self, Unique}; use rt::heap::{allocate, deallocate, EMPTY}; use collections::hash_state::HashState; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 90373441edc..d06b027adf6 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -272,7 +272,9 @@ mod dl { use ptr; use result::Result; use result::Result::{Ok, Err}; + #[cfg(stage0)] use slice::SliceExt; + #[cfg(stage0)] use str::StrExt; use str; use string::String; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 11e8f24f523..4b6fbe01f76 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -452,7 +452,7 @@ pub fn get_exit_status() -> i32 { EXIT_STATUS.load(Ordering::SeqCst) as i32 } -/// An iterator over the arguments of a process, yielding an `String` value +/// An iterator over the arguments of a process, yielding a `String` value /// for each argument. /// /// This structure is created through the `std::env::args` method. diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 677894ba6e4..48526f2bf2d 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -22,7 +22,11 @@ use old_io; use ops::Deref; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::{self, SliceExt}; +#[cfg(not(stage0))] +use slice; +#[cfg(stage0)] use str::StrExt; use string::String; use vec::Vec; diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index 825a11c3464..ba89b3a0ea6 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -124,7 +124,7 @@ impl File { /// This function will return an error if `path` does not already exist. /// Other errors may also be returned according to `OpenOptions::open`. #[stable(feature = "rust1", since = "1.0.0")] - pub fn open<P: AsPath + ?Sized>(path: &P) -> io::Result<File> { + pub fn open<P: AsPath>(path: P) -> io::Result<File> { OpenOptions::new().read(true).open(path) } @@ -135,7 +135,7 @@ impl File { /// /// See the `OpenOptions::open` function for more details. #[stable(feature = "rust1", since = "1.0.0")] - pub fn create<P: AsPath + ?Sized>(path: &P) -> io::Result<File> { + pub fn create<P: AsPath>(path: P) -> io::Result<File> { OpenOptions::new().write(true).create(true).truncate(true).open(path) } @@ -297,7 +297,7 @@ impl OpenOptions { /// permissions for /// * Filesystem-level errors (full disk, etc) #[stable(feature = "rust1", since = "1.0.0")] - pub fn open<P: AsPath + ?Sized>(&self, path: &P) -> io::Result<File> { + pub fn open<P: AsPath>(&self, path: P) -> io::Result<File> { let path = path.as_path(); let inner = try!(fs_imp::File::open(path, &self.0)); Ok(File { path: path.to_path_buf(), inner: inner }) @@ -410,7 +410,7 @@ impl DirEntry { /// user lacks permissions to remove the file, or if some other filesystem-level /// error occurs. #[stable(feature = "rust1", since = "1.0.0")] -pub fn remove_file<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { +pub fn remove_file<P: AsPath>(path: P) -> io::Result<()> { fs_imp::unlink(path.as_path()) } @@ -438,7 +438,7 @@ pub fn remove_file<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { /// permissions to perform a `metadata` call on the given `path` or if there /// is no entry in the filesystem at the provided path. #[stable(feature = "rust1", since = "1.0.0")] -pub fn metadata<P: AsPath + ?Sized>(path: &P) -> io::Result<Metadata> { +pub fn metadata<P: AsPath>(path: P) -> io::Result<Metadata> { fs_imp::stat(path.as_path()).map(Metadata) } @@ -459,8 +459,7 @@ pub fn metadata<P: AsPath + ?Sized>(path: &P) -> io::Result<Metadata> { /// reside on separate filesystems, or if some other intermittent I/O error /// occurs. #[stable(feature = "rust1", since = "1.0.0")] -pub fn rename<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q) - -> io::Result<()> { +pub fn rename<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<()> { fs_imp::rename(from.as_path(), to.as_path()) } @@ -490,9 +489,9 @@ pub fn rename<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q) /// * The current process does not have the permission rights to access /// `from` or write `to` #[stable(feature = "rust1", since = "1.0.0")] -pub fn copy<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q) - -> io::Result<u64> { +pub fn copy<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<u64> { let from = from.as_path(); + let to = to.as_path(); if !from.is_file() { return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation, "the source path is not an existing file", @@ -513,8 +512,7 @@ pub fn copy<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q) /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. #[stable(feature = "rust1", since = "1.0.0")] -pub fn hard_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q) - -> io::Result<()> { +pub fn hard_link<P: AsPath, Q: AsPath>(src: P, dst: Q) -> io::Result<()> { fs_imp::link(src.as_path(), dst.as_path()) } @@ -522,8 +520,7 @@ pub fn hard_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q) /// /// The `dst` path will be a soft link pointing to the `src` path. #[stable(feature = "rust1", since = "1.0.0")] -pub fn soft_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q) - -> io::Result<()> { +pub fn soft_link<P: AsPath, Q: AsPath>(src: P, dst: Q) -> io::Result<()> { fs_imp::symlink(src.as_path(), dst.as_path()) } @@ -535,7 +532,7 @@ pub fn soft_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q) /// reading a file that does not exist or reading a file that is not a soft /// link. #[stable(feature = "rust1", since = "1.0.0")] -pub fn read_link<P: AsPath + ?Sized>(path: &P) -> io::Result<PathBuf> { +pub fn read_link<P: AsPath>(path: P) -> io::Result<PathBuf> { fs_imp::readlink(path.as_path()) } @@ -554,7 +551,7 @@ pub fn read_link<P: AsPath + ?Sized>(path: &P) -> io::Result<PathBuf> { /// This function will return an error if the user lacks permissions to make a /// new directory at the provided `path`, or if the directory already exists. #[stable(feature = "rust1", since = "1.0.0")] -pub fn create_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { +pub fn create_dir<P: AsPath>(path: P) -> io::Result<()> { fs_imp::mkdir(path.as_path()) } @@ -568,7 +565,7 @@ pub fn create_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { /// error conditions for when a directory is being created (after it is /// determined to not exist) are outlined by `fs::create_dir`. #[stable(feature = "rust1", since = "1.0.0")] -pub fn create_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { +pub fn create_dir_all<P: AsPath>(path: P) -> io::Result<()> { let path = path.as_path(); if path.is_dir() { return Ok(()) } if let Some(p) = path.parent() { try!(create_dir_all(p)) } @@ -590,7 +587,7 @@ pub fn create_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { /// This function will return an error if the user lacks permissions to remove /// the directory at the provided `path`, or if the directory isn't empty. #[stable(feature = "rust1", since = "1.0.0")] -pub fn remove_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { +pub fn remove_dir<P: AsPath>(path: P) -> io::Result<()> { fs_imp::rmdir(path.as_path()) } @@ -604,7 +601,7 @@ pub fn remove_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { /// /// See `file::remove_file` and `fs::remove_dir` #[stable(feature = "rust1", since = "1.0.0")] -pub fn remove_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { +pub fn remove_dir_all<P: AsPath>(path: P) -> io::Result<()> { let path = path.as_path(); for child in try!(read_dir(path)) { let child = try!(child).path(); @@ -657,7 +654,7 @@ pub fn remove_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> { /// the process lacks permissions to view the contents or if the `path` points /// at a non-directory file #[stable(feature = "rust1", since = "1.0.0")] -pub fn read_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<ReadDir> { +pub fn read_dir<P: AsPath>(path: P) -> io::Result<ReadDir> { fs_imp::readdir(path.as_path()).map(ReadDir) } @@ -673,7 +670,7 @@ pub fn read_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<ReadDir> { reason = "the precise semantics and defaults for a recursive walk \ may change and this may end up accounting for files such \ as symlinks differently")] -pub fn walk_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<WalkDir> { +pub fn walk_dir<P: AsPath>(path: P) -> io::Result<WalkDir> { let start = try!(read_dir(path)); Ok(WalkDir { cur: Some(start), stack: Vec::new() }) } @@ -759,8 +756,8 @@ impl PathExt for Path { reason = "the argument type of u64 is not quite appropriate for \ this function and may change if the standard library \ gains a type to represent a moment in time")] -pub fn set_file_times<P: AsPath + ?Sized>(path: &P, accessed: u64, - modified: u64) -> io::Result<()> { +pub fn set_file_times<P: AsPath>(path: P, accessed: u64, + modified: u64) -> io::Result<()> { fs_imp::utimes(path.as_path(), accessed, modified) } @@ -788,8 +785,7 @@ pub fn set_file_times<P: AsPath + ?Sized>(path: &P, accessed: u64, reason = "a more granual ability to set specific permissions may \ be exposed on the Permissions structure itself and this \ method may not always exist")] -pub fn set_permissions<P: AsPath + ?Sized>(path: &P, perm: Permissions) - -> io::Result<()> { +pub fn set_permissions<P: AsPath>(path: P, perm: Permissions) -> io::Result<()> { fs_imp::set_perm(path.as_path(), perm.0) } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 3fddaaad807..d1231f549bb 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -9,10 +9,6 @@ // except according to those terms. //! Traits, helpers, and type definitions for core I/O functionality. -//! -//! > **NOTE**: This module is very much a work in progress and is under active -//! > development. At this time it is still recommended to use the `old_io` -//! > module while the details of this module shake out. #![stable(feature = "rust1", since = "1.0.0")] @@ -24,12 +20,19 @@ use iter::Iterator; use marker::Sized; use ops::{Drop, FnOnce}; use option::Option::{self, Some, None}; +#[cfg(stage0)] use ptr::PtrExt; use result::Result::{Ok, Err}; use result; +#[cfg(stage0)] use slice::{self, SliceExt}; +#[cfg(not(stage0))] +use slice; use string::String; +#[cfg(stage0)] use str::{self, StrExt}; +#[cfg(not(stage0))] +use str; use vec::Vec; pub use self::buffered::{BufReader, BufWriter, BufStream, LineWriter}; @@ -37,10 +40,10 @@ pub use self::buffered::IntoInnerError; pub use self::cursor::Cursor; pub use self::error::{Result, Error, ErrorKind}; pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; -pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr}; +pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr}; pub use self::stdio::{StdoutLock, StderrLock, StdinLock}; #[doc(no_inline, hidden)] -pub use self::stdio::set_panic; +pub use self::stdio::{set_panic, set_print}; #[macro_use] mod lazy; @@ -360,7 +363,7 @@ pub trait Write { /// /// It is considered an error if not all bytes could be written due to /// I/O errors or EOF being reached. - #[unstable(feature = "io", reason = "waiting for RFC 950")] + #[stable(feature = "rust1", since = "1.0.0")] fn flush(&mut self) -> Result<()>; /// Attempts to write an entire buffer into this write. diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 3b4e396953d..75d047d5c9c 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -11,6 +11,7 @@ use prelude::v1::*; use io::prelude::*; +use cell::RefCell; use cmp; use fmt; use io::lazy::Lazy; @@ -18,23 +19,30 @@ use io::{self, BufReader, LineWriter}; use sync::{Arc, Mutex, MutexGuard}; use sys::stdio; +/// Stdout used by print! and println! macroses +thread_local! { + static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = { + RefCell::new(None) + } +} + /// A handle to a raw instance of the standard input stream of this process. /// /// This handle is not synchronized or buffered in any fashion. Constructed via -/// the `std::io::stdin_raw` function. -pub struct StdinRaw(stdio::Stdin); +/// the `std::io::stdio::stdin_raw` function. +struct StdinRaw(stdio::Stdin); /// A handle to a raw instance of the standard output stream of this process. /// /// This handle is not synchronized or buffered in any fashion. Constructed via -/// the `std::io::stdout_raw` function. -pub struct StdoutRaw(stdio::Stdout); +/// the `std::io::stdio::stdout_raw` function. +struct StdoutRaw(stdio::Stdout); /// A handle to a raw instance of the standard output stream of this process. /// /// This handle is not synchronized or buffered in any fashion. Constructed via -/// the `std::io::stderr_raw` function. -pub struct StderrRaw(stdio::Stderr); +/// the `std::io::stdio::stderr_raw` function. +struct StderrRaw(stdio::Stderr); /// Construct a new raw handle to the standard input of this process. /// @@ -43,7 +51,7 @@ pub struct StderrRaw(stdio::Stderr); /// handles is **not** available to raw handles returned from this function. /// /// The returned handle has no external synchronization or buffering. -pub fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) } +fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) } /// Construct a new raw handle to the standard input stream of this process. /// @@ -54,7 +62,7 @@ pub fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) } /// /// The returned handle has no external synchronization or buffering layered on /// top. -pub fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) } +fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) } /// Construct a new raw handle to the standard input stream of this process. /// @@ -63,7 +71,7 @@ pub fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) } /// /// The returned handle has no external synchronization or buffering layered on /// top. -pub fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) } +fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) } impl Read for StdinRaw { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } @@ -109,9 +117,6 @@ pub struct StdinLock<'a> { /// The `Read` trait is implemented for the returned value but the `BufRead` /// trait is not due to the global nature of the standard input stream. The /// locked version, `StdinLock`, implements both `Read` and `BufRead`, however. -/// -/// To avoid locking and buffering altogether, it is recommended to use the -/// `stdin_raw` constructor. #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init); @@ -224,9 +229,6 @@ pub struct StdoutLock<'a> { /// provided via the `lock` method. /// /// The returned handle implements the `Write` trait. -/// -/// To avoid locking and buffering altogether, it is recommended to use the -/// `stdout_raw` constructor. #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init); @@ -297,9 +299,6 @@ pub struct StderrLock<'a> { /// this function. No handles are buffered, however. /// /// The returned handle implements the `Write` trait. -/// -/// To avoid locking altogether, it is recommended to use the `stderr_raw` -/// constructor. #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init); @@ -347,15 +346,15 @@ impl<'a> Write for StderrLock<'a> { fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } -/// Resets the task-local stdout handle to the specified writer +/// Resets the task-local stderr handle to the specified writer /// -/// This will replace the current task's stdout handle, returning the old -/// handle. All future calls to `print` and friends will emit their output to +/// This will replace the current task's stderr handle, returning the old +/// handle. All future calls to `panic!` and friends will emit their output to /// this specified handle. /// /// Note that this does not need to be called for all new tasks; the default -/// output handle is to the process's stdout stream. -#[unstable(feature = "set_panic", +/// output handle is to the process's stderr stream. +#[unstable(feature = "set_stdio", reason = "this function may disappear completely or be replaced \ with a more general mechanism")] #[doc(hidden)] @@ -369,3 +368,37 @@ pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> { Some(s) }) } + +/// Resets the task-local stdout handle to the specified writer +/// +/// This will replace the current task's stdout handle, returning the old +/// handle. All future calls to `print!` and friends will emit their output to +/// this specified handle. +/// +/// Note that this does not need to be called for all new tasks; the default +/// output handle is to the process's stdout stream. +#[unstable(feature = "set_stdio", + reason = "this function may disappear completely or be replaced \ + with a more general mechanism")] +#[doc(hidden)] +pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> { + use mem; + LOCAL_STDOUT.with(move |slot| { + mem::replace(&mut *slot.borrow_mut(), Some(sink)) + }).and_then(|mut s| { + let _ = s.flush(); + Some(s) + }) +} + +#[unstable(feature = "print", + reason = "implementation detail which may disappear or be replaced at any time")] +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + if let Err(e) = LOCAL_STDOUT.with(|s| match s.borrow_mut().as_mut() { + Some(w) => w.write_fmt(args), + None => stdout().write_fmt(args) + }) { + panic!("failed printing to stdout: {}", e); + } +} diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 995544c49a4..e1ef3062794 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -60,19 +60,21 @@ macro_rules! panic { }); } +/// Macro for printing to the standard output. +/// /// Equivalent to the `println!` macro except that a newline is not printed at /// the end of the message. #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] macro_rules! print { - ($($arg:tt)*) => ($crate::old_io::stdio::print_args(format_args!($($arg)*))) + ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); } -/// Macro for printing to a task's stdout handle. +/// Macro for printing to the standard output. /// -/// Each task can override its stdout handle via `std::old_io::stdio::set_stdout`. -/// The syntax of this macro is the same as that used for `format!`. For more -/// information, see `std::fmt` and `std::old_io::stdio`. +/// Use the `format!` syntax to write data to the standard output. +/// See `std::fmt` for more information. /// /// # Examples /// @@ -83,7 +85,8 @@ macro_rules! print { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! println { - ($($arg:tt)*) => ($crate::old_io::stdio::println_args(format_args!($($arg)*))) + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } /// Helper macro for unwrapping `Result` values while returning early with an diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 101aae3eb24..702f81db8e2 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -15,150 +15,220 @@ use hash; use io; use libc::{self, socklen_t, sa_family_t}; use mem; -use net::{IpAddr, lookup_host, ntoh, hton}; +use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr}; use option; use sys_common::{FromInner, AsInner, IntoInner}; use vec; -/// Representation of a socket address for networking applications +/// Representation of a socket address for networking applications. /// -/// A socket address consists of at least an (ip, port) pair and may also -/// contain other information depending on the protocol. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct SocketAddr { - repr: Repr, +/// A socket address can either represent the IPv4 or IPv6 protocol and is +/// paired with at least a port number as well. Each protocol may have more +/// specific information about the address available to it as well. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum SocketAddr { + /// An IPv4 socket address which is a (ip, port) combination. + #[stable(feature = "rust1", since = "1.0.0")] + V4(SocketAddrV4), + /// An IPv6 socket address + #[stable(feature = "rust1", since = "1.0.0")] + V6(SocketAddrV6), } +/// An IPv4 socket address which is a (ip, port) combination. #[derive(Copy)] -enum Repr { - V4(libc::sockaddr_in), - V6(libc::sockaddr_in6), -} +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV4 { inner: libc::sockaddr_in } + +/// An IPv6 socket address +#[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV6 { inner: libc::sockaddr_in6 } impl SocketAddr { + /// Gets the port number associated with this socket address + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { + match *self { + SocketAddr::V4(ref a) => a.port(), + SocketAddr::V6(ref a) => a.port(), + } + } +} + +impl SocketAddrV4 { /// Creates a new socket address from the (ip, port) pair. - pub fn new(ip: IpAddr, port: u16) -> SocketAddr { - let repr = match ip { - IpAddr::V4(ref ip) => { - Repr::V4(libc::sockaddr_in { - sin_family: libc::AF_INET as sa_family_t, - sin_port: hton(port), - sin_addr: *ip.as_inner(), - .. unsafe { mem::zeroed() } - }) - } - IpAddr::V6(ref ip) => { - Repr::V6(libc::sockaddr_in6 { - sin6_family: libc::AF_INET6 as sa_family_t, - sin6_port: hton(port), - sin6_addr: *ip.as_inner(), - .. unsafe { mem::zeroed() } - }) - } - }; - SocketAddr { repr: repr } + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { + SocketAddrV4 { + inner: libc::sockaddr_in { + sin_family: libc::AF_INET as sa_family_t, + sin_port: hton(port), + sin_addr: *ip.as_inner(), + .. unsafe { mem::zeroed() } + }, + } } /// Gets the IP address associated with this socket address. - pub fn ip(&self) -> IpAddr { - match self.repr { - Repr::V4(ref sa) => IpAddr::V4(FromInner::from_inner(sa.sin_addr)), - Repr::V6(ref sa) => IpAddr::V6(FromInner::from_inner(sa.sin6_addr)), + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ip(&self) -> &Ipv4Addr { + unsafe { + &*(&self.inner.sin_addr as *const libc::in_addr as *const Ipv4Addr) } } /// Gets the port number associated with this socket address - pub fn port(&self) -> u16 { - match self.repr { - Repr::V4(ref sa) => ntoh(sa.sin_port), - Repr::V6(ref sa) => ntoh(sa.sin6_port), - } - } + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) } +} - fn set_port(&mut self, port: u16) { - match self.repr { - Repr::V4(ref mut sa) => sa.sin_port = hton(port), - Repr::V6(ref mut sa) => sa.sin6_port = hton(port), +impl SocketAddrV6 { + /// Creates a new socket address from the ip/port/flowinfo/scope_id + /// components. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) + -> SocketAddrV6 { + SocketAddrV6 { + inner: libc::sockaddr_in6 { + sin6_family: libc::AF_INET6 as sa_family_t, + sin6_port: hton(port), + sin6_addr: *ip.as_inner(), + sin6_flowinfo: hton(flowinfo), + sin6_scope_id: hton(scope_id), + .. unsafe { mem::zeroed() } + }, } } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for SocketAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.repr { - Repr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()), - Repr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()), + /// Gets the IP address associated with this socket address. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ip(&self) -> &Ipv6Addr { + unsafe { + &*(&self.inner.sin6_addr as *const libc::in6_addr as *const Ipv6Addr) } } + + /// Gets the port number associated with this socket address + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { ntoh(self.inner.sin6_port) } + + /// Gets scope ID associated with this address, corresponding to the + /// `sin6_flowinfo` field in C. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn flowinfo(&self) -> u32 { ntoh(self.inner.sin6_flowinfo) } + + /// Gets scope ID associated with this address, corresponding to the + /// `sin6_scope_id` field in C. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn scope_id(&self) -> u32 { ntoh(self.inner.sin6_scope_id) } } -impl FromInner<libc::sockaddr_in> for SocketAddr { - fn from_inner(addr: libc::sockaddr_in) -> SocketAddr { - SocketAddr { repr: Repr::V4(addr) } +impl FromInner<libc::sockaddr_in> for SocketAddrV4 { + fn from_inner(addr: libc::sockaddr_in) -> SocketAddrV4 { + SocketAddrV4 { inner: addr } } } -impl FromInner<libc::sockaddr_in6> for SocketAddr { - fn from_inner(addr: libc::sockaddr_in6) -> SocketAddr { - SocketAddr { repr: Repr::V6(addr) } +impl FromInner<libc::sockaddr_in6> for SocketAddrV6 { + fn from_inner(addr: libc::sockaddr_in6) -> SocketAddrV6 { + SocketAddrV6 { inner: addr } } } impl<'a> IntoInner<(*const libc::sockaddr, socklen_t)> for &'a SocketAddr { fn into_inner(self) -> (*const libc::sockaddr, socklen_t) { - match self.repr { - Repr::V4(ref a) => { + match *self { + SocketAddr::V4(ref a) => { (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) } - Repr::V6(ref a) => { + SocketAddr::V6(ref a) => { (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) } } } } -impl fmt::Debug for SocketAddr { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + SocketAddr::V4(ref a) => a.fmt(f), + SocketAddr::V6(ref a) => a.fmt(f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV4 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}", self.ip(), self.port()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV4 { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } -impl Clone for Repr { - fn clone(&self) -> Repr { *self } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV6 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{}]:{}", self.ip(), self.port()) + } } -impl PartialEq for Repr { - fn eq(&self, other: &Repr) -> bool { - match (*self, *other) { - (Repr::V4(ref a), Repr::V4(ref b)) => { - a.sin_port == b.sin_port && - a.sin_addr.s_addr == b.sin_addr.s_addr - } - (Repr::V6(ref a), Repr::V6(ref b)) => { - a.sin6_port == b.sin6_port && - a.sin6_addr.s6_addr == b.sin6_addr.s6_addr && - a.sin6_flowinfo == b.sin6_flowinfo && - a.sin6_scope_id == b.sin6_scope_id - } - _ => false, - } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV6 { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SocketAddrV4 { + fn clone(&self) -> SocketAddrV4 { *self } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SocketAddrV6 { + fn clone(&self) -> SocketAddrV6 { *self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for SocketAddrV4 { + fn eq(&self, other: &SocketAddrV4) -> bool { + self.inner.sin_port == other.inner.sin_port && + self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr } } -impl Eq for Repr {} +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for SocketAddrV6 { + fn eq(&self, other: &SocketAddrV6) -> bool { + self.inner.sin6_port == other.inner.sin6_port && + self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr && + self.inner.sin6_flowinfo == other.inner.sin6_flowinfo && + self.inner.sin6_scope_id == other.inner.sin6_scope_id + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for SocketAddrV4 {} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for SocketAddrV6 {} #[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for Repr { +impl hash::Hash for SocketAddrV4 { fn hash<H: hash::Hasher>(&self, s: &mut H) { - match *self { - Repr::V4(ref a) => { - (a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s) - } - Repr::V6(ref a) => { - (a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr, - a.sin6_flowinfo, a.sin6_scope_id).hash(s) - } - } + (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for SocketAddrV6 { + fn hash<H: hash::Hasher>(&self, s: &mut H) { + (self.inner.sin6_port, &self.inner.sin6_addr.s6_addr, + self.inner.sin6_flowinfo, self.inner.sin6_scope_id).hash(s) } } @@ -168,12 +238,13 @@ impl hash::Hash for Repr { /// This trait is used for generic address resolution when constructing network /// objects. By default it is implemented for the following types: /// -/// * `SocketAddr` - `to_socket_addrs` is identity function. +/// * `SocketAddr`, `SocketAddrV4`, `SocketAddrV6` - `to_socket_addrs` is +/// identity function. /// -/// * `(IpAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially. +/// * `(IpvNAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially. /// /// * `(&str, u16)` - the string should be either a string representation of an -/// IP address expected by `FromStr` implementation for `IpAddr` or a host +/// IP address expected by `FromStr` implementation for `IpvNAddr` or a host /// name. /// /// * `&str` - the string should be either a string representation of a @@ -192,18 +263,18 @@ impl hash::Hash for Repr { /// Some examples: /// /// ```no_run -/// use std::net::{IpAddr, SocketAddr, TcpStream, UdpSocket, TcpListener}; +/// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr}; /// /// fn main() { -/// let ip = IpAddr::new_v4(127, 0, 0, 1); +/// let ip = Ipv4Addr::new(127, 0, 0, 1); /// let port = 12345; /// /// // The following lines are equivalent modulo possible "localhost" name /// // resolution differences -/// let tcp_s = TcpStream::connect(&SocketAddr::new(ip, port)); -/// let tcp_s = TcpStream::connect(&(ip, port)); -/// let tcp_s = TcpStream::connect(&("127.0.0.1", port)); -/// let tcp_s = TcpStream::connect(&("localhost", port)); +/// let tcp_s = TcpStream::connect(SocketAddrV4::new(ip, port)); +/// let tcp_s = TcpStream::connect((ip, port)); +/// let tcp_s = TcpStream::connect(("127.0.0.1", port)); +/// let tcp_s = TcpStream::connect(("localhost", port)); /// let tcp_s = TcpStream::connect("127.0.0.1:12345"); /// let tcp_s = TcpStream::connect("localhost:12345"); /// @@ -211,13 +282,15 @@ impl hash::Hash for Repr { /// // behave similarly /// let tcp_l = TcpListener::bind("localhost:12345"); /// -/// let mut udp_s = UdpSocket::bind(&("127.0.0.1", port)).unwrap(); -/// udp_s.send_to(&[7], &(ip, 23451)); +/// let mut udp_s = UdpSocket::bind(("127.0.0.1", port)).unwrap(); +/// udp_s.send_to(&[7], (ip, 23451)); /// } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub trait ToSocketAddrs { /// Returned iterator over socket addresses which this type may correspond /// to. + #[stable(feature = "rust1", since = "1.0.0")] type Iter: Iterator<Item=SocketAddr>; /// Converts this object to an iterator of resolved `SocketAddr`s. @@ -231,9 +304,11 @@ pub trait ToSocketAddrs { /// # Errors /// /// Any errors encountered during resolution will be returned as an `Err`. + #[stable(feature = "rust1", since = "1.0.0")] fn to_socket_addrs(&self) -> io::Result<Self::Iter>; } +#[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for SocketAddr { type Iter = option::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { @@ -241,31 +316,72 @@ impl ToSocketAddrs for SocketAddr { } } -impl ToSocketAddrs for (IpAddr, u16) { +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for SocketAddrV4 { + type Iter = option::IntoIter<SocketAddr>; + fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { + SocketAddr::V4(*self).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for SocketAddrV6 { + type Iter = option::IntoIter<SocketAddr>; + fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { + SocketAddr::V6(*self).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (Ipv4Addr, u16) { + type Iter = option::IntoIter<SocketAddr>; + fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { + let (ip, port) = *self; + SocketAddrV4::new(ip, port).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (Ipv6Addr, u16) { type Iter = option::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { let (ip, port) = *self; - Ok(Some(SocketAddr::new(ip, port)).into_iter()) + SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs() } } fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> { let ips = try!(lookup_host(s)); let v: Vec<_> = try!(ips.map(|a| { - a.map(|mut a| { a.set_port(p); a }) + a.map(|a| { + match a { + SocketAddr::V4(ref a) => { + SocketAddr::V4(SocketAddrV4::new(*a.ip(), p)) + } + SocketAddr::V6(ref a) => { + SocketAddr::V6(SocketAddrV6::new(*a.ip(), p, a.flowinfo(), + a.scope_id())) + } + } + }) }).collect()); Ok(v.into_iter()) } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> ToSocketAddrs for (&'a str, u16) { type Iter = vec::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { let (host, port) = *self; - // try to parse the host as a regular IpAddr first - match host.parse().ok() { - Some(addr) => return Ok(vec![SocketAddr::new(addr, port)].into_iter()), - None => {} + // try to parse the host as a regular IP address first + if let Ok(addr) = host.parse::<Ipv4Addr>() { + let addr = SocketAddrV4::new(addr, port); + return Ok(vec![SocketAddr::V4(addr)].into_iter()) + } + if let Ok(addr) = host.parse::<Ipv6Addr>() { + let addr = SocketAddrV6::new(addr, port, 0, 0); + return Ok(vec![SocketAddr::V6(addr)].into_iter()) } resolve_socket_addr(host, port) @@ -273,6 +389,7 @@ impl<'a> ToSocketAddrs for (&'a str, u16) { } // accepts strings like 'localhost:12345' +#[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for str { type Iter = vec::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { @@ -322,16 +439,16 @@ mod tests { assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse()); // out of range - let none: Option<IpAddr> = "256.0.0.1".parse().ok(); + let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok(); assert_eq!(None, none); // too short - let none: Option<IpAddr> = "255.0.0".parse().ok(); + let none: Option<Ipv4Addr> = "255.0.0".parse().ok(); assert_eq!(None, none); // too long - let none: Option<IpAddr> = "255.0.0.1.2".parse().ok(); + let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok(); assert_eq!(None, none); // no number between dots - let none: Option<IpAddr> = "255.0..1".parse().ok(); + let none: Option<Ipv4Addr> = "255.0..1".parse().ok(); assert_eq!(None, none); } @@ -347,19 +464,19 @@ mod tests { "2a02:6b8::11:11".parse()); // too long group - let none: Option<IpAddr> = "::00000".parse().ok(); + let none: Option<Ipv6Addr> = "::00000".parse().ok(); assert_eq!(None, none); // too short - let none: Option<IpAddr> = "1:2:3:4:5:6:7".parse().ok(); + let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok(); assert_eq!(None, none); // too long - let none: Option<IpAddr> = "1:2:3:4:5:6:7:8:9".parse().ok(); + let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok(); assert_eq!(None, none); // triple colon - let none: Option<IpAddr> = "1:2:::6:7:8".parse().ok(); + let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok(); assert_eq!(None, none); // two double colons - let none: Option<IpAddr> = "1:2::6::8".parse().ok(); + let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok(); assert_eq!(None, none); } @@ -375,24 +492,24 @@ mod tests { "2001:db8:122:c000:2:2100:192.0.2.33".parse()); // colon after v4 - let none: Option<IpAddr> = "::127.0.0.1:".parse().ok(); + let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok(); assert_eq!(None, none); // not enough groups - let none: Option<IpAddr> = "1.2.3.4.5:127.0.0.1".parse().ok(); + let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok(); assert_eq!(None, none); // too many groups - let none: Option<IpAddr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); + let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); assert_eq!(None, none); } #[test] fn test_from_str_socket_addr() { - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 80)), - "77.88.21.11:80".parse()); - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), - "[2a02:6b8:0:1::1]:53".parse()); - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), - "[::127.0.0.1]:22".parse()); + assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), + "77.88.21.11:80".parse()); + assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), + "[2a02:6b8:0:1::1]:53".parse()); + assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), + "[::127.0.0.1]:22".parse()); // without port let none: Option<SocketAddr> = "127.0.0.1".parse().ok(); @@ -555,39 +672,47 @@ mod tests { #[test] fn to_socket_addr_socketaddr() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 12345); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345); assert_eq!(Ok(vec![a]), tsa(a)); } + fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { + SocketAddr::V4(SocketAddrV4::new(a, p)) + } + + fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr { + SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0)) + } + #[test] fn to_socket_addr_ipaddr_u16() { - let a = IpAddr::new_v4(77, 88, 21, 11); + let a = Ipv4Addr::new(77, 88, 21, 11); let p = 12345; - let e = SocketAddr::new(a, p); + let e = SocketAddr::V4(SocketAddrV4::new(a, p)); assert_eq!(Ok(vec![e]), tsa((a, p))); } #[test] fn to_socket_addr_str_u16() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 24352); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352))); - let a = SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); + let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53))); - let a = SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), 23924); + let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); assert!(tsa(("localhost", 23924)).unwrap().contains(&a)); } #[test] fn to_socket_addr_str() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 24352); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); assert_eq!(Ok(vec![a]), tsa("77.88.21.11:24352")); - let a = SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); + let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53")); - let a = SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), 23924); + let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); assert!(tsa("localhost:23924").unwrap().contains(&a)); } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index d699886e577..c5f2ae53d22 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "ip", reason = "extra functionality has not been \ + scrutinized to the level that it should \ + be stable")] + use prelude::v1::*; use cmp::Ordering; @@ -19,12 +23,14 @@ use net::{hton, ntoh}; /// Representation of an IPv4 address. #[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv4Addr { inner: libc::in_addr, } /// Representation of an IPv6 address. #[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv6Addr { inner: libc::in6_addr, } @@ -41,46 +47,11 @@ pub enum Ipv6MulticastScope { Global } -/// Enumeration of possible IP addresses -#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] -pub enum IpAddr { - /// An IPv4 address. - V4(Ipv4Addr), - /// An IPv6 address. - V6(Ipv6Addr) -} - -impl IpAddr { - /// Create a new IpAddr that contains an IPv4 address. - /// - /// The result will represent the IP address a.b.c.d - pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr { - IpAddr::V4(Ipv4Addr::new(a, b, c, d)) - } - - /// Create a new IpAddr that contains an IPv6 address. - /// - /// The result will represent the IP address a:b:c:d:e:f - pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, - h: u16) -> IpAddr { - IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for IpAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - IpAddr::V4(v4) => v4.fmt(f), - IpAddr::V6(v6) => v6.fmt(f) - } - } -} - impl Ipv4Addr { /// Create a new IPv4 address from four eight-bit octets. /// /// The result will represent the IP address a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { Ipv4Addr { inner: libc::in_addr { @@ -93,6 +64,7 @@ impl Ipv4Addr { } /// Returns the four eight-bit integers that make up this address + #[stable(feature = "rust1", since = "1.0.0")] pub fn octets(&self) -> [u8; 4] { let bits = ntoh(self.inner.s_addr); [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] @@ -148,6 +120,7 @@ impl Ipv4Addr { /// Convert this address to an IPv4-compatible IPv6 address /// /// a.b.c.d becomes ::a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_compatible(&self) -> Ipv6Addr { Ipv6Addr::new(0, 0, 0, 0, 0, 0, ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, @@ -157,6 +130,7 @@ impl Ipv4Addr { /// Convert this address to an IPv4-mapped IPv6 address /// /// a.b.c.d becomes ::ffff:a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_mapped(&self) -> Ipv6Addr { Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, @@ -165,6 +139,7 @@ impl Ipv4Addr { } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let octets = self.octets(); @@ -172,21 +147,26 @@ impl fmt::Display for Ipv4Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for Ipv4Addr { fn clone(&self) -> Ipv4Addr { *self } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Ipv4Addr { fn eq(&self, other: &Ipv4Addr) -> bool { self.inner.s_addr == other.inner.s_addr } } + +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ipv4Addr {} #[stable(feature = "rust1", since = "1.0.0")] @@ -196,12 +176,14 @@ impl hash::Hash for Ipv4Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv4Addr { fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { Some(self.cmp(other)) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv4Addr { fn cmp(&self, other: &Ipv4Addr) -> Ordering { self.inner.s_addr.cmp(&other.inner.s_addr) @@ -221,6 +203,7 @@ impl Ipv6Addr { /// Create a new IPv6 address from eight 16-bit segments. /// /// The result will represent the IP address a:b:c:d:e:f + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { Ipv6Addr { @@ -232,6 +215,7 @@ impl Ipv6Addr { } /// Return the eight 16-bit segments that make up this address + #[stable(feature = "rust1", since = "1.0.0")] pub fn segments(&self) -> [u16; 8] { [ntoh(self.inner.s6_addr[0]), ntoh(self.inner.s6_addr[1]), @@ -324,6 +308,7 @@ impl Ipv6Addr { /// neither IPv4-compatible or IPv4-mapped. /// /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv4(&self) -> Option<Ipv4Addr> { match self.segments() { [0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => { @@ -335,6 +320,7 @@ impl Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv6Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.segments() { @@ -359,7 +345,7 @@ impl fmt::Display for Ipv6Addr { let mut cur_span_len = 0; let mut cur_span_at = 0; - for i in range(0, 8) { + for i in 0..8 { if segments[i] == 0 { if cur_span_len == 0 { cur_span_at = i; @@ -405,21 +391,26 @@ impl fmt::Display for Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Ipv6Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for Ipv6Addr { fn clone(&self) -> Ipv6Addr { *self } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Ipv6Addr { fn eq(&self, other: &Ipv6Addr) -> bool { self.inner.s6_addr == other.inner.s6_addr } } + +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ipv6Addr {} #[stable(feature = "rust1", since = "1.0.0")] @@ -429,12 +420,14 @@ impl hash::Hash for Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv6Addr { fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { Some(self.cmp(other)) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv6Addr { fn cmp(&self, other: &Ipv6Addr) -> Ordering { self.inner.s6_addr.cmp(&other.inner.s6_addr) diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index b8cb8cb5289..36f36af73e1 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -11,10 +11,9 @@ //! Networking primitives for TCP/UDP communication //! //! > **NOTE**: This module is very much a work in progress and is under active -//! > development. At this time it is still recommended to use the `old_io` -//! > module while the details of this module shake out. +//! > development. -#![unstable(feature = "net")] +#![stable(feature = "rust1", since = "1.0.0")] use prelude::v1::*; @@ -22,8 +21,8 @@ use io::{self, Error, ErrorKind}; use num::Int; use sys_common::net2 as net_imp; -pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; -pub use self::addr::{SocketAddr, ToSocketAddrs}; +pub use self::ip::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; pub use self::tcp::{TcpStream, TcpListener}; pub use self::udp::UdpSocket; @@ -37,23 +36,27 @@ mod parser; /// Possible values which can be passed to the `shutdown` method of `TcpStream` /// and `UdpSocket`. #[derive(Copy, Clone, PartialEq)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Shutdown { /// Indicates that the reading portion of this stream/socket should be shut /// down. All currently blocked and future reads will return `Ok(0)`. + #[stable(feature = "rust1", since = "1.0.0")] Read, /// Indicates that the writing portion of this stream/socket should be shut /// down. All currently blocked and future writes will return an error. + #[stable(feature = "rust1", since = "1.0.0")] Write, /// Shut down both the reading and writing portions of this stream. /// /// See `Shutdown::Read` and `Shutdown::Write` for more information. - Both + #[stable(feature = "rust1", since = "1.0.0")] + Both, } fn hton<I: Int>(i: I) -> I { i.to_be() } fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) } -fn each_addr<A: ToSocketAddrs + ?Sized, F, T>(addr: &A, mut f: F) -> io::Result<T> +fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T> where F: FnMut(&SocketAddr) -> io::Result<T> { let mut last_err = None; @@ -70,8 +73,10 @@ fn each_addr<A: ToSocketAddrs + ?Sized, F, T>(addr: &A, mut f: F) -> io::Result< } /// An iterator over `SocketAddr` values returned from a host lookup operation. +#[stable(feature = "rust1", since = "1.0.0")] pub struct LookupHost(net_imp::LookupHost); +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for LookupHost { type Item = io::Result<SocketAddr>; fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() } @@ -94,6 +99,7 @@ impl Iterator for LookupHost { /// # Ok(()) /// # } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub fn lookup_host(host: &str) -> io::Result<LookupHost> { net_imp::lookup_host(host).map(LookupHost) } diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index aa54a432d62..9843a152718 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use str::FromStr; -use net::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr}; +use net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; struct Parser<'a> { // parsing as ASCII, so can use byte array @@ -24,6 +24,11 @@ struct Parser<'a> { pos: usize, } +enum IpAddr { + V4(Ipv4Addr), + V6(Ipv6Addr), +} + impl<'a> Parser<'a> { fn new(s: &'a str) -> Parser<'a> { Parser { @@ -281,18 +286,13 @@ impl<'a> Parser<'a> { let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16); // host, colon, port - self.read_seq_3::<IpAddr, char, u16, _, _, _>(ip_addr, colon, port) - .map(|t| match t { (ip, _, port) => SocketAddr::new(ip, port) }) - } -} - -impl FromStr for IpAddr { - type Err = ParseError; - fn from_str(s: &str) -> Result<IpAddr, ParseError> { - match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) { - Some(s) => Ok(s), - None => Err(ParseError), - } + self.read_seq_3(ip_addr, colon, port).map(|t| { + let (ip, _, port): (IpAddr, char, u16) = t; + match ip { + IpAddr::V4(ip) => SocketAddr::V4(SocketAddrV4::new(ip, port)), + IpAddr::V6(ip) => SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)), + } + }) } } diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 76c04835473..501ba2dc2c1 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "tcp", reason = "remaining functions have not been \ + scrutinized enough to be stabilized")] + use prelude::v1::*; use io::prelude::*; @@ -35,6 +38,7 @@ use sys_common::AsInner; /// let _ = stream.read(&mut [0; 128]); // ignore here too /// } // the stream is closed here /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct TcpStream(net_imp::TcpStream); /// A structure representing a socket server. @@ -67,12 +71,14 @@ pub struct TcpStream(net_imp::TcpStream); /// // close the socket server /// drop(listener); /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); /// An infinite iterator over the connections from a `TcpListener`. /// /// This iterator will infinitely yield `Some` of the accepted connections. It /// is equivalent to calling `accept` in a loop. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Incoming<'a> { listener: &'a TcpListener } impl TcpStream { @@ -81,25 +87,36 @@ impl TcpStream { /// `addr` is an address of the remote host. Anything which implements /// `ToSocketAddrs` trait can be supplied for the address; see this trait /// documentation for concrete examples. - pub fn connect<A: ToSocketAddrs + ?Sized>(addr: &A) -> io::Result<TcpStream> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> { super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) } /// Returns the socket address of the remote peer of this TCP connection. + #[stable(feature = "rust1", since = "1.0.0")] pub fn peer_addr(&self) -> io::Result<SocketAddr> { self.0.peer_addr() } /// Returns the socket address of the local half of this TCP connection. + #[unstable(feature = "net")] + #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] pub fn socket_addr(&self) -> io::Result<SocketAddr> { self.0.socket_addr() } + /// Returns the socket address of the local half of this TCP connection. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result<SocketAddr> { + self.0.socket_addr() + } + /// Shut down the read, write, or both halves of this connection. /// /// This function will cause all pending and future I/O on the specified /// portions to return immediately with an appropriate value (see the /// documentation of `Shutdown`). + #[stable(feature = "rust1", since = "1.0.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) } @@ -110,6 +127,7 @@ impl TcpStream { /// object references. Both handles will read and write the same stream of /// data, and options set on one stream will be propagated to the other /// stream. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result<TcpStream> { self.0.duplicate().map(TcpStream) } @@ -129,16 +147,20 @@ impl TcpStream { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -160,11 +182,20 @@ impl TcpListener { /// /// The address type can be any implementer of `ToSocketAddrs` trait. See /// its documentation for concrete examples. - pub fn bind<A: ToSocketAddrs + ?Sized>(addr: &A) -> io::Result<TcpListener> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> { super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) } /// Returns the local socket address of this listener. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result<SocketAddr> { + self.0.socket_addr() + } + + /// Deprecated, renamed to local_addr + #[unstable(feature = "net")] + #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] pub fn socket_addr(&self) -> io::Result<SocketAddr> { self.0.socket_addr() } @@ -174,6 +205,7 @@ impl TcpListener { /// The returned `TcpListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result<TcpListener> { self.0.duplicate().map(TcpListener) } @@ -183,6 +215,7 @@ impl TcpListener { /// This function will block the calling thread until a new TCP connection /// is established. When established, the corresponding `TcpStream` and the /// remote peer's address will be returned. + #[stable(feature = "rust1", since = "1.0.0")] pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { self.0.accept().map(|(a, b)| (TcpStream(a), b)) } @@ -192,11 +225,13 @@ impl TcpListener { /// /// The returned iterator will never returned `None` and will also not yield /// the peer's `SocketAddr` structure. + #[stable(feature = "rust1", since = "1.0.0")] pub fn incoming(&self) -> Incoming { Incoming { listener: self } } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result<TcpStream>; fn next(&mut self) -> Option<io::Result<TcpStream>> { diff --git a/src/libstd/net/test.rs b/src/libstd/net/test.rs index dbebede9f50..3d42472f0fc 100644 --- a/src/libstd/net/test.rs +++ b/src/libstd/net/test.rs @@ -11,19 +11,20 @@ use prelude::v1::*; use env; -use net::{SocketAddr, IpAddr}; +use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr}; use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; static PORT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_test_ip4() -> SocketAddr { - SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), - PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port()) + let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)) } pub fn next_test_ip6() -> SocketAddr { - SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0, 1), - PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port()) + let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); + SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), + port, 0, 0)) } // The bots run multiple builds at the same time, and these builds diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 041e6551ff5..1ace1957526 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "udp", reason = "remaining functions have not been \ + scrutinized enough to be stabilized")] + use prelude::v1::*; use io::{self, Error, ErrorKind}; -use net::{ToSocketAddrs, SocketAddr, IpAddr}; +use net::{ToSocketAddrs, SocketAddr}; use sys_common::net2 as net_imp; use sys_common::AsInner; @@ -41,6 +44,7 @@ use sys_common::AsInner; /// # Ok(()) /// # } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct UdpSocket(net_imp::UdpSocket); impl UdpSocket { @@ -48,12 +52,14 @@ impl UdpSocket { /// /// Address type can be any implementor of `ToSocketAddr` trait. See its /// documentation for concrete examples. - pub fn bind<A: ToSocketAddrs + ?Sized>(addr: &A) -> io::Result<UdpSocket> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> { super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) } /// Receives data from the socket. On success, returns the number of bytes /// read and the address from whence the data came. + #[stable(feature = "rust1", since = "1.0.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.0.recv_from(buf) } @@ -63,8 +69,9 @@ impl UdpSocket { /// /// Address type can be any implementor of `ToSocketAddrs` trait. See its /// documentation for concrete examples. - pub fn send_to<A: ToSocketAddrs + ?Sized>(&self, buf: &[u8], addr: &A) - -> io::Result<usize> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) + -> io::Result<usize> { match try!(addr.to_socket_addrs()).next() { Some(addr) => self.0.send_to(buf, &addr), None => Err(Error::new(ErrorKind::InvalidInput, @@ -73,15 +80,24 @@ impl UdpSocket { } /// Returns the socket address that this socket was created from. + #[unstable(feature = "net")] + #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] pub fn socket_addr(&self) -> io::Result<SocketAddr> { self.0.socket_addr() } + /// Returns the socket address that this socket was created from. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result<SocketAddr> { + self.0.socket_addr() + } + /// Create a new independently owned handle to the underlying socket. /// /// The returned `UdpSocket` is a reference to the same socket that this /// object references. Both handles will read and write the same port, and /// options set on one socket will be propagated to the other. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result<UdpSocket> { self.0.duplicate().map(UdpSocket) } @@ -99,12 +115,12 @@ impl UdpSocket { } /// Joins a multicast IP address (becomes a member of it) - pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { self.0.join_multicast(multi) } /// Leaves a multicast IP address (drops membership from it) - pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { self.0.leave_multicast(multi) } @@ -151,7 +167,7 @@ mod tests { #[cfg_attr(any(windows, target_os = "android"), ignore)] #[test] fn bind_error() { - let addr = SocketAddr::new(IpAddr::new_v4(0, 0, 0, 0), 1); + let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 1); match UdpSocket::bind(&addr) { Ok(..) => panic!(), Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied), diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 969dd35ba22..a7825c4f93a 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -357,6 +357,1236 @@ impl Float for f32 { } } +#[cfg(not(stage0))] +#[cfg(not(test))] +#[lang = "f32"] +#[stable(feature = "rust1", since = "1.0.0")] +impl f32 { + // inlined methods from `num::Float` + /// Returns the `NaN` value. + /// + /// ``` + /// use std::num::Float; + /// + /// let nan: f32 = Float::nan(); + /// + /// assert!(nan.is_nan()); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn nan() -> f32 { num::Float::nan() } + + /// Returns the infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let infinity: f32 = Float::infinity(); + /// + /// assert!(infinity.is_infinite()); + /// assert!(!infinity.is_finite()); + /// assert!(infinity > f32::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn infinity() -> f32 { num::Float::infinity() } + + /// Returns the negative infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let neg_infinity: f32 = Float::neg_infinity(); + /// + /// assert!(neg_infinity.is_infinite()); + /// assert!(!neg_infinity.is_finite()); + /// assert!(neg_infinity < f32::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_infinity() -> f32 { num::Float::neg_infinity() } + + /// Returns `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> f32 { num::Float::zero() } + + /// Returns `-0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_zero() -> f32 { num::Float::neg_zero() } + + /// Returns `1.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let one: f32 = Float::one(); + /// + /// assert_eq!(one, 1.0f32); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> f32 { num::Float::one() } + + // FIXME (#5527): These should be associated constants + + /// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS` + /// instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MANTISSA_DIGITS` or \ + `std::f64::MANTISSA_DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn mantissa_digits(unused_self: Option<f32>) -> uint { + num::Float::mantissa_digits(unused_self) + } + + /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn digits(unused_self: Option<f32>) -> uint { num::Float::digits(unused_self) } + + /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn epsilon() -> f32 { num::Float::epsilon() } + + /// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_exp(unused_self: Option<f32>) -> int { num::Float::min_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_exp(unused_self: Option<f32>) -> int { num::Float::max_exp(unused_self) } + + /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_10_exp(unused_self: Option<f32>) -> int { num::Float::min_10_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_10_exp(unused_self: Option<f32>) -> int { num::Float::max_10_exp(unused_self) } + + /// Returns the smallest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::min_value(); + /// + /// assert_eq!(x, f64::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_value() -> f32 { num::Float::min_value() } + + /// Returns the smallest normalized positive number that this type can represent. + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_pos_value(unused_self: Option<f32>) -> f32 { num::Float::min_pos_value(unused_self) } + + /// Returns the largest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::max_value(); + /// assert_eq!(x, f64::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn max_value() -> f32 { num::Float::max_value() } + + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// let f = 7.0; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_nan(self) -> bool { num::Float::is_nan(self) } + + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } + + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_finite(self) -> bool { num::Float::is_finite(self) } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_normal(self) -> bool { num::Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::{Float, FpCategory}; + /// use std::f32; + /// + /// let num = 12.4f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { num::Float::classify(self) } + + /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. + /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. + /// The floating point encoding is documented in the [Reference][floating-point]. + /// + /// ``` + /// use std::num::Float; + /// + /// let num = 2.0f32; + /// + /// // (8388608, -22, 1) + /// let (mantissa, exponent, sign) = num.integer_decode(); + /// let sign_f = sign as f32; + /// let mantissa_f = mantissa as f32; + /// let exponent_f = num.powf(exponent as f32); + /// + /// // 1 * 8388608 * 2^(-22) == 2 + /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + /// [floating-point]: ../../../../../reference.html#machine-types + #[unstable(feature = "std_misc", reason = "signature is undecided")] + #[inline] + pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } + + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.99; + /// let g = 3.0; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn floor(self) -> f32 { num::Float::floor(self) } + + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.01; + /// let g = 4.0; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ceil(self) -> f32 { num::Float::ceil(self) } + + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.3; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn round(self) -> f32 { num::Float::round(self) } + + /// Return the integer part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.7; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trunc(self) -> f32 { num::Float::trunc(self) } + + /// Returns the fractional part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.5; + /// let y = -3.5; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn fract(self) -> f32 { num::Float::fract(self) } + + /// Computes the absolute value of `self`. Returns `Float::nan()` if the + /// number is `Float::nan()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 3.5; + /// let y = -3.5; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs(self) -> f32 { num::Float::abs(self) } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` + /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` + /// - `Float::nan()` if the number is `Float::nan()` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = 3.5; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f64::NAN.signum().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> f32 { num::Float::signum(self) } + + /// Returns `true` if `self` is positive, including `+0.0` and + /// `Float::infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan: f64 = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(f.is_positive()); + /// assert!(!g.is_positive()); + /// // Requires both tests to determine if is `NaN` + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { num::Float::is_positive(self) } + + /// Returns `true` if `self` is negative, including `-0.0` and + /// `Float::neg_infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(!f.is_negative()); + /// assert!(g.is_negative()); + /// // Requires both tests to determine if is `NaN`. + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { num::Float::is_negative(self) } + + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding + /// error. This produces a more accurate result with better performance than + /// a separate multiplication operation followed by an add. + /// + /// ``` + /// use std::num::Float; + /// + /// let m = 10.0; + /// let x = 4.0; + /// let b = 60.0; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn mul_add(self, a: f32, b: f32) -> f32 { num::Float::mul_add(self, a, b) } + + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn recip(self) -> f32 { num::Float::recip(self) } + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) } + + /// Raise a number to a floating point power. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powf(self, n: f32) -> f32 { num::Float::powf(self, n) } + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative number. + /// + /// ``` + /// use std::num::Float; + /// + /// let positive = 4.0; + /// let negative = -4.0; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(negative.sqrt().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sqrt(self) -> f32 { num::Float::sqrt(self) } + + + /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 4.0; + /// + /// let abs_difference = (f.rsqrt() - 0.5).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn rsqrt(self) -> f32 { num::Float::rsqrt(self) } + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp(self) -> f32 { num::Float::exp(self) } + + /// Returns `2^(self)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 2.0; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp2(self) -> f32 { num::Float::exp2(self) } + + /// Returns the natural logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln(self) -> f32 { num::Float::ln(self) } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// let two = 2.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log(self, base: f32) -> f32 { num::Float::log(self, base) } + + /// Returns the base 2 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let two = 2.0; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log2(self) -> f32 { num::Float::log2(self) } + + /// Returns the base 10 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log10(self) -> f32 { num::Float::log10(self) } + + /// Convert radians to degrees. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) } + + /// Convert degrees to radians. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = 180.0; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_radians(self) -> f32 { num::Float::to_radians(self) } + + /// Constructs a floating point number of `x*2^exp`. + /// + /// ``` + /// use std::num::Float; + /// + /// // 3*2^2 - 12 == 0 + /// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn ldexp(x: f32, exp: int) -> f32 { + unsafe { cmath::ldexpf(x, exp as c_int) } + } + + /// Breaks the number into a normalized fraction and a base-2 exponent, + /// satisfying: + /// + /// * `self = x * 2^exp` + /// * `0.5 <= abs(x) < 1.0` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 4.0; + /// + /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0 + /// let f = x.frexp(); + /// let abs_difference_0 = (f.0 - 0.5).abs(); + /// let abs_difference_1 = (f.1 as f64 - 3.0).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_1 < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn frexp(self) -> (f32, int) { + unsafe { + let mut exp = 0; + let x = cmath::frexpf(self, &mut exp); + (x, exp as int) + } + } + + /// Returns the next representable floating-point value in the direction of + /// `other`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0f32; + /// + /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs(); + /// + /// assert!(abs_diff < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn next_after(self, other: f32) -> f32 { + unsafe { cmath::nextafterf(self, other) } + } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f32) -> f32 { + unsafe { cmath::fmaxf(self, other) } + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f32) -> f32 { + unsafe { cmath::fminf(self, other) } + } + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.0; + /// let y = -3.0; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn abs_sub(self, other: f32) -> f32 { + unsafe { cmath::fdimf(self, other) } + } + + /// Take the cubic root of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 8.0; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn cbrt(self) -> f32 { + unsafe { cmath::cbrtf(self) } + } + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let y = 3.0; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn hypot(self, other: f32) -> f32 { + unsafe { cmath::hypotf(self, other) } + } + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin(self) -> f32 { + unsafe { intrinsics::sinf32(self) } + } + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 2.0*f64::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cos(self) -> f32 { + unsafe { intrinsics::cosf32(self) } + } + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tan(self) -> f32 { + unsafe { cmath::tanf(self) } + } + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asin(self) -> f32 { + unsafe { cmath::asinf(self) } + } + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acos(self) -> f32 { + unsafe { cmath::acosf(self) } + } + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 1.0; + /// + /// // atan(tan(1)) + /// let abs_difference = (f.tan().atan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan(self) -> f32 { + unsafe { cmath::atanf(self) } + } + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let pi = f64::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0; + /// let y1 = -3.0; + /// + /// // 135 deg clockwise + /// let x2 = -3.0; + /// let y2 = 3.0; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan2(self, other: f32) -> f32 { + unsafe { cmath::atan2f(self, other) } + } + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_0 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin_cos(self) -> (f32, f32) { + (self.sin(), self.cos()) + } + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 7.0; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn exp_m1(self) -> f32 { + unsafe { cmath::expm1f(self) } + } + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn ln_1p(self) -> f32 { + unsafe { cmath::log1pf(self) } + } + + /// Hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sinh(self) -> f32 { + unsafe { cmath::sinhf(self) } + } + + /// Hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cosh(self) -> f32 { + unsafe { cmath::coshf(self) } + } + + /// Hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tanh(self) -> f32 { + unsafe { cmath::tanhf(self) } + } + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asinh(self) -> f32 { + match self { + NEG_INFINITY => NEG_INFINITY, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acosh(self) -> f32 { + match self { + x if x < 1.0 => Float::nan(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let f = e.tanh().atanh(); + /// + /// let abs_difference = (f - e).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atanh(self) -> f32 { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} + // // Section: String Conversions // diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 95065b59678..f3978cae485 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -366,6 +366,1235 @@ impl Float for f64 { } } +#[cfg(not(stage0))] +#[cfg(not(test))] +#[lang = "f64"] +#[stable(feature = "rust1", since = "1.0.0")] +impl f64 { + // inlined methods from `num::Float` + /// Returns the `NaN` value. + /// + /// ``` + /// use std::num::Float; + /// + /// let nan: f32 = Float::nan(); + /// + /// assert!(nan.is_nan()); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn nan() -> f64 { num::Float::nan() } + + /// Returns the infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let infinity: f32 = Float::infinity(); + /// + /// assert!(infinity.is_infinite()); + /// assert!(!infinity.is_finite()); + /// assert!(infinity > f32::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn infinity() -> f64 { num::Float::infinity() } + + /// Returns the negative infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let neg_infinity: f32 = Float::neg_infinity(); + /// + /// assert!(neg_infinity.is_infinite()); + /// assert!(!neg_infinity.is_finite()); + /// assert!(neg_infinity < f32::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_infinity() -> f64 { num::Float::neg_infinity() } + + /// Returns `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> f64 { num::Float::zero() } + + /// Returns `-0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_zero() -> f64 { num::Float::neg_zero() } + + /// Returns `1.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let one: f32 = Float::one(); + /// + /// assert_eq!(one, 1.0f32); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> f64 { num::Float::one() } + + // FIXME (#5527): These should be associated constants + + /// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS` + /// instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MANTISSA_DIGITS` or \ + `std::f64::MANTISSA_DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn mantissa_digits(unused_self: Option<f64>) -> uint { + num::Float::mantissa_digits(unused_self) + } + + /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn digits(unused_self: Option<f64>) -> uint { num::Float::digits(unused_self) } + + /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn epsilon() -> f64 { num::Float::epsilon() } + + /// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_exp(unused_self: Option<f64>) -> int { num::Float::min_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_exp(unused_self: Option<f64>) -> int { num::Float::max_exp(unused_self) } + + /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_10_exp(unused_self: Option<f64>) -> int { num::Float::min_10_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_10_exp(unused_self: Option<f64>) -> int { num::Float::max_10_exp(unused_self) } + + /// Returns the smallest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::min_value(); + /// + /// assert_eq!(x, f64::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_value() -> f64 { num::Float::min_value() } + + /// Returns the smallest normalized positive number that this type can represent. + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_pos_value(unused_self: Option<f64>) -> f64 { num::Float::min_pos_value(unused_self) } + + /// Returns the largest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::max_value(); + /// assert_eq!(x, f64::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn max_value() -> f64 { num::Float::max_value() } + + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// let f = 7.0; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_nan(self) -> bool { num::Float::is_nan(self) } + + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } + + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_finite(self) -> bool { num::Float::is_finite(self) } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_normal(self) -> bool { num::Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::{Float, FpCategory}; + /// use std::f32; + /// + /// let num = 12.4f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { num::Float::classify(self) } + + /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. + /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. + /// The floating point encoding is documented in the [Reference][floating-point]. + /// + /// ``` + /// use std::num::Float; + /// + /// let num = 2.0f32; + /// + /// // (8388608, -22, 1) + /// let (mantissa, exponent, sign) = num.integer_decode(); + /// let sign_f = sign as f32; + /// let mantissa_f = mantissa as f32; + /// let exponent_f = num.powf(exponent as f32); + /// + /// // 1 * 8388608 * 2^(-22) == 2 + /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + /// [floating-point]: ../../../../../reference.html#machine-types + #[unstable(feature = "std_misc", reason = "signature is undecided")] + #[inline] + pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } + + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.99; + /// let g = 3.0; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn floor(self) -> f64 { num::Float::floor(self) } + + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.01; + /// let g = 4.0; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ceil(self) -> f64 { num::Float::ceil(self) } + + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.3; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn round(self) -> f64 { num::Float::round(self) } + + /// Return the integer part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.7; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trunc(self) -> f64 { num::Float::trunc(self) } + + /// Returns the fractional part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.5; + /// let y = -3.5; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn fract(self) -> f64 { num::Float::fract(self) } + + /// Computes the absolute value of `self`. Returns `Float::nan()` if the + /// number is `Float::nan()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 3.5; + /// let y = -3.5; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs(self) -> f64 { num::Float::abs(self) } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` + /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` + /// - `Float::nan()` if the number is `Float::nan()` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = 3.5; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f64::NAN.signum().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> f64 { num::Float::signum(self) } + + /// Returns `true` if `self` is positive, including `+0.0` and + /// `Float::infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan: f64 = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(f.is_positive()); + /// assert!(!g.is_positive()); + /// // Requires both tests to determine if is `NaN` + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { num::Float::is_positive(self) } + + /// Returns `true` if `self` is negative, including `-0.0` and + /// `Float::neg_infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(!f.is_negative()); + /// assert!(g.is_negative()); + /// // Requires both tests to determine if is `NaN`. + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { num::Float::is_negative(self) } + + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding + /// error. This produces a more accurate result with better performance than + /// a separate multiplication operation followed by an add. + /// + /// ``` + /// use std::num::Float; + /// + /// let m = 10.0; + /// let x = 4.0; + /// let b = 60.0; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn mul_add(self, a: f64, b: f64) -> f64 { num::Float::mul_add(self, a, b) } + + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn recip(self) -> f64 { num::Float::recip(self) } + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) } + + /// Raise a number to a floating point power. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powf(self, n: f64) -> f64 { num::Float::powf(self, n) } + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative number. + /// + /// ``` + /// use std::num::Float; + /// + /// let positive = 4.0; + /// let negative = -4.0; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(negative.sqrt().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sqrt(self) -> f64 { num::Float::sqrt(self) } + + /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 4.0; + /// + /// let abs_difference = (f.rsqrt() - 0.5).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn rsqrt(self) -> f64 { num::Float::rsqrt(self) } + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp(self) -> f64 { num::Float::exp(self) } + + /// Returns `2^(self)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 2.0; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp2(self) -> f64 { num::Float::exp2(self) } + + /// Returns the natural logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln(self) -> f64 { num::Float::ln(self) } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// let two = 2.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log(self, base: f64) -> f64 { num::Float::log(self, base) } + + /// Returns the base 2 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let two = 2.0; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log2(self) -> f64 { num::Float::log2(self) } + + /// Returns the base 10 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log10(self) -> f64 { num::Float::log10(self) } + + /// Convert radians to degrees. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) } + + /// Convert degrees to radians. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = 180.0; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_radians(self) -> f64 { num::Float::to_radians(self) } + + /// Constructs a floating point number of `x*2^exp`. + /// + /// ``` + /// use std::num::Float; + /// + /// // 3*2^2 - 12 == 0 + /// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn ldexp(x: f64, exp: int) -> f64 { + unsafe { cmath::ldexp(x, exp as c_int) } + } + + /// Breaks the number into a normalized fraction and a base-2 exponent, + /// satisfying: + /// + /// * `self = x * 2^exp` + /// * `0.5 <= abs(x) < 1.0` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 4.0; + /// + /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0 + /// let f = x.frexp(); + /// let abs_difference_0 = (f.0 - 0.5).abs(); + /// let abs_difference_1 = (f.1 as f64 - 3.0).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_1 < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn frexp(self) -> (f64, int) { + unsafe { + let mut exp = 0; + let x = cmath::frexp(self, &mut exp); + (x, exp as int) + } + } + + /// Returns the next representable floating-point value in the direction of + /// `other`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0f32; + /// + /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs(); + /// + /// assert!(abs_diff < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn next_after(self, other: f64) -> f64 { + unsafe { cmath::nextafter(self, other) } + } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f64) -> f64 { + unsafe { cmath::fmax(self, other) } + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f64) -> f64 { + unsafe { cmath::fmin(self, other) } + } + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.0; + /// let y = -3.0; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn abs_sub(self, other: f64) -> f64 { + unsafe { cmath::fdim(self, other) } + } + + /// Take the cubic root of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 8.0; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn cbrt(self) -> f64 { + unsafe { cmath::cbrt(self) } + } + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let y = 3.0; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn hypot(self, other: f64) -> f64 { + unsafe { cmath::hypot(self, other) } + } + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin(self) -> f64 { + unsafe { intrinsics::sinf64(self) } + } + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 2.0*f64::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cos(self) -> f64 { + unsafe { intrinsics::cosf64(self) } + } + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tan(self) -> f64 { + unsafe { cmath::tan(self) } + } + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asin(self) -> f64 { + unsafe { cmath::asin(self) } + } + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acos(self) -> f64 { + unsafe { cmath::acos(self) } + } + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 1.0; + /// + /// // atan(tan(1)) + /// let abs_difference = (f.tan().atan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan(self) -> f64 { + unsafe { cmath::atan(self) } + } + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let pi = f64::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0; + /// let y1 = -3.0; + /// + /// // 135 deg clockwise + /// let x2 = -3.0; + /// let y2 = 3.0; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan2(self, other: f64) -> f64 { + unsafe { cmath::atan2(self, other) } + } + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_0 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin_cos(self) -> (f64, f64) { + (self.sin(), self.cos()) + } + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 7.0; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn exp_m1(self) -> f64 { + unsafe { cmath::expm1(self) } + } + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn ln_1p(self) -> f64 { + unsafe { cmath::log1p(self) } + } + + /// Hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sinh(self) -> f64 { + unsafe { cmath::sinh(self) } + } + + /// Hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cosh(self) -> f64 { + unsafe { cmath::cosh(self) } + } + + /// Hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tanh(self) -> f64 { + unsafe { cmath::tanh(self) } + } + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asinh(self) -> f64 { + match self { + NEG_INFINITY => NEG_INFINITY, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acosh(self) -> f64 { + match self { + x if x < 1.0 => Float::nan(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let f = e.tanh().atanh(); + /// + /// let abs_difference = (f - e).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atanh(self) -> f64 { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} + // // Section: String Conversions // diff --git a/src/libstd/num/float_macros.rs b/src/libstd/num/float_macros.rs index 2b730cd6f9a..ece7af9c152 100644 --- a/src/libstd/num/float_macros.rs +++ b/src/libstd/num/float_macros.rs @@ -11,6 +11,7 @@ #![unstable(feature = "std_misc")] #![doc(hidden)] +#[cfg(stage0)] macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use num::Float; @@ -19,3 +20,12 @@ macro_rules! assert_approx_eq { "{} is not approximately equal to {}", *a, *b); }) } + +#[cfg(not(stage0))] +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => ({ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", *a, *b); + }) +} diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 35d973d2d4e..599f3f02a8b 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -23,7 +23,10 @@ use marker::Copy; use clone::Clone; use cmp::{PartialOrd, PartialEq}; +#[cfg(stage0)] pub use core::num::{Int, SignedInt, UnsignedInt}; +#[cfg(not(stage0))] +pub use core::num::{Int, SignedInt}; pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive}; pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64}; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 5fdd42dbc7a..ea1e05df85f 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -16,11 +16,16 @@ use self::ExponentFormat::*; use self::SignificantDigits::*; use self::SignFormat::*; +#[cfg(stage0)] use char::{self, CharExt}; +#[cfg(not(stage0))] +use char; use num::{self, Int, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnMut; +#[cfg(stage0)] use slice::SliceExt; +#[cfg(stage0)] use str::StrExt; use string::String; use vec::Vec; diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs index 9be7fcca1e8..82a48a72499 100644 --- a/src/libstd/old_io/buffered.rs +++ b/src/libstd/old_io/buffered.rs @@ -20,6 +20,7 @@ use ops::Drop; use option::Option; use option::Option::{Some, None}; use result::Result::Ok; +#[cfg(stage0)] use slice::{SliceExt}; use slice; use vec::Vec; diff --git a/src/libstd/old_io/comm_adapters.rs b/src/libstd/old_io/comm_adapters.rs index 72ba653a986..33928d638e0 100644 --- a/src/libstd/old_io/comm_adapters.rs +++ b/src/libstd/old_io/comm_adapters.rs @@ -14,7 +14,10 @@ use sync::mpsc::{Sender, Receiver}; use old_io; use option::Option::{None, Some}; use result::Result::{Ok, Err}; +#[cfg(stage0)] use slice::{bytes, SliceExt}; +#[cfg(not(stage0))] +use slice::bytes; use super::{Buffer, Reader, Writer, IoResult}; use vec::Vec; diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index ec30121d78d..a81275952c5 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -26,8 +26,10 @@ use num::Int; use ops::FnOnce; use option::Option; use option::Option::{Some, None}; +#[cfg(stage0)] use ptr::PtrExt; use result::Result::{Ok, Err}; +#[cfg(stage0)] use slice::SliceExt; /// An iterator that reads a single byte on each iteration, @@ -162,6 +164,7 @@ pub fn u64_to_be_bytes<T, F>(n: u64, size: uint, f: F) -> T where /// 32-bit value is parsed. pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { use ptr::{copy_nonoverlapping_memory}; + #[cfg(stage0)] use slice::SliceExt; assert!(size <= 8); diff --git a/src/libstd/old_io/fs.rs b/src/libstd/old_io/fs.rs index 80a09b3bd0b..ff3af380b7d 100644 --- a/src/libstd/old_io/fs.rs +++ b/src/libstd/old_io/fs.rs @@ -64,6 +64,7 @@ use option::Option::{Some, None}; use old_path::{Path, GenericPath}; use old_path; use result::Result::{Err, Ok}; +#[cfg(stage0)] use slice::SliceExt; use string::String; use vec::Vec; diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 80d4b013fff..72774334c13 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -17,7 +17,10 @@ use option::Option::None; use result::Result::{Err, Ok}; use old_io; use old_io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult}; +#[cfg(stage0)] use slice::{self, SliceExt}; +#[cfg(not(stage0))] +use slice; use vec::Vec; const BUF_CAPACITY: uint = 128; @@ -395,7 +398,7 @@ impl<'a> Buffer for BufReader<'a> { mod test { extern crate "test" as test_crate; use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek}; - use prelude::v1::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt}; + use prelude::v1::{Ok, Err, range, Vec, Buffer, AsSlice}; use prelude::v1::IteratorExt; use old_io; use iter::repeat; diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 9b1de45fdf8..15a80e34451 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -251,6 +251,7 @@ pub use self::FileMode::*; pub use self::FileAccess::*; pub use self::IoErrorKind::*; +#[cfg(stage0)] use char::CharExt; use default::Default; use error::Error; @@ -267,7 +268,9 @@ use boxed::Box; use result::Result; use result::Result::{Ok, Err}; use sys; +#[cfg(stage0)] use slice::SliceExt; +#[cfg(stage0)] use str::StrExt; use str; use string::String; @@ -931,15 +934,16 @@ impl<'a> Reader for &'a mut (Reader+'a) { // Private function here because we aren't sure if we want to expose this as // API yet. If so, it should be a method on Vec. unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -> &'a mut [T] { - use raw::Slice; + use slice; + #[cfg(stage0)] use ptr::PtrExt; assert!(start <= end); assert!(end <= v.capacity()); - transmute(Slice { - data: v.as_ptr().offset(start as int), - len: end - start - }) + slice::from_raw_parts_mut( + v.as_mut_ptr().offset(start as int), + end - start + ) } /// A `RefReader` is a struct implementing `Reader` which contains a reference @@ -1849,7 +1853,7 @@ impl fmt::Display for FilePermission { mod tests { use self::BadReaderBehavior::*; use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer}; - use prelude::v1::{Ok, Vec, Buffer, SliceExt}; + use prelude::v1::{Ok, Vec, Buffer}; use usize; #[derive(Clone, PartialEq, Debug)] diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs index 6e2f491262d..2dda2c1277a 100644 --- a/src/libstd/old_io/net/ip.rs +++ b/src/libstd/old_io/net/ip.rs @@ -26,8 +26,12 @@ use ops::{FnOnce, FnMut}; use option::Option; use option::Option::{None, Some}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::SliceExt; +#[cfg(stage0)] use str::{FromStr, StrExt}; +#[cfg(not(stage0))] +use str::FromStr; use vec::Vec; pub type Port = u16; diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index cabba8e358a..e5f23643372 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -761,7 +761,7 @@ mod tests { use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; use prelude::v1::{Ok, Err, range, drop, Some, None, Vec}; use prelude::v1::{Path, String, Reader, Writer, Clone}; - use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; + use prelude::v1::{Str, AsSlice, ToString, GenericPath}; use old_io::fs::PathExtensions; use old_io::timer::*; use rt::running_on_valgrind; diff --git a/src/libstd/old_io/stdio.rs b/src/libstd/old_io/stdio.rs index 784d5faec88..b699b93f2b8 100644 --- a/src/libstd/old_io/stdio.rs +++ b/src/libstd/old_io/stdio.rs @@ -43,7 +43,9 @@ use ops::{Deref, DerefMut, FnOnce}; use ptr; use result::Result::{Ok, Err}; use rt; +#[cfg(stage0)] use slice::SliceExt; +#[cfg(stage0)] use str::StrExt; use string::String; use sys::{fs, tty}; @@ -535,18 +537,4 @@ mod tests { stdout(); stderr(); } - - #[test] - fn capture_stdout() { - use old_io::{ChanReader, ChanWriter}; - - let (tx, rx) = channel(); - let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - let _t = thread::spawn(move|| { - set_stdout(Box::new(w)); - println!("hello!"); - }); - assert_eq!(r.read_to_string().unwrap(), "hello!\n"); - } } diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs index 76753dca52e..b34804fce61 100644 --- a/src/libstd/old_io/tempfile.rs +++ b/src/libstd/old_io/tempfile.rs @@ -21,6 +21,7 @@ use option::Option; use old_path::{Path, GenericPath}; use rand::{Rng, thread_rng}; use result::Result::{Ok, Err}; +#[cfg(stage0)] use str::StrExt; use string::String; diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index 01eec230d21..37875658ae0 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -72,8 +72,10 @@ use iter::IteratorExt; use option::Option; use option::Option::{None, Some}; use str; +#[cfg(stage0)] use str::StrExt; use string::{String, CowString}; +#[cfg(stage0)] use slice::SliceExt; use vec::Vec; diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index 8d5765e1ffe..e35623d7b1a 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -20,8 +20,14 @@ use iter::{Iterator, IteratorExt, Map}; use marker::Sized; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::{AsSlice, Split, SliceExt, SliceConcatExt}; +#[cfg(not(stage0))] +use slice::{AsSlice, Split, SliceConcatExt}; +#[cfg(stage0)] use str::{self, FromStr, StrExt}; +#[cfg(not(stage0))] +use str::{self, FromStr}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; @@ -447,8 +453,8 @@ mod tests { use iter::IteratorExt; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::{AsSlice, SliceExt}; - use str::{self, Str, StrExt}; + use slice::AsSlice; + use str::{self, Str}; use string::ToString; use vec::Vec; diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index 838710b1aec..ff4f083333b 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -15,6 +15,7 @@ use self::PathPrefix::*; use ascii::AsciiExt; +#[cfg(stage0)] use char::CharExt; use clone::Clone; use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd}; @@ -26,8 +27,14 @@ use iter::{Iterator, IteratorExt, Map, repeat}; use mem; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::{SliceExt, SliceConcatExt}; +#[cfg(not(stage0))] +use slice::SliceConcatExt; +#[cfg(stage0)] use str::{SplitTerminator, FromStr, StrExt}; +#[cfg(not(stage0))] +use str::{SplitTerminator, FromStr}; use string::{String, ToString}; use vec::Vec; @@ -1126,7 +1133,7 @@ mod tests { use iter::IteratorExt; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::{AsSlice, SliceExt}; + use slice::AsSlice; use str::Str; use string::ToString; use vec::Vec; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index ffe762450d0..46233a46ee5 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -52,12 +52,19 @@ use option::Option::{Some, None}; use option::Option; use old_path::{Path, GenericPath, BytesContainer}; use path::{self, PathBuf}; +#[cfg(stage0)] use ptr::PtrExt; use ptr; use result::Result::{Err, Ok}; use result::Result; +#[cfg(stage0)] use slice::{AsSlice, SliceExt}; +#[cfg(not(stage0))] +use slice::AsSlice; +#[cfg(stage0)] use str::{Str, StrExt}; +#[cfg(not(stage0))] +use str::Str; use str; use string::{String, ToString}; use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; @@ -210,7 +217,7 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> { #[cfg(unix)] fn byteify(s: OsString) -> Vec<u8> { - use os::unix::*; + use os::unix::prelude::*; s.into_vec() } #[cfg(windows)] @@ -238,7 +245,7 @@ fn byteify(s: OsString) -> Vec<u8> { pub fn setenv<T: BytesContainer>(n: &str, v: T) { #[cfg(unix)] fn _setenv(n: &str, v: &[u8]) { - use os::unix::*; + use os::unix::prelude::*; let v: OsString = OsStringExt::from_vec(v.to_vec()); env::set_var(n, &v) } @@ -591,7 +598,6 @@ pub fn get_exit_status() -> int { unsafe fn load_argc_and_argv(argc: int, argv: *const *const c_char) -> Vec<Vec<u8>> { use ffi::CStr; - use iter::range; (0..argc).map(|i| { CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec() @@ -1709,13 +1715,13 @@ mod tests { #[cfg(not(windows))] fn get_fd(file: &File) -> libc::c_int { - use os::unix::AsRawFd; + use os::unix::prelude::*; file.as_raw_fd() } #[cfg(windows)] fn get_fd(file: &File) -> libc::HANDLE { - use os::windows::AsRawHandle; + use os::windows::prelude::*; file.as_raw_handle() } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 536c7fbf66f..2d97d651366 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -86,8 +86,8 @@ //! //! * Occurrences of `.` are normalized away, *except* if they are at //! the beginning of the path (in which case they are often meaningful -//! in terms of path searching). So, fore xample, `a/./b`, `a/b/`, -//! `/a/b/.` and `a/b` all ahve components `a` and `b`, but `./a/b` +//! in terms of path searching). So, for example, `a/./b`, `a/b/`, +//! `/a/b/.` and `a/b` all have components `a` and `b`, but `./a/b` //! has a leading current directory component. //! //! No other normalization takes place by default. In particular, @@ -159,6 +159,7 @@ mod platform { use core::prelude::*; use ascii::*; + #[cfg(stage0)] use char::CharExt as UnicodeCharExt; use super::{os_str_as_u8_slice, u8_slice_as_os_str, Prefix}; use ffi::OsStr; @@ -877,7 +878,7 @@ impl PathBuf { /// Allocate a `PathBuf` with initial contents given by the /// argument. #[stable(feature = "rust1", since = "1.0.0")] - pub fn new<S: ?Sized + AsOsStr>(s: &S) -> PathBuf { + pub fn new<S: AsOsStr>(s: S) -> PathBuf { PathBuf { inner: s.as_os_str().to_os_string() } } @@ -891,7 +892,7 @@ impl PathBuf { /// replaces everything except for the prefix (if any) of `self`. /// * if `path` has a prefix but no root, it replaces `self. #[stable(feature = "rust1", since = "1.0.0")] - pub fn push<P: ?Sized>(&mut self, path: &P) where P: AsPath { + pub fn push<P: AsPath>(&mut self, path: P) { let path = path.as_path(); // in general, a separator is needed if the rightmost byte is not a separator @@ -959,7 +960,7 @@ impl PathBuf { /// assert!(buf == PathBuf::new("/baz.txt")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn set_file_name<S: ?Sized>(&mut self, file_name: &S) where S: AsOsStr { + pub fn set_file_name<S: AsOsStr>(&mut self, file_name: S) { if self.file_name().is_some() { let popped = self.pop(); debug_assert!(popped); @@ -974,7 +975,7 @@ impl PathBuf { /// Otherwise, returns `true`; if `self.extension()` is `None`, the extension /// is added; otherwise it is replaced. #[stable(feature = "rust1", since = "1.0.0")] - pub fn set_extension<S: ?Sized + AsOsStr>(&mut self, extension: &S) -> bool { + pub fn set_extension<S: AsOsStr>(&mut self, extension: S) -> bool { if self.file_name().is_none() { return false; } let mut stem = match self.file_stem() { @@ -1000,8 +1001,8 @@ impl PathBuf { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, P: ?Sized + 'a> iter::FromIterator<&'a P> for PathBuf where P: AsPath { - fn from_iter<I: IntoIterator<Item = &'a P>>(iter: I) -> PathBuf { +impl<P: AsPath> iter::FromIterator<P> for PathBuf { + fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf { let mut buf = PathBuf::new(""); buf.extend(iter); buf @@ -1009,8 +1010,8 @@ impl<'a, P: ?Sized + 'a> iter::FromIterator<&'a P> for PathBuf where P: AsPath { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, P: ?Sized + 'a> iter::Extend<&'a P> for PathBuf where P: AsPath { - fn extend<I: IntoIterator<Item = &'a P>>(&mut self, iter: I) { +impl<P: AsPath> iter::Extend<P> for PathBuf { + fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) { for p in iter { self.push(p) } @@ -1253,13 +1254,13 @@ impl Path { /// Determines whether `base` is a prefix of `self`. #[stable(feature = "rust1", since = "1.0.0")] - pub fn starts_with<P: ?Sized>(&self, base: &P) -> bool where P: AsPath { + pub fn starts_with<P: AsPath>(&self, base: P) -> bool { iter_after(self.components(), base.as_path().components()).is_some() } /// Determines whether `child` is a suffix of `self`. #[stable(feature = "rust1", since = "1.0.0")] - pub fn ends_with<P: ?Sized>(&self, child: &P) -> bool where P: AsPath { + pub fn ends_with<P: AsPath>(&self, child: P) -> bool { iter_after(self.components().rev(), child.as_path().components().rev()).is_some() } @@ -1293,7 +1294,7 @@ impl Path { /// /// See `PathBuf::push` for more details on what it means to adjoin a path. #[stable(feature = "rust1", since = "1.0.0")] - pub fn join<P: ?Sized>(&self, path: &P) -> PathBuf where P: AsPath { + pub fn join<P: AsPath>(&self, path: P) -> PathBuf { let mut buf = self.to_path_buf(); buf.push(path); buf @@ -1303,7 +1304,7 @@ impl Path { /// /// See `PathBuf::set_file_name` for more details. #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_file_name<S: ?Sized>(&self, file_name: &S) -> PathBuf where S: AsOsStr { + pub fn with_file_name<S: AsOsStr>(&self, file_name: S) -> PathBuf { let mut buf = self.to_path_buf(); buf.set_file_name(file_name); buf @@ -1313,7 +1314,7 @@ impl Path { /// /// See `PathBuf::set_extension` for more details. #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_extension<S: ?Sized>(&self, extension: &S) -> PathBuf where S: AsOsStr { + pub fn with_extension<S: AsOsStr>(&self, extension: S) -> PathBuf { let mut buf = self.to_path_buf(); buf.set_extension(extension); buf diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 60e1354482c..4327b26260a 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -25,6 +25,7 @@ // Reexported types and traits #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use boxed::Box; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use char::CharExt; #[stable(feature = "rust1", since = "1.0.0")] @@ -39,14 +40,23 @@ #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use option::Option::{self, Some, None}; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt, AsSlice}; +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] pub use slice::{SliceConcatExt, AsSlice}; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use str::{Str, StrExt}; +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] pub use str::Str; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use string::{String, ToString}; #[stable(feature = "rust1", since = "1.0.0")] @@ -57,6 +67,7 @@ // NB: remove when I/O reform lands #[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude}; // NB: remove when range syntax lands +#[allow(deprecated)] #[doc(no_inline)] pub use iter::range; #[doc(no_inline)] pub use num::wrapping::{Wrapping, WrappingOps}; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index ebd0820669c..df8a5d27c7f 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -147,7 +147,7 @@ impl Command { /// Builder methods are provided to change these defaults and /// otherwise configure the process. #[stable(feature = "process", since = "1.0.0")] - pub fn new<S: AsOsStr + ?Sized>(program: &S) -> Command { + pub fn new<S: AsOsStr>(program: S) -> Command { Command { inner: CommandImp::new(program.as_os_str()), stdin: None, @@ -158,7 +158,7 @@ impl Command { /// Add an argument to pass to the program. #[stable(feature = "process", since = "1.0.0")] - pub fn arg<S: AsOsStr + ?Sized>(&mut self, arg: &S) -> &mut Command { + pub fn arg<S: AsOsStr>(&mut self, arg: S) -> &mut Command { self.inner.arg(arg.as_os_str()); self } @@ -175,7 +175,7 @@ impl Command { /// Note that environment variable names are case-insensitive (but case-preserving) on Windows, /// and case-sensitive on all other platforms. #[stable(feature = "process", since = "1.0.0")] - pub fn env<K: ?Sized, V: ?Sized>(&mut self, key: &K, val: &V) -> &mut Command + pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command where K: AsOsStr, V: AsOsStr { self.inner.env(key.as_os_str(), val.as_os_str()); @@ -184,7 +184,7 @@ impl Command { /// Removes an environment variable mapping. #[stable(feature = "process", since = "1.0.0")] - pub fn env_remove<K: ?Sized + AsOsStr>(&mut self, key: &K) -> &mut Command { + pub fn env_remove<K: AsOsStr>(&mut self, key: K) -> &mut Command { self.inner.env_remove(key.as_os_str()); self } @@ -198,7 +198,7 @@ impl Command { /// Set the working directory for the child process. #[stable(feature = "process", since = "1.0.0")] - pub fn current_dir<P: AsPath + ?Sized>(&mut self, dir: &P) -> &mut Command { + pub fn current_dir<P: AsPath>(&mut self, dir: P) -> &mut Command { self.inner.cwd(dir.as_path().as_os_str()); self } @@ -533,7 +533,7 @@ mod tests { use io::prelude::*; use prelude::v1::{Ok, Err, drop, Some, Vec}; use prelude::v1::{String, Clone}; - use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; + use prelude::v1::{Str, AsSlice, ToString, GenericPath}; use old_path; use old_io::fs::PathExtensions; use rt::running_on_valgrind; @@ -573,7 +573,7 @@ mod tests { #[cfg(all(unix, not(target_os="android")))] #[test] fn signal_reported_right() { - use os::unix::ExitStatusExt; + use os::unix::process::ExitStatusExt; let p = Command::new("/bin/sh").arg("-c").arg("kill -9 $$").spawn(); assert!(p.is_ok()); @@ -633,7 +633,7 @@ mod tests { #[cfg(all(unix, not(target_os="android")))] #[test] fn uid_works() { - use os::unix::*; + use os::unix::prelude::*; use libc; let mut p = Command::new("/bin/sh") .arg("-c").arg("true") @@ -646,7 +646,7 @@ mod tests { #[cfg(all(unix, not(target_os="android")))] #[test] fn uid_to_root_fails() { - use os::unix::*; + use os::unix::prelude::*; use libc; // if we're already root, this isn't a valid test. Most of the bots run diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 6cb3eb4d16e..46e35e0fa8b 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -24,6 +24,7 @@ mod imp { use rand::Rng; use rand::reader::ReaderRng; use result::Result::Ok; + #[cfg(stage0)] use slice::SliceExt; use mem; use os::errno; @@ -193,6 +194,7 @@ mod imp { use rand::Rng; use result::Result::{Ok}; use self::libc::{c_int, size_t}; + #[cfg(stage0)] use slice::SliceExt; /// A random number generator that retrieves randomness straight from @@ -263,6 +265,7 @@ mod imp { use result::Result::{Ok, Err}; use self::libc::{DWORD, BYTE, LPCSTR, BOOL}; use self::libc::types::os::arch::extra::{LONG_PTR}; + #[cfg(stage0)] use slice::SliceExt; type HCRYPTPROV = LONG_PTR; diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index 576bf24d8a3..42c153af036 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -13,6 +13,7 @@ use old_io::Reader; use rand::Rng; use result::Result::{Ok, Err}; +#[cfg(stage0)] use slice::SliceExt; /// An RNG that reads random bytes straight from a `Reader`. This will diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs index 08755ba829f..f6bb87f011d 100644 --- a/src/libstd/rt/at_exit_imp.rs +++ b/src/libstd/rt/at_exit_imp.rs @@ -12,6 +12,7 @@ //! //! Documentation can be found on the `rt::at_exit` function. +#[cfg(stage0)] use core::prelude::*; use boxed; diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index af5b49a4239..25aeab1b4ff 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -14,7 +14,7 @@ use ffi::CString; use io::{self, Error, ErrorKind}; use libc::{self, c_int, c_char, c_void, socklen_t}; use mem; -use net::{IpAddr, SocketAddr, Shutdown}; +use net::{SocketAddr, Shutdown}; use sys::c; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys_common::{AsInner, FromInner, IntoInner}; @@ -63,15 +63,15 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage, match storage.ss_family as libc::c_int { libc::AF_INET => { assert!(len as usize >= mem::size_of::<libc::sockaddr_in>()); - Ok(FromInner::from_inner(unsafe { + Ok(SocketAddr::V4(FromInner::from_inner(unsafe { *(storage as *const _ as *const libc::sockaddr_in) - })) + }))) } libc::AF_INET6 => { assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>()); - Ok(FromInner::from_inner(unsafe { + Ok(SocketAddr::V6(FromInner::from_inner(unsafe { *(storage as *const _ as *const libc::sockaddr_in6) - })) + }))) } _ => { Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None)) @@ -334,39 +334,39 @@ impl UdpSocket { libc::IP_MULTICAST_LOOP, on as c_int) } - pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { match *multi { - IpAddr::V4(..) => { + SocketAddr::V4(..) => { self.set_membership(multi, libc::IP_ADD_MEMBERSHIP) } - IpAddr::V6(..) => { + SocketAddr::V6(..) => { self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP) } } } - pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { match *multi { - IpAddr::V4(..) => { + SocketAddr::V4(..) => { self.set_membership(multi, libc::IP_DROP_MEMBERSHIP) } - IpAddr::V6(..) => { + SocketAddr::V6(..) => { self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP) } } } - fn set_membership(&self, addr: &IpAddr, opt: c_int) -> io::Result<()> { + fn set_membership(&self, addr: &SocketAddr, opt: c_int) -> io::Result<()> { match *addr { - IpAddr::V4(ref addr) => { + SocketAddr::V4(ref addr) => { let mreq = libc::ip_mreq { - imr_multiaddr: *addr.as_inner(), + imr_multiaddr: *addr.ip().as_inner(), // interface == INADDR_ANY imr_interface: libc::in_addr { s_addr: 0x0 }, }; setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq) } - IpAddr::V6(ref addr) => { + SocketAddr::V6(ref addr) => { let mreq = libc::ip6_mreq { - ipv6mr_multiaddr: *addr.as_inner(), + ipv6mr_multiaddr: *addr.ip().as_inner(), ipv6mr_interface: 0, }; setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq) diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 6c17f9910ac..dfc88571a82 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -29,7 +29,6 @@ use core::prelude::*; use core::char::{encode_utf8_raw, encode_utf16_raw}; use core::str::{char_range_at_raw, next_code_point}; -use core::raw::Slice as RawSlice; use ascii::*; use borrow::Cow; @@ -173,6 +172,7 @@ impl Wtf8Buf { Wtf8Buf { bytes: string.into_bytes() } } + #[cfg(stage0)] /// Create a WTF-8 string from an UTF-8 `&str` slice. /// /// This copies the content of the slice. @@ -183,6 +183,17 @@ impl Wtf8Buf { Wtf8Buf { bytes: slice::SliceExt::to_vec(str.as_bytes()) } } + #[cfg(not(stage0))] + /// Create a WTF-8 string from an UTF-8 `&str` slice. + /// + /// This copies the content of the slice. + /// + /// Since WTF-8 is a superset of UTF-8, this always succeeds. + #[inline] + pub fn from_str(str: &str) -> Wtf8Buf { + Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()) } + } + /// Create a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units. /// /// This is lossless: calling `.encode_wide()` on the resulting string @@ -214,10 +225,10 @@ impl Wtf8Buf { unsafe { // Attempt to not use an intermediate buffer by just pushing bytes // directly onto this string. - let slice = RawSlice { - data: self.bytes.as_ptr().offset(cur_len as int), - len: 4, - }; + let slice = slice::from_raw_parts_mut( + self.bytes.as_mut_ptr().offset(cur_len as int), + 4 + ); let used = encode_utf8_raw(code_point.value, mem::transmute(slice)) .unwrap_or(0); self.bytes.set_len(cur_len + used); @@ -725,10 +736,11 @@ pub fn is_code_point_boundary(slice: &Wtf8, index: uint) -> bool { /// Copied from core::str::raw::slice_unchecked #[inline] pub unsafe fn slice_unchecked(s: &Wtf8, begin: uint, end: uint) -> &Wtf8 { - mem::transmute(RawSlice { - data: s.bytes.as_ptr().offset(begin as int), - len: end - begin, - }) + // memory layout of an &[u8] and &Wtf8 are the same + mem::transmute(slice::from_raw_parts( + s.bytes.as_ptr().offset(begin as int), + end - begin + )) } /// Copied from core::str::raw::slice_error_fail diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 3fa9f5d07aa..74ab04978cb 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -118,7 +118,7 @@ pub fn write(w: &mut Write) -> io::Result<()> { // local, it still displays much nicer backtraces when a // couple of tasks panic simultaneously static LOCK: StaticMutex = MUTEX_INIT; - let _g = unsafe { LOCK.lock() }; + let _g = LOCK.lock(); try!(writeln!(w, "stack backtrace:")); // 100 lines should be enough diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 3dd05319194..0805949d560 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -29,183 +29,206 @@ //! } //! ``` -#![unstable(feature = "std_misc")] - -use prelude::v1::*; - -use ffi::{CString, NulError, OsStr, OsString}; -use fs::{self, Permissions, OpenOptions}; -use net; -use mem; -use process; -use sys; -use sys::os_str::Buf; -use sys_common::{AsInner, AsInnerMut, IntoInner, FromInner}; -use libc::{self, gid_t, uid_t}; - -#[allow(deprecated)] use old_io; - -/// Raw file descriptors. -pub type Fd = libc::c_int; - -/// Extract raw file descriptor -pub trait AsRawFd { - /// Extract the raw file descriptor, without taking any ownership. - fn as_raw_fd(&self) -> Fd; -} +#![stable(feature = "rust1", since = "1.0.0")] + +/// Unix-specific extensions to general I/O primitives +#[unstable(feature = "io_ext", + reason = "may want a slightly different organization or a more \ + general file descriptor primitive")] +pub mod io { + #[allow(deprecated)] use old_io; + use fs; + use libc; + use net; + use sys_common::AsInner; + + /// Raw file descriptors. + pub type Fd = libc::c_int; + + /// Extract raw file descriptor + pub trait AsRawFd { + /// Extract the raw file descriptor, without taking any ownership. + fn as_raw_fd(&self) -> Fd; + } -#[allow(deprecated)] -impl AsRawFd for old_io::fs::File { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::fs::File { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -impl AsRawFd for fs::File { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd().raw() + impl AsRawFd for fs::File { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd().raw() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::pipe::PipeStream { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::pipe::PipeStream { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::net::pipe::UnixStream { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::net::pipe::UnixStream { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::net::pipe::UnixListener { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::net::pipe::UnixListener { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::net::pipe::UnixAcceptor { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::net::pipe::UnixAcceptor { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::net::tcp::TcpStream { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::net::tcp::TcpStream { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::net::tcp::TcpListener { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::net::tcp::TcpListener { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::net::tcp::TcpAcceptor { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::net::tcp::TcpAcceptor { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawFd for old_io::net::udp::UdpSocket { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawFd for old_io::net::udp::UdpSocket { + fn as_raw_fd(&self) -> Fd { + self.as_inner().fd() + } } -} -impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } -} -impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } -} -impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + impl AsRawFd for net::TcpStream { + fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + } + impl AsRawFd for net::TcpListener { + fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + } + impl AsRawFd for net::UdpSocket { + fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + } } //////////////////////////////////////////////////////////////////////////////// // OsString and OsStr //////////////////////////////////////////////////////////////////////////////// -/// Unix-specific extensions to `OsString`. -pub trait OsStringExt { - /// Create an `OsString` from a byte vector. - fn from_vec(vec: Vec<u8>) -> Self; - - /// Yield the underlying byte vector of this `OsString`. - fn into_vec(self) -> Vec<u8>; -} - -impl OsStringExt for OsString { - fn from_vec(vec: Vec<u8>) -> OsString { - FromInner::from_inner(Buf { inner: vec }) +/// Unix-specific extension to the primitives in the `std::ffi` module +#[stable(feature = "rust1", since = "1.0.0")] +pub mod ffi { + use ffi::{CString, NulError, OsStr, OsString}; + use mem; + use prelude::v1::*; + use sys::os_str::Buf; + use sys_common::{FromInner, IntoInner, AsInner}; + + /// Unix-specific extensions to `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStringExt { + /// Create an `OsString` from a byte vector. + #[stable(feature = "rust1", since = "1.0.0")] + fn from_vec(vec: Vec<u8>) -> Self; + + /// Yield the underlying byte vector of this `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] + fn into_vec(self) -> Vec<u8>; } - fn into_vec(self) -> Vec<u8> { - self.into_inner().inner + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStringExt for OsString { + fn from_vec(vec: Vec<u8>) -> OsString { + FromInner::from_inner(Buf { inner: vec }) + } + fn into_vec(self) -> Vec<u8> { + self.into_inner().inner + } } -} - -/// Unix-specific extensions to `OsStr`. -pub trait OsStrExt { - fn from_bytes(slice: &[u8]) -> &OsStr; - /// Get the underlying byte view of the `OsStr` slice. - fn as_bytes(&self) -> &[u8]; + /// Unix-specific extensions to `OsStr`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStrExt { + #[stable(feature = "rust1", since = "1.0.0")] + fn from_bytes(slice: &[u8]) -> &Self; - /// Convert the `OsStr` slice into a `CString`. - fn to_cstring(&self) -> Result<CString, NulError>; -} + /// Get the underlying byte view of the `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_bytes(&self) -> &[u8]; -impl OsStrExt for OsStr { - fn from_bytes(slice: &[u8]) -> &OsStr { - unsafe { mem::transmute(slice) } - } - fn as_bytes(&self) -> &[u8] { - &self.as_inner().inner + /// Convert the `OsStr` slice into a `CString`. + #[stable(feature = "rust1", since = "1.0.0")] + fn to_cstring(&self) -> Result<CString, NulError>; } - fn to_cstring(&self) -> Result<CString, NulError> { - CString::new(self.as_bytes()) + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStrExt for OsStr { + fn from_bytes(slice: &[u8]) -> &OsStr { + unsafe { mem::transmute(slice) } + } + fn as_bytes(&self) -> &[u8] { + &self.as_inner().inner + } + fn to_cstring(&self) -> Result<CString, NulError> { + CString::new(self.as_bytes()) + } } } -// Unix-specific extensions to `Permissions` -pub trait PermissionsExt { - fn mode(&self) -> i32; - fn set_mode(&mut self, mode: i32); -} +/// Unix-specific extensions to primitives in the `std::fs` module. +#[unstable(feature = "fs_ext", + reason = "may want a more useful mode abstraction")] +pub mod fs { + use sys_common::{FromInner, AsInner, AsInnerMut}; + use fs::{Permissions, OpenOptions}; + + /// Unix-specific extensions to `Permissions` + pub trait PermissionsExt { + fn mode(&self) -> i32; + fn set_mode(&mut self, mode: i32); + } -impl PermissionsExt for Permissions { - fn mode(&self) -> i32 { self.as_inner().mode() } + impl PermissionsExt for Permissions { + fn mode(&self) -> i32 { self.as_inner().mode() } - fn set_mode(&mut self, mode: i32) { - *self = FromInner::from_inner(FromInner::from_inner(mode)); + fn set_mode(&mut self, mode: i32) { + *self = FromInner::from_inner(FromInner::from_inner(mode)); + } } -} -// Unix-specific extensions to `OpenOptions` -pub trait OpenOptionsExt { - /// Set the mode bits that a new file will be created with. - /// - /// If a new file is created as part of a `File::open_opts` call then this - /// specified `mode` will be used as the permission bits for the new file. - fn mode(&mut self, mode: i32) -> &mut Self; -} + /// Unix-specific extensions to `OpenOptions` + pub trait OpenOptionsExt { + /// Set the mode bits that a new file will be created with. + /// + /// If a new file is created as part of a `File::open_opts` call then this + /// specified `mode` will be used as the permission bits for the new file. + fn mode(&mut self, mode: i32) -> &mut Self; + } -impl OpenOptionsExt for OpenOptions { - fn mode(&mut self, mode: i32) -> &mut OpenOptions { - self.as_inner_mut().mode(mode); self + impl OpenOptionsExt for OpenOptions { + fn mode(&mut self, mode: i32) -> &mut OpenOptions { + self.as_inner_mut().mode(mode); self + } } } @@ -213,41 +236,58 @@ impl OpenOptionsExt for OpenOptions { // Process and Command //////////////////////////////////////////////////////////////////////////////// -/// Unix-specific extensions to the `std::process::Command` builder -pub trait CommandExt { - /// Sets the child process's user id. This translates to a - /// `setuid` call in the child process. Failure in the `setuid` - /// call will cause the spawn to fail. - fn uid(&mut self, id: uid_t) -> &mut process::Command; +/// Unix-specific extensions to primitives in the `std::process` module. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod process { + use prelude::v1::*; + use libc::{uid_t, gid_t}; + use process; + use sys; + use sys_common::{AsInnerMut, AsInner}; + + /// Unix-specific extensions to the `std::process::Command` builder + #[stable(feature = "rust1", since = "1.0.0")] + pub trait CommandExt { + /// Sets the child process's user id. This translates to a + /// `setuid` call in the child process. Failure in the `setuid` + /// call will cause the spawn to fail. + #[stable(feature = "rust1", since = "1.0.0")] + fn uid(&mut self, id: uid_t) -> &mut process::Command; + + /// Similar to `uid`, but sets the group id of the child process. This has + /// the same semantics as the `uid` field. + #[stable(feature = "rust1", since = "1.0.0")] + fn gid(&mut self, id: gid_t) -> &mut process::Command; + } - /// Similar to `uid`, but sets the group id of the child process. This has - /// the same semantics as the `uid` field. - fn gid(&mut self, id: gid_t) -> &mut process::Command; -} + #[stable(feature = "rust1", since = "1.0.0")] + impl CommandExt for process::Command { + fn uid(&mut self, id: uid_t) -> &mut process::Command { + self.as_inner_mut().uid = Some(id); + self + } -impl CommandExt for process::Command { - fn uid(&mut self, id: uid_t) -> &mut process::Command { - self.as_inner_mut().uid = Some(id); - self + fn gid(&mut self, id: gid_t) -> &mut process::Command { + self.as_inner_mut().gid = Some(id); + self + } } - fn gid(&mut self, id: gid_t) -> &mut process::Command { - self.as_inner_mut().gid = Some(id); - self + /// Unix-specific extensions to `std::process::ExitStatus` + #[stable(feature = "rust1", since = "1.0.0")] + pub trait ExitStatusExt { + /// If the process was terminated by a signal, returns that signal. + #[stable(feature = "rust1", since = "1.0.0")] + fn signal(&self) -> Option<i32>; } -} - -/// Unix-specific extensions to `std::process::ExitStatus` -pub trait ExitStatusExt { - /// If the process was terminated by a signal, returns that signal. - fn signal(&self) -> Option<i32>; -} -impl ExitStatusExt for process::ExitStatus { - fn signal(&self) -> Option<i32> { - match *self.as_inner() { - sys::process2::ExitStatus::Signal(s) => Some(s), - _ => None + #[stable(feature = "rust1", since = "1.0.0")] + impl ExitStatusExt for process::ExitStatus { + fn signal(&self) -> Option<i32> { + match *self.as_inner() { + sys::process2::ExitStatus::Signal(s) => Some(s), + _ => None + } } } } @@ -259,9 +299,14 @@ impl ExitStatusExt for process::ExitStatus { /// A prelude for conveniently writing platform-specific code. /// /// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt}; + pub use super::io::{Fd, AsRawFd}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] - pub use super::{CommandExt, ExitStatusExt}; + pub use super::fs::{PermissionsExt, OpenOptionsExt}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::process::{CommandExt, ExitStatusExt}; } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 83b6a14b78d..b22fa33e562 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -15,7 +15,7 @@ use io; use libc::{self, c_int, size_t}; use str; use sys::c; -use net::{SocketAddr, IpAddr}; +use net::SocketAddr; use sys::fd::FileDesc; use sys_common::AsInner; @@ -40,9 +40,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { - let fam = match addr.ip() { - IpAddr::V4(..) => libc::AF_INET, - IpAddr::V6(..) => libc::AF_INET6, + let fam = match *addr { + SocketAddr::V4(..) => libc::AF_INET, + SocketAddr::V6(..) => libc::AF_INET6, }; unsafe { let fd = try!(cvt(libc::socket(fam, ty, 0))); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index d332556d188..75aeafe6e3c 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -13,7 +13,7 @@ #![allow(unused_imports)] // lots of cfg code here use prelude::v1::*; -use os::unix::*; +use os::unix::prelude::*; use error::Error as StdError; use ffi::{CString, CStr, OsString, OsStr, AsOsStr}; @@ -206,7 +206,7 @@ pub fn current_exe() -> io::Result<PathBuf> { if err != 0 { return Err(io::Error::last_os_error()); } if sz == 0 { return Err(io::Error::last_os_error()); } v.set_len(sz as uint - 1); // chop off trailing NUL - Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v))) + Ok(PathBuf::new::<OsString>(OsStringExt::from_vec(v))) } } @@ -232,7 +232,7 @@ pub fn current_exe() -> io::Result<PathBuf> { Err(io::Error::last_os_error()) } else { let vec = CStr::from_ptr(v).to_bytes().to_vec(); - Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(vec))) + Ok(PathBuf::new::<OsString>(OsStringExt::from_vec(vec))) } } } @@ -253,7 +253,7 @@ pub fn current_exe() -> io::Result<PathBuf> { let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); if err != 0 { return Err(io::Error::last_os_error()); } v.set_len(sz as uint - 1); // chop off trailing NUL - Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v))) + Ok(PathBuf::new(OsString::from_vec(v))) } } @@ -286,7 +286,7 @@ pub fn args() -> Args { let vec = unsafe { let (argc, argv) = (*_NSGetArgc() as isize, *_NSGetArgv() as *const *const c_char); - range(0, argc as isize).map(|i| { + (0.. argc as isize).map(|i| { let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec(); OsStringExt::from_vec(bytes) }).collect::<Vec<_>>() diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index 89ab3e1981b..99591480752 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -16,6 +16,7 @@ use core::prelude::*; use borrow::Cow; use fmt::{self, Debug}; use vec::Vec; +#[cfg(stage0)] use slice::SliceExt as StdSliceExt; use str; use string::String; diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index 03b77eb75d7..20c409154b8 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -9,6 +9,7 @@ // except according to those terms. use prelude::v1::*; +use os::unix::prelude::*; use collections::HashMap; use env; @@ -17,7 +18,6 @@ use fmt; use io::{self, Error, ErrorKind}; use libc::{self, pid_t, c_void, c_int, gid_t, uid_t}; use mem; -use os::unix::OsStrExt; use ptr; use sys::pipe2::AnonPipe; use sys::{self, retry, c, cvt}; diff --git a/src/libstd/sys/unix/tty.rs b/src/libstd/sys/unix/tty.rs index f607f7c6a2f..e4973a8f9f3 100644 --- a/src/libstd/sys/unix/tty.rs +++ b/src/libstd/sys/unix/tty.rs @@ -23,6 +23,8 @@ pub struct TTY { } #[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "dragonfly", target_os = "freebsd", target_os = "bitrig", target_os = "openbsd"))] @@ -54,12 +56,6 @@ impl TTY { Err(sys_common::unimpl()) } - #[cfg(any(target_os = "linux", - target_os = "android", - target_os = "macos", - target_os = "freebsd", - target_os = "bitrig", - target_os = "openbsd"))] pub fn get_winsize(&mut self) -> IoResult<(int, int)> { unsafe { #[repr(C)] @@ -82,10 +78,4 @@ impl TTY { } } } - - #[cfg(any(target_os = "ios", - target_os = "dragonfly"))] - pub fn get_winsize(&mut self) -> IoResult<(int, int)> { - Err(sys_common::unimpl()) - } } diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index dc820a4ce45..7955397892b 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -14,197 +14,225 @@ //! descriptors, and sockets, but its functionality will grow over //! time. -#![unstable(feature = "std_misc")] +#![stable(feature = "rust1", since = "1.0.0")] -pub use sys_common::wtf8::{Wtf8Buf, EncodeWide}; +#[unstable(feature = "io_ext", + reason = "organization may change slightly and the primitives \ + provided may be tweaked")] +pub mod io { + use fs; + use libc; + use net; + use sys_common::AsInner; -use ffi::{OsStr, OsString}; -use fs::{self, OpenOptions}; -use libc; -use net; -use sys::os_str::Buf; -use sys_common::{AsInner, FromInner, AsInnerMut}; + #[allow(deprecated)] + use old_io; -#[allow(deprecated)] -use old_io; + /// Raw HANDLEs. + pub type Handle = libc::HANDLE; -/// Raw HANDLEs. -pub type Handle = libc::HANDLE; + /// Raw SOCKETs. + pub type Socket = libc::SOCKET; -/// Raw SOCKETs. -pub type Socket = libc::SOCKET; + /// Extract raw handles. + pub trait AsRawHandle { + /// Extract the raw handle, without taking any ownership. + fn as_raw_handle(&self) -> Handle; + } -/// Extract raw handles. -pub trait AsRawHandle { - /// Extract the raw handle, without taking any ownership. - fn as_raw_handle(&self) -> Handle; -} + #[allow(deprecated)] + impl AsRawHandle for old_io::fs::File { + fn as_raw_handle(&self) -> Handle { + self.as_inner().handle() + } + } -#[allow(deprecated)] -impl AsRawHandle for old_io::fs::File { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + impl AsRawHandle for fs::File { + fn as_raw_handle(&self) -> Handle { + self.as_inner().handle().raw() + } } -} -impl AsRawHandle for fs::File { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle().raw() + #[allow(deprecated)] + impl AsRawHandle for old_io::pipe::PipeStream { + fn as_raw_handle(&self) -> Handle { + self.as_inner().handle() + } } -} -#[allow(deprecated)] -impl AsRawHandle for old_io::pipe::PipeStream { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[allow(deprecated)] + impl AsRawHandle for old_io::net::pipe::UnixStream { + fn as_raw_handle(&self) -> Handle { + self.as_inner().handle() + } } -} -#[allow(deprecated)] -impl AsRawHandle for old_io::net::pipe::UnixStream { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[allow(deprecated)] + impl AsRawHandle for old_io::net::pipe::UnixListener { + fn as_raw_handle(&self) -> Handle { + self.as_inner().handle() + } } -} -#[allow(deprecated)] -impl AsRawHandle for old_io::net::pipe::UnixListener { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[allow(deprecated)] + impl AsRawHandle for old_io::net::pipe::UnixAcceptor { + fn as_raw_handle(&self) -> Handle { + self.as_inner().handle() + } } -} -#[allow(deprecated)] -impl AsRawHandle for old_io::net::pipe::UnixAcceptor { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + /// Extract raw sockets. + pub trait AsRawSocket { + fn as_raw_socket(&self) -> Socket; } -} -/// Extract raw sockets. -pub trait AsRawSocket { - fn as_raw_socket(&self) -> Socket; -} + #[allow(deprecated)] + impl AsRawSocket for old_io::net::tcp::TcpStream { + fn as_raw_socket(&self) -> Socket { + self.as_inner().fd() + } + } -#[allow(deprecated)] -impl AsRawSocket for old_io::net::tcp::TcpStream { - fn as_raw_socket(&self) -> Socket { - self.as_inner().fd() + #[allow(deprecated)] + impl AsRawSocket for old_io::net::tcp::TcpListener { + fn as_raw_socket(&self) -> Socket { + self.as_inner().socket() + } } -} -#[allow(deprecated)] -impl AsRawSocket for old_io::net::tcp::TcpListener { - fn as_raw_socket(&self) -> Socket { - self.as_inner().socket() + #[allow(deprecated)] + impl AsRawSocket for old_io::net::tcp::TcpAcceptor { + fn as_raw_socket(&self) -> Socket { + self.as_inner().socket() + } } -} -#[allow(deprecated)] -impl AsRawSocket for old_io::net::tcp::TcpAcceptor { - fn as_raw_socket(&self) -> Socket { - self.as_inner().socket() + #[allow(deprecated)] + impl AsRawSocket for old_io::net::udp::UdpSocket { + fn as_raw_socket(&self) -> Socket { + self.as_inner().fd() + } } -} -#[allow(deprecated)] -impl AsRawSocket for old_io::net::udp::UdpSocket { - fn as_raw_socket(&self) -> Socket { - self.as_inner().fd() + impl AsRawSocket for net::TcpStream { + fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + } + impl AsRawSocket for net::TcpListener { + fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + } + impl AsRawSocket for net::UdpSocket { + fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } } } -impl AsRawSocket for net::TcpStream { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } -} -impl AsRawSocket for net::TcpListener { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } -} -impl AsRawSocket for net::UdpSocket { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } -} +/// Windows-specific extensions to the primitives in the `std::ffi` module. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod ffi { + use ffi::{OsString, OsStr}; + use sys::os_str::Buf; + use sys_common::wtf8::Wtf8Buf; + use sys_common::{FromInner, AsInner}; -/// Windows-specific extensions to `OsString`. -pub trait OsStringExt { - /// Create an `OsString` from a potentially ill-formed UTF-16 slice of 16-bit code units. - /// - /// This is lossless: calling `.encode_wide()` on the resulting string - /// will always return the original code units. - fn from_wide(wide: &[u16]) -> Self; -} + pub use sys_common::wtf8::EncodeWide; -impl OsStringExt for OsString { - fn from_wide(wide: &[u16]) -> OsString { - FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) + /// Windows-specific extensions to `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStringExt { + /// Create an `OsString` from a potentially ill-formed UTF-16 slice of + /// 16-bit code units. + /// + /// This is lossless: calling `.encode_wide()` on the resulting string + /// will always return the original code units. + #[stable(feature = "rust1", since = "1.0.0")] + fn from_wide(wide: &[u16]) -> Self; } -} -/// Windows-specific extensions to `OsStr`. -pub trait OsStrExt { - /// Re-encode an `OsStr` as a wide character sequence, - /// i.e. potentially ill-formed UTF-16. - /// - /// This is lossless. Note that the encoding does not include a final null. - fn encode_wide(&self) -> EncodeWide; -} + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStringExt for OsString { + fn from_wide(wide: &[u16]) -> OsString { + FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) + } + } -impl OsStrExt for OsStr { - fn encode_wide(&self) -> EncodeWide { - self.as_inner().inner.encode_wide() + /// Windows-specific extensions to `OsStr`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStrExt { + /// Re-encode an `OsStr` as a wide character sequence, + /// i.e. potentially ill-formed UTF-16. + /// + /// This is lossless. Note that the encoding does not include a final + /// null. + #[stable(feature = "rust1", since = "1.0.0")] + fn encode_wide(&self) -> EncodeWide; } -} -// Windows-specific extensions to `OpenOptions` -pub trait OpenOptionsExt { - /// Override the `dwDesiredAccess` argument to the call to `CreateFile` with - /// the specified value. - fn desired_access(&mut self, access: i32) -> &mut Self; - - /// Override the `dwCreationDisposition` argument to the call to - /// `CreateFile` with the specified value. - /// - /// This will override any values of the standard `create` flags, for - /// example. - fn creation_disposition(&mut self, val: i32) -> &mut Self; - - /// Override the `dwFlagsAndAttributes` argument to the call to - /// `CreateFile` with the specified value. - /// - /// This will override any values of the standard flags on the `OpenOptions` - /// structure. - fn flags_and_attributes(&mut self, val: i32) -> &mut Self; - - /// Override the `dwShareMode` argument to the call to `CreateFile` with the - /// specified value. - /// - /// This will override any values of the standard flags on the `OpenOptions` - /// structure. - fn share_mode(&mut self, val: i32) -> &mut Self; + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStrExt for OsStr { + fn encode_wide(&self) -> EncodeWide { + self.as_inner().inner.encode_wide() + } + } } -impl OpenOptionsExt for OpenOptions { - fn desired_access(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().desired_access(access); self - } - fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().creation_disposition(access); self - } - fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().flags_and_attributes(access); self - } - fn share_mode(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().share_mode(access); self +/// Windows-specific extensions for the primitives in `std::fs` +#[unstable(feature = "fs_ext", reason = "may require more thought/methods")] +pub mod fs { + use fs::OpenOptions; + use sys_common::AsInnerMut; + + /// Windows-specific extensions to `OpenOptions` + pub trait OpenOptionsExt { + /// Override the `dwDesiredAccess` argument to the call to `CreateFile` + /// with the specified value. + fn desired_access(&mut self, access: i32) -> &mut Self; + + /// Override the `dwCreationDisposition` argument to the call to + /// `CreateFile` with the specified value. + /// + /// This will override any values of the standard `create` flags, for + /// example. + fn creation_disposition(&mut self, val: i32) -> &mut Self; + + /// Override the `dwFlagsAndAttributes` argument to the call to + /// `CreateFile` with the specified value. + /// + /// This will override any values of the standard flags on the + /// `OpenOptions` structure. + fn flags_and_attributes(&mut self, val: i32) -> &mut Self; + + /// Override the `dwShareMode` argument to the call to `CreateFile` with + /// the specified value. + /// + /// This will override any values of the standard flags on the + /// `OpenOptions` structure. + fn share_mode(&mut self, val: i32) -> &mut Self; + } + + impl OpenOptionsExt for OpenOptions { + fn desired_access(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().desired_access(access); self + } + fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().creation_disposition(access); self + } + fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().flags_and_attributes(access); self + } + fn share_mode(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().share_mode(access); self + } } } /// A prelude for conveniently writing platform-specific code. /// /// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::{Socket, Handle, AsRawSocket, AsRawHandle}; - #[doc(no_inline)] - pub use super::{OsStrExt, OsStringExt}; + pub use super::io::{Socket, Handle, AsRawSocket, AsRawHandle}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] - pub use super::OpenOptionsExt; + pub use super::fs::OpenOptionsExt; } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 6b0f6a78c85..d02fe79fcdb 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -20,7 +20,7 @@ use libc; use mem; use num::Int; use old_io::{self, IoResult, IoError}; -use os::windows::{OsStrExt, OsStringExt}; +use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; use sync::{Once, ONCE_INIT}; diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 6caa4df5dfe..e092faf4935 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -14,7 +14,7 @@ use io; use libc::consts::os::extra::INVALID_SOCKET; use libc::{self, c_int, c_void}; use mem; -use net::{SocketAddr, IpAddr}; +use net::SocketAddr; use num::{SignedInt, Int}; use rt; use sync::{Once, ONCE_INIT}; @@ -73,9 +73,9 @@ pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T { impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { - let fam = match addr.ip() { - IpAddr::V4(..) => libc::AF_INET, - IpAddr::V6(..) => libc::AF_INET6, + let fam = match *addr { + SocketAddr::V4(..) => libc::AF_INET, + SocketAddr::V6(..) => libc::AF_INET6, }; match unsafe { libc::socket(fam, ty, 0) } { INVALID_SOCKET => Err(last_error()), diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index ecd538abfb4..4f6c4c9aab3 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -13,7 +13,7 @@ #![allow(bad_style)] use prelude::v1::*; -use os::windows::*; +use os::windows::prelude::*; use error::Error as StdError; use ffi::{OsString, OsStr, AsOsStr}; @@ -25,6 +25,7 @@ use mem; #[allow(deprecated)] use old_io::{IoError, IoResult}; use ops::Range; +use os::windows::ffi::EncodeWide; use path::{self, PathBuf}; use ptr; use slice; diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 8a6a485cbbe..e3cf5da59f0 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -19,7 +19,7 @@ use fmt; use fs; use io::{self, Error}; use libc::{self, c_void}; -use os::windows::OsStrExt; +use os::windows::ffi::OsStrExt; use ptr; use sync::{StaticMutex, MUTEX_INIT}; use sys::handle::Handle; @@ -128,6 +128,7 @@ impl Process { use env::split_paths; use mem; use iter::IteratorExt; + #[cfg(stage0)] use str::StrExt; // To have the spawning semantics of unix/windows stay the same, we need to diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index adc3b77407a..a40b26c85be 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -402,18 +402,18 @@ pub fn park() { /// the specified duration has been reached (may wake spuriously). /// /// The semantics of this function are equivalent to `park()` except that the -/// thread will be blocked for roughly no longer than dur. This method +/// thread will be blocked for roughly no longer than *duration*. This method /// should not be used for precise timing due to anomalies such as /// preemption or platform differences that may not cause the maximum -/// amount of time waited to be precisely dur +/// amount of time waited to be precisely *duration* long. /// /// See the module doc for more detail. #[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")] -pub fn park_timeout(dur: Duration) { +pub fn park_timeout(duration: Duration) { let thread = current(); let mut guard = thread.inner.lock.lock().unwrap(); if !*guard { - let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap(); + let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap(); guard = g; } *guard = false; @@ -502,11 +502,11 @@ impl Thread { /// Deprecated: use module-level free function. #[deprecated(since = "1.0.0", reason = "use module-level free function")] #[unstable(feature = "std_misc", reason = "recently introduced")] - pub fn park_timeout(dur: Duration) { + pub fn park_timeout(duration: Duration) { let thread = current(); let mut guard = thread.inner.lock.lock().unwrap(); if !*guard { - let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap(); + let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap(); guard = g; } *guard = false; diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 48c045ee4f9..c38556b0782 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -361,8 +361,7 @@ pub mod rt { parse::parse_stmt_from_source_str("<quote expansion>".to_string(), s, self.cfg(), - Vec::new(), - self.parse_sess()) + self.parse_sess()).expect("parse error") } fn parse_expr(&self, s: String) -> P<ast::Expr> { @@ -407,7 +406,7 @@ pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box<base::MacResult+'cx> { - let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts); + let expanded = expand_parse_call(cx, sp, "parse_expr", vec!(), tts); base::MacEager::expr(expanded) } @@ -415,8 +414,7 @@ pub fn expand_quote_item<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box<base::MacResult+'cx> { - let expanded = expand_parse_call(cx, sp, "parse_item_with_outer_attributes", - vec!(), tts); + let expanded = expand_parse_call(cx, sp, "parse_item", vec!(), tts); base::MacEager::expr(expanded) } @@ -448,9 +446,7 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box<base::MacResult+'static> { - let e_attrs = cx.expr_vec_ng(sp); - let expanded = expand_parse_call(cx, sp, "parse_stmt", - vec!(e_attrs), tts); + let expanded = expand_parse_call(cx, sp, "parse_stmt", vec!(), tts); base::MacEager::expr(expanded) } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index eb0daac3ab8..c61aec0069d 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -115,7 +115,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree -> Option<SmallVector<P<ast::Item>>> { let mut ret = SmallVector::zero(); while self.p.token != token::Eof { - match self.p.parse_item_with_outer_attributes() { + match self.p.parse_item() { Some(item) => ret.push(item), None => self.p.span_fatal( self.p.span, diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index eb15d708232..b7d40a46f3e 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -521,12 +521,15 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { // check at the beginning and the parser checks after each bump p.check_unknown_macro_variable(); match name { - "item" => match p.parse_item(Vec::new()) { + "item" => match p.parse_item() { Some(i) => token::NtItem(i), None => p.fatal("expected an item keyword") }, "block" => token::NtBlock(p.parse_block()), - "stmt" => token::NtStmt(p.parse_stmt(Vec::new())), + "stmt" => match p.parse_stmt() { + Some(s) => token::NtStmt(s), + None => p.fatal("expected a statement") + }, "pat" => token::NtPat(p.parse_pat()), "expr" => token::NtExpr(p.parse_expr()), "ty" => token::NtTy(p.parse_ty()), diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 7575d4b5ecd..7a2ae55e914 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -17,7 +17,6 @@ use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::{parse, parse_or_else}; use parse::lexer::new_tt_reader; use parse::parser::Parser; -use parse::attr::ParserAttr; use parse::token::{self, special_idents, gensym_ident, NtTT, Token}; use parse::token::Token::*; use print; @@ -68,15 +67,8 @@ impl<'a> MacResult for ParserAnyMacro<'a> { } fn make_items(self: Box<ParserAnyMacro<'a>>) -> Option<SmallVector<P<ast::Item>>> { let mut ret = SmallVector::zero(); - loop { - let mut parser = self.parser.borrow_mut(); - // so... do outer attributes attached to the macro invocation - // just disappear? This question applies to make_impl_items, as - // well. - match parser.parse_item_with_outer_attributes() { - Some(item) => ret.push(item), - None => break - } + while let Some(item) = self.parser.borrow_mut().parse_item() { + ret.push(item); } self.ensure_complete_parse(false); Some(ret) @@ -89,7 +81,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> { let mut parser = self.parser.borrow_mut(); match parser.token { token::Eof => break, - _ => ret.push(parser.parse_impl_item_with_outer_attributes()) + _ => ret.push(parser.parse_impl_item()) } } self.ensure_complete_parse(false); @@ -97,10 +89,9 @@ impl<'a> MacResult for ParserAnyMacro<'a> { } fn make_stmt(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Stmt>> { - let attrs = self.parser.borrow_mut().parse_outer_attributes(); - let ret = self.parser.borrow_mut().parse_stmt(attrs); + let ret = self.parser.borrow_mut().parse_stmt(); self.ensure_complete_parse(true); - Some(ret) + ret } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index f60ac8f3f33..b53bb4bc75e 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -37,7 +37,6 @@ #![feature(staged_api)] #![feature(std_misc)] #![feature(unicode)] -#![feature(io)] #![feature(path_ext)] extern crate arena; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index db5583cf13a..a5dd4f22224 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -19,9 +19,8 @@ use ptr::P; /// A parser that can parse attributes. pub trait ParserAttr { fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute>; + fn parse_inner_attributes(&mut self) -> Vec<ast::Attribute>; fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute; - fn parse_inner_attrs_and_next(&mut self) - -> (Vec<ast::Attribute>, Vec<ast::Attribute>); fn parse_meta_item(&mut self) -> P<ast::MetaItem>; fn parse_meta_seq(&mut self) -> Vec<P<ast::MetaItem>>; fn parse_optional_meta(&mut self) -> Vec<P<ast::MetaItem>>; @@ -118,45 +117,40 @@ impl<'a> ParserAttr for Parser<'a> { /// Parse attributes that appear after the opening of an item. These should /// be preceded by an exclamation mark, but we accept and warn about one - /// terminated by a semicolon. In addition to a vector of inner attributes, - /// this function also returns a vector that may contain the first outer - /// attribute of the next item (since we can't know whether the attribute - /// is an inner attribute of the containing item or an outer attribute of - /// the first contained item until we see the semi). - - /// matches inner_attrs* outer_attr? - /// you can make the 'next' field an Option, but the result is going to be - /// more useful as a vector. - fn parse_inner_attrs_and_next(&mut self) - -> (Vec<ast::Attribute> , Vec<ast::Attribute> ) { - let mut inner_attrs: Vec<ast::Attribute> = Vec::new(); - let mut next_outer_attrs: Vec<ast::Attribute> = Vec::new(); + /// terminated by a semicolon. + + /// matches inner_attrs* + fn parse_inner_attributes(&mut self) -> Vec<ast::Attribute> { + let mut attrs: Vec<ast::Attribute> = vec![]; loop { - let attr = match self.token { + match self.token { token::Pound => { - self.parse_attribute(true) + // Don't even try to parse if it's not an inner attribute. + if !self.look_ahead(1, |t| t == &token::Not) { + break; + } + + let attr = self.parse_attribute(true); + assert!(attr.node.style == ast::AttrInner); + attrs.push(attr); } token::DocComment(s) => { // we need to get the position of this token before we bump. let Span { lo, hi, .. } = self.span; - self.bump(); - attr::mk_sugared_doc_attr(attr::mk_attr_id(), - self.id_to_interned_str(s.ident()), - lo, - hi) - } - _ => { - break; + let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), + self.id_to_interned_str(s.ident()), + lo, hi); + if attr.node.style == ast::AttrInner { + attrs.push(attr); + self.bump(); + } else { + break; + } } - }; - if attr.node.style == ast::AttrInner { - inner_attrs.push(attr); - } else { - next_outer_attrs.push(attr); - break; + _ => break } } - (inner_attrs, next_outer_attrs) + attrs } /// matches meta_item = IDENT diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index f542246705c..82ba873e54b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -96,9 +96,7 @@ pub fn parse_crate_attrs_from_file( cfg: ast::CrateConfig, sess: &ParseSess ) -> Vec<ast::Attribute> { - let mut parser = new_parser_from_file(sess, cfg, input); - let (inner, _) = parser.parse_inner_attrs_and_next(); - inner + new_parser_from_file(sess, cfg, input).parse_inner_attributes() } pub fn parse_crate_from_source_str(name: String, @@ -122,8 +120,7 @@ pub fn parse_crate_attrs_from_source_str(name: String, cfg, name, source); - let (inner, _) = maybe_aborted(p.parse_inner_attrs_and_next(),p); - inner + maybe_aborted(p.parse_inner_attributes(), p) } pub fn parse_expr_from_source_str(name: String, @@ -141,7 +138,7 @@ pub fn parse_item_from_source_str(name: String, sess: &ParseSess) -> Option<P<ast::Item>> { let mut p = new_parser_from_source_str(sess, cfg, name, source); - maybe_aborted(p.parse_item_with_outer_attributes(),p) + maybe_aborted(p.parse_item(),p) } pub fn parse_meta_from_source_str(name: String, @@ -156,16 +153,15 @@ pub fn parse_meta_from_source_str(name: String, pub fn parse_stmt_from_source_str(name: String, source: String, cfg: ast::CrateConfig, - attrs: Vec<ast::Attribute> , sess: &ParseSess) - -> P<ast::Stmt> { + -> Option<P<ast::Stmt>> { let mut p = new_parser_from_source_str( sess, cfg, name, source ); - maybe_aborted(p.parse_stmt(attrs),p) + maybe_aborted(p.parse_stmt(), p) } // Note: keep in sync with `with_hygiene::parse_tts_from_source_str` diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ea1c1705514..bf2b2c0afe6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -39,7 +39,7 @@ use ast::{LitStr, LitInt, Local, LocalLet}; use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces}; use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource}; use ast::{MutTy, BiMul, Mutability}; -use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; +use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; use ast::{PolyTraitRef, QSelf}; @@ -77,8 +77,8 @@ use owned_slice::OwnedSlice; use std::collections::HashSet; use std::io::prelude::*; -use std::iter; use std::mem; +#[cfg(stage0)] use std::num::Float; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -117,11 +117,6 @@ pub enum BoundParsingMode { Modified, } -/// The `Err` case indicates a failure to parse any kind of item. -/// The attributes are returned. -type MaybeItem = Result<P<Item>, Vec<Attribute>>; - - /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression /// dropped into the token stream, which happens while parsing the result of /// macro expansion). Placement of these is not as complex as I feared it would @@ -208,7 +203,7 @@ macro_rules! maybe_whole { } } ); - (Some $p:expr, $constructor:ident) => ( + (Some deref $p:expr, $constructor:ident) => ( { let found = match ($p).token { token::Interpolated(token::$constructor(_)) => { @@ -217,7 +212,7 @@ macro_rules! maybe_whole { _ => None }; if let Some(token::Interpolated(token::$constructor(x))) = found { - return Some(x.clone()); + return Some((*x).clone()); } } ); @@ -749,7 +744,7 @@ impl<'a> Parser<'a> { // would encounter a `>` and stop. This lets the parser handle trailing // commas in generic parameters, because it can stop either after // parsing a type or after parsing a comma. - for i in iter::count(0, 1) { + for i in 0.. { if self.check(&token::Gt) || self.token == token::BinOp(token::Shr) || self.token == token::Ge @@ -1240,41 +1235,6 @@ impl<'a> Parser<'a> { } } - /// Parses `type Foo;` in a trait declaration only. The `type` keyword has - /// already been parsed. - fn parse_assoc_ty_in_trait(&mut self, attrs: Vec<Attribute>) - -> P<TraitItem> { - let TyParam {id, ident, bounds, default, span} = self.parse_ty_param(); - self.expect(&token::Semi); - P(TraitItem { - id: id, - ident: ident, - attrs: attrs, - node: TypeTraitItem(bounds, default), - span: span, - }) - } - - /// Parses `type Foo = TYPE;` in an implementation declaration only. The - /// `type` keyword has already been parsed. - fn parse_assoc_ty_in_impl(&mut self, attrs: Vec<Attribute>, vis: Visibility) - -> P<ImplItem> { - let lo = self.span.lo; - let ident = self.parse_ident(); - self.expect(&token::Eq); - let typ = self.parse_ty_sum(); - let hi = self.span.hi; - self.expect(&token::Semi); - P(ImplItem { - id: ast::DUMMY_NODE_ID, - span: mk_sp(lo, hi), - ident: ident, - vis: vis, - attrs: attrs, - node: TypeImplItem(typ), - }) - } - /// Parse the items in a trait declaration pub fn parse_trait_items(&mut self) -> Vec<P<TraitItem>> { self.parse_unspanned_seq( @@ -1282,13 +1242,14 @@ impl<'a> Parser<'a> { &token::CloseDelim(token::Brace), seq_sep_none(), |p| { + let lo = p.span.lo; let mut attrs = p.parse_outer_attributes(); - if p.eat_keyword(keywords::Type) { - p.parse_assoc_ty_in_trait(attrs) + let (name, node) = if p.eat_keyword(keywords::Type) { + let TyParam {ident, bounds, default, ..} = p.parse_ty_param(); + p.expect(&token::Semi); + (ident, TypeTraitItem(bounds, default)) } else { - let lo = p.span.lo; - let style = p.parse_unsafety(); let abi = if p.eat_keyword(keywords::Extern) { p.parse_opt_abi().unwrap_or(abi::C) @@ -1316,7 +1277,6 @@ impl<'a> Parser<'a> { explicit_self: explicit_self, }; - let hi = p.last_span.hi; let body = match p.token { token::Semi => { p.bump(); @@ -1337,15 +1297,16 @@ impl<'a> Parser<'a> { token_str)[..]) } }; + (ident, ast::MethodTraitItem(sig, body)) + }; - P(TraitItem { - id: ast::DUMMY_NODE_ID, - ident: ident, - attrs: attrs, - node: ast::MethodTraitItem(sig, body), - span: mk_sp(lo, hi), - }) - } + P(TraitItem { + id: ast::DUMMY_NODE_ID, + ident: name, + attrs: attrs, + node: node, + span: mk_sp(lo, p.last_span.hi), + }) }) } @@ -3647,41 +3608,47 @@ impl<'a> Parser<'a> { }) } - /// Get an expected item after attributes error message. - fn expected_item_err(attrs: &[Attribute]) -> &'static str { - match attrs.last() { + /// Emit an expected item after attributes error. + fn expected_item_err(&self, attrs: &[Attribute]) { + let message = match attrs.last() { Some(&Attribute { node: ast::Attribute_ { is_sugared_doc: true, .. }, .. }) => { "expected item after doc comment" } _ => "expected item after attributes", - } + }; + + self.span_err(self.last_span, message); } /// Parse a statement. may include decl. - /// Precondition: any attributes are parsed already - pub fn parse_stmt(&mut self, item_attrs: Vec<Attribute>) -> P<Stmt> { - maybe_whole!(self, NtStmt); + pub fn parse_stmt(&mut self) -> Option<P<Stmt>> { + self.parse_stmt_().map(P) + } + + fn parse_stmt_(&mut self) -> Option<Stmt> { + maybe_whole!(Some deref self, NtStmt); fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) { // If we have attributes then we should have an item if !attrs.is_empty() { - let last_span = p.last_span; - p.span_err(last_span, Parser::expected_item_err(attrs)); + p.expected_item_err(attrs); } } let lo = self.span.lo; - if self.check_keyword(keywords::Let) { - check_expected_item(self, &item_attrs[..]); + let attrs = self.parse_outer_attributes(); + + Some(if self.check_keyword(keywords::Let) { + check_expected_item(self, &attrs); self.expect_keyword(keywords::Let); let decl = self.parse_let(); - P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) + spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)) } else if self.token.is_ident() && !self.token.is_any_keyword() && self.look_ahead(1, |t| *t == token::Not) { // it's a macro invocation: - check_expected_item(self, &item_attrs[..]); + check_expected_item(self, &attrs); // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... @@ -3728,12 +3695,11 @@ impl<'a> Parser<'a> { }; if id.name == token::special_idents::invalid.name { - P(spanned(lo, - hi, - StmtMac(P(spanned(lo, + spanned(lo, hi, + StmtMac(P(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))), - style))) + style)) } else { // if it has a special ident, it's definitely an item // @@ -3747,35 +3713,38 @@ impl<'a> Parser<'a> { followed by a semicolon"); } } - P(spanned(lo, hi, StmtDecl( + spanned(lo, hi, StmtDecl( P(spanned(lo, hi, DeclItem( self.mk_item( lo, hi, id /*id is good here*/, ItemMac(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))), Inherited, Vec::new(/*no attrs*/))))), - ast::DUMMY_NODE_ID))) + ast::DUMMY_NODE_ID)) } } else { - let found_attrs = !item_attrs.is_empty(); - let item_err = Parser::expected_item_err(&item_attrs[..]); - match self.parse_item_(item_attrs, false) { - Ok(i) => { + match self.parse_item_(attrs, false) { + Some(i) => { let hi = i.span.hi; let decl = P(spanned(lo, hi, DeclItem(i))); - P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) + spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID)) } - Err(_) => { - if found_attrs { - let last_span = self.last_span; - self.span_err(last_span, item_err); + None => { + // Do not attempt to parse an expression if we're done here. + if self.token == token::Semi { + self.bump(); + return None; + } + + if self.token == token::CloseDelim(token::Brace) { + return None; } // Remainder are line-expr stmts. let e = self.parse_expr_res(RESTRICTION_STMT_EXPR); - P(spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID))) + spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID)) } } - } + }) } /// Is this expression a successfully-parsed statement? @@ -3798,153 +3767,110 @@ impl<'a> Parser<'a> { "place this code inside a block"); } - return self.parse_block_tail_(lo, DefaultBlock, Vec::new()); + self.parse_block_tail(lo, DefaultBlock) } /// Parse a block. Inner attrs are allowed. - fn parse_inner_attrs_and_block(&mut self) - -> (Vec<Attribute> , P<Block>) { - + fn parse_inner_attrs_and_block(&mut self) -> (Vec<Attribute>, P<Block>) { maybe_whole!(pair_empty self, NtBlock); let lo = self.span.lo; self.expect(&token::OpenDelim(token::Brace)); - let (inner, next) = self.parse_inner_attrs_and_next(); - - (inner, self.parse_block_tail_(lo, DefaultBlock, next)) + (self.parse_inner_attributes(), + self.parse_block_tail(lo, DefaultBlock)) } + /// Parse the rest of a block expression or function body /// Precondition: already parsed the '{'. fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> { - self.parse_block_tail_(lo, s, Vec::new()) - } - - /// Parse the rest of a block expression or function body - fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, - first_item_attrs: Vec<Attribute>) -> P<Block> { let mut stmts = vec![]; let mut expr = None; - let mut attributes_box = first_item_attrs; - while self.token != token::CloseDelim(token::Brace) { - // parsing items even when they're not allowed lets us give - // better error messages and recover more gracefully. - attributes_box.push_all(&self.parse_outer_attributes()); - match self.token { - token::Semi => { - if !attributes_box.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attributes_box[..])); - attributes_box = Vec::new(); - } - self.bump(); // empty - } - token::CloseDelim(token::Brace) => { - // fall through and out. + while !self.eat(&token::CloseDelim(token::Brace)) { + let Spanned {node, span} = if let Some(s) = self.parse_stmt_() { + s + } else { + // Found only `;` or `}`. + continue; + }; + match node { + StmtExpr(e, _) => { + self.handle_expression_like_statement(e, span, &mut stmts, &mut expr); } - _ => { - let stmt = self.parse_stmt(attributes_box); - attributes_box = Vec::new(); - stmt.and_then(|Spanned {node, span}| match node { - StmtExpr(e, stmt_id) => { - self.handle_expression_like_statement(e, - stmt_id, - span, - &mut stmts, - &mut expr); + StmtMac(mac, MacStmtWithoutBraces) => { + // statement macro without braces; might be an + // expr depending on whether a semicolon follows + match self.token { + token::Semi => { + stmts.push(P(Spanned { + node: StmtMac(mac, MacStmtWithSemicolon), + span: span, + })); + self.bump(); } - StmtMac(mac, MacStmtWithoutBraces) => { - // statement macro without braces; might be an - // expr depending on whether a semicolon follows - match self.token { - token::Semi => { - stmts.push(P(Spanned { - node: StmtMac(mac, - MacStmtWithSemicolon), - span: span, - })); - self.bump(); - } - _ => { - let e = self.mk_mac_expr(span.lo, - span.hi, - mac.and_then(|m| m.node)); - let e = self.parse_dot_or_call_expr_with(e); - let e = self.parse_more_binops(e, 0); - let e = self.parse_assign_expr_with(e); - self.handle_expression_like_statement( - e, - ast::DUMMY_NODE_ID, - span, - &mut stmts, - &mut expr); - } - } + _ => { + let e = self.mk_mac_expr(span.lo, span.hi, + mac.and_then(|m| m.node)); + let e = self.parse_dot_or_call_expr_with(e); + let e = self.parse_more_binops(e, 0); + let e = self.parse_assign_expr_with(e); + self.handle_expression_like_statement( + e, + span, + &mut stmts, + &mut expr); } - StmtMac(m, style) => { - // statement macro; might be an expr - match self.token { - token::Semi => { - stmts.push(P(Spanned { - node: StmtMac(m, - MacStmtWithSemicolon), - span: span, - })); - self.bump(); - } - token::CloseDelim(token::Brace) => { - // if a block ends in `m!(arg)` without - // a `;`, it must be an expr - expr = Some( - self.mk_mac_expr(span.lo, - span.hi, + } + } + StmtMac(m, style) => { + // statement macro; might be an expr + match self.token { + token::Semi => { + stmts.push(P(Spanned { + node: StmtMac(m, MacStmtWithSemicolon), + span: span, + })); + self.bump(); + } + token::CloseDelim(token::Brace) => { + // if a block ends in `m!(arg)` without + // a `;`, it must be an expr + expr = Some(self.mk_mac_expr(span.lo, span.hi, m.and_then(|x| x.node))); - } - _ => { - stmts.push(P(Spanned { - node: StmtMac(m, style), - span: span - })); - } - } } - _ => { // all other kinds of statements: - if classify::stmt_ends_with_semi(&node) { - self.commit_stmt_expecting(token::Semi); - } - + _ => { stmts.push(P(Spanned { - node: node, + node: StmtMac(m, style), span: span })); } - }) + } } - } - } + _ => { // all other kinds of statements: + if classify::stmt_ends_with_semi(&node) { + self.commit_stmt_expecting(token::Semi); + } - if !attributes_box.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attributes_box[..])); + stmts.push(P(Spanned { + node: node, + span: span + })); + } + } } - let hi = self.span.hi; - self.bump(); P(ast::Block { stmts: stmts, expr: expr, id: ast::DUMMY_NODE_ID, rules: s, - span: mk_sp(lo, hi), + span: mk_sp(lo, self.last_span.hi), }) } fn handle_expression_like_statement( &mut self, e: P<Expr>, - stmt_id: NodeId, span: Span, stmts: &mut Vec<P<Stmt>>, last_block_expr: &mut Option<P<Expr>>) { @@ -3964,14 +3890,14 @@ impl<'a> Parser<'a> { expn_id: span.expn_id, }; stmts.push(P(Spanned { - node: StmtSemi(e, stmt_id), + node: StmtSemi(e, ast::DUMMY_NODE_ID), span: span_with_semi, })); } token::CloseDelim(token::Brace) => *last_block_expr = Some(e), _ => { stmts.push(P(Spanned { - node: StmtExpr(e, stmt_id), + node: StmtExpr(e, ast::DUMMY_NODE_ID), span: span })); } @@ -4626,14 +4552,30 @@ impl<'a> Parser<'a> { } /// Parse an impl item. - pub fn parse_impl_item_with_outer_attributes(&mut self) -> P<ImplItem> { - let attrs = self.parse_outer_attributes(); + pub fn parse_impl_item(&mut self) -> P<ImplItem> { + let lo = self.span.lo; + let mut attrs = self.parse_outer_attributes(); let vis = self.parse_visibility(); - if self.eat_keyword(keywords::Type) { - self.parse_assoc_ty_in_impl(attrs, vis) + let (name, node) = if self.eat_keyword(keywords::Type) { + let name = self.parse_ident(); + self.expect(&token::Eq); + let typ = self.parse_ty_sum(); + self.expect(&token::Semi); + (name, TypeImplItem(typ)) } else { - self.parse_method(attrs, vis) - } + let (name, inner_attrs, node) = self.parse_impl_method(vis); + attrs.extend(inner_attrs.into_iter()); + (name, node) + }; + + P(ImplItem { + id: ast::DUMMY_NODE_ID, + span: mk_sp(lo, self.last_span.hi), + ident: name, + vis: vis, + attrs: attrs, + node: node + }) } fn complain_if_pub_macro(&mut self, visa: Visibility, span: Span) { @@ -4647,76 +4589,58 @@ impl<'a> Parser<'a> { } } - /// Parse a method in a trait impl, starting with `attrs` attributes. - pub fn parse_method(&mut self, - attrs: Vec<Attribute>, - vis: Visibility) - -> P<ImplItem> { - let lo = self.span.lo; - + /// Parse a method or a macro invocation in a trait impl. + fn parse_impl_method(&mut self, vis: Visibility) + -> (Ident, Vec<ast::Attribute>, ast::ImplItem_) { // code copied from parse_macro_use_or_failure... abstraction! - let (method_, hi, new_attrs, ident) = { - if !self.token.is_any_keyword() - && self.look_ahead(1, |t| *t == token::Not) - && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) - || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { - // method macro. + if !self.token.is_any_keyword() + && self.look_ahead(1, |t| *t == token::Not) + && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) + || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { + // method macro. - let last_span = self.last_span; - self.complain_if_pub_macro(vis, last_span); - - let pth = self.parse_path(NoTypesAllowed); - self.expect(&token::Not); - - // eat a matched-delimiter token tree: - let delim = self.expect_open_delim(); - let tts = self.parse_seq_to_end(&token::CloseDelim(delim), - seq_sep_none(), - |p| p.parse_token_tree()); - let m_ = ast::MacInvocTT(pth, tts, EMPTY_CTXT); - let m: ast::Mac = codemap::Spanned { node: m_, - span: mk_sp(self.span.lo, - self.span.hi) }; - if delim != token::Brace { - self.expect(&token::Semi) - } - (ast::MacImplItem(m), self.span.hi, attrs, - token::special_idents::invalid) - } else { - let unsafety = self.parse_unsafety(); - let abi = if self.eat_keyword(keywords::Extern) { - self.parse_opt_abi().unwrap_or(abi::C) - } else { - abi::Rust - }; - self.expect_keyword(keywords::Fn); - let ident = self.parse_ident(); - let mut generics = self.parse_generics(); - let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { - p.parse_arg() - }); - self.parse_where_clause(&mut generics); - let (inner_attrs, body) = self.parse_inner_attrs_and_block(); - let body_span = body.span; - let mut new_attrs = attrs; - new_attrs.push_all(&inner_attrs[..]); - (MethodImplItem(ast::MethodSig { - generics: generics, - abi: abi, - explicit_self: explicit_self, - unsafety: unsafety, - decl: decl - }, body), body_span.hi, new_attrs, ident) + let last_span = self.last_span; + self.complain_if_pub_macro(vis, last_span); + + let pth = self.parse_path(NoTypesAllowed); + self.expect(&token::Not); + + // eat a matched-delimiter token tree: + let delim = self.expect_open_delim(); + let tts = self.parse_seq_to_end(&token::CloseDelim(delim), + seq_sep_none(), + |p| p.parse_token_tree()); + let m_ = ast::MacInvocTT(pth, tts, EMPTY_CTXT); + let m: ast::Mac = codemap::Spanned { node: m_, + span: mk_sp(self.span.lo, + self.span.hi) }; + if delim != token::Brace { + self.expect(&token::Semi) } - }; - P(ImplItem { - id: ast::DUMMY_NODE_ID, - attrs: new_attrs, - vis: vis, - ident: ident, - node: method_, - span: mk_sp(lo, hi), - }) + (token::special_idents::invalid, vec![], ast::MacImplItem(m)) + } else { + let unsafety = self.parse_unsafety(); + let abi = if self.eat_keyword(keywords::Extern) { + self.parse_opt_abi().unwrap_or(abi::C) + } else { + abi::Rust + }; + self.expect_keyword(keywords::Fn); + let ident = self.parse_ident(); + let mut generics = self.parse_generics(); + let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { + p.parse_arg() + }); + self.parse_where_clause(&mut generics); + let (inner_attrs, body) = self.parse_inner_attrs_and_block(); + (ident, inner_attrs, MethodImplItem(ast::MethodSig { + generics: generics, + abi: abi, + explicit_self: explicit_self, + unsafety: unsafety, + decl: decl + }, body)) + } } /// Parse trait Foo { ... } @@ -4747,28 +4671,6 @@ impl<'a> Parser<'a> { (ident, ItemTrait(unsafety, tps, bounds, meths), None) } - fn parse_impl_items(&mut self) -> (Vec<P<ImplItem>>, Vec<Attribute>) { - let mut impl_items = Vec::new(); - self.expect(&token::OpenDelim(token::Brace)); - let (inner_attrs, mut method_attrs) = - self.parse_inner_attrs_and_next(); - loop { - method_attrs.extend(self.parse_outer_attributes().into_iter()); - if method_attrs.is_empty() && self.eat(&token::CloseDelim(token::Brace)) { - break; - } - - let vis = self.parse_visibility(); - impl_items.push(if self.eat_keyword(keywords::Type) { - self.parse_assoc_ty_in_impl(method_attrs, vis) - } else { - self.parse_method(method_attrs, vis) - }); - method_attrs = vec![]; - } - (impl_items, inner_attrs) - } - /// Parses items implementations variants /// impl<T> Foo { ... } /// impl<T> ToString for &'static T { ... } @@ -4835,7 +4737,14 @@ impl<'a> Parser<'a> { ty = self.parse_ty_sum(); } self.parse_where_clause(&mut generics); - let (impl_items, attrs) = self.parse_impl_items(); + + self.expect(&token::OpenDelim(token::Brace)); + let attrs = self.parse_inner_attributes(); + + let mut impl_items = vec![]; + while !self.eat(&token::CloseDelim(token::Brace)) { + impl_items.push(self.parse_impl_item()); + } (ast_util::impl_pretty_name(&opt_trait, Some(&*ty)), ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), @@ -5074,53 +4983,16 @@ impl<'a> Parser<'a> { } } - /// Given a termination token and a vector of already-parsed - /// attributes (of length 0 or 1), parse all of the items in a module - fn parse_mod_items(&mut self, - term: token::Token, - first_item_attrs: Vec<Attribute>, - inner_lo: BytePos) - -> Mod { - // Parse all of the items up to closing or an attribute. - - let mut attrs = first_item_attrs; - attrs.push_all(&self.parse_outer_attributes()); + /// Given a termination token, parse all of the items in a module + fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> Mod { let mut items = vec![]; - - loop { - match self.parse_item_(attrs, true) { - Err(returned_attrs) => { - attrs = returned_attrs; - break - } - Ok(item) => { - attrs = self.parse_outer_attributes(); - items.push(item) - } - } - } - - // don't think this other loop is even necessary.... - - while self.token != term { - let mut attrs = mem::replace(&mut attrs, vec![]); - attrs.push_all(&self.parse_outer_attributes()); - debug!("parse_mod_items: parse_item_(attrs={:?})", attrs); - match self.parse_item_(attrs, true /* macros allowed */) { - Ok(item) => items.push(item), - Err(_) => { - let token_str = self.this_token_to_string(); - self.fatal(&format!("expected item, found `{}`", - token_str)) - } - } + while let Some(item) = self.parse_item() { + items.push(item); } - if !attrs.is_empty() { - // We parsed attributes for the first item but didn't find it - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attrs[..])); + if !self.eat(term) { + let token_str = self.this_token_to_string(); + self.fatal(&format!("expected item, found `{}`", token_str)) } ast::Mod { @@ -5158,12 +5030,11 @@ impl<'a> Parser<'a> { let mod_inner_lo = self.span.lo; let old_owns_directory = self.owns_directory; self.owns_directory = true; - let (inner, next) = self.parse_inner_attrs_and_next(); - let m = self.parse_mod_items(token::CloseDelim(token::Brace), next, mod_inner_lo); - self.expect(&token::CloseDelim(token::Brace)); + let attrs = self.parse_inner_attributes(); + let m = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo); self.owns_directory = old_owns_directory; self.pop_mod_path(); - (id, ItemMod(m), Some(inner)) + (id, ItemMod(m), Some(attrs)) } } @@ -5290,11 +5161,10 @@ impl<'a> Parser<'a> { Some(name), id_sp); let mod_inner_lo = p0.span.lo; - let (mod_attrs, next) = p0.parse_inner_attrs_and_next(); - let first_item_outer_attrs = next; - let m0 = p0.parse_mod_items(token::Eof, first_item_outer_attrs, mod_inner_lo); + let mod_attrs = p0.parse_inner_attributes(); + let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo); self.sess.included_mod_stack.borrow_mut().pop(); - return (ast::ItemMod(m0), mod_attrs); + (ast::ItemMod(m0), mod_attrs) } /// Parse a function declaration from a foreign module @@ -5341,20 +5211,6 @@ impl<'a> Parser<'a> { }) } - /// At this point, this is essentially a wrapper for - /// parse_foreign_items. - fn parse_foreign_mod_items(&mut self, - abi: abi::Abi, - first_item_attrs: Vec<Attribute>) - -> ForeignMod { - let foreign_items = self.parse_foreign_items(first_item_attrs); - assert!(self.token == token::CloseDelim(token::Brace)); - ast::ForeignMod { - abi: abi, - items: foreign_items - } - } - /// Parse extern crate links /// /// # Examples @@ -5433,24 +5289,31 @@ impl<'a> Parser<'a> { lo: BytePos, opt_abi: Option<abi::Abi>, visibility: Visibility, - attrs: Vec<Attribute>) + mut attrs: Vec<Attribute>) -> P<Item> { - self.expect(&token::OpenDelim(token::Brace)); let abi = opt_abi.unwrap_or(abi::C); - let (inner, next) = self.parse_inner_attrs_and_next(); - let m = self.parse_foreign_mod_items(abi, next); + attrs.extend(self.parse_inner_attributes().into_iter()); + + let mut foreign_items = vec![]; + while let Some(item) = self.parse_foreign_item() { + foreign_items.push(item); + } self.expect(&token::CloseDelim(token::Brace)); let last_span = self.last_span; + let m = ast::ForeignMod { + abi: abi, + items: foreign_items + }; self.mk_item(lo, last_span.hi, special_idents::invalid, ItemForeignMod(m), visibility, - maybe_append(attrs, Some(inner))) + attrs) } /// Parse type Foo = Bar; @@ -5592,12 +5455,11 @@ impl<'a> Parser<'a> { } } - /// Parse one of the items allowed by the flags; on failure, - /// return `Err(remaining_attrs)`. + /// Parse one of the items allowed by the flags. /// NB: this function no longer parses the items inside an /// extern crate. fn parse_item_(&mut self, attrs: Vec<Attribute>, - macros_allowed: bool) -> MaybeItem { + macros_allowed: bool) -> Option<P<Item>> { let nt_item = match self.token { token::Interpolated(token::NtItem(ref item)) => { Some((**item).clone()) @@ -5610,7 +5472,7 @@ impl<'a> Parser<'a> { let mut attrs = attrs; mem::swap(&mut item.attrs, &mut attrs); item.attrs.extend(attrs.into_iter()); - return Ok(P(item)); + return Some(P(item)); } None => {} } @@ -5631,12 +5493,12 @@ impl<'a> Parser<'a> { item_, visibility, attrs); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Extern) { if self.eat_keyword(keywords::Crate) { - return Ok(self.parse_item_extern_crate(lo, visibility, attrs)); + return Some(self.parse_item_extern_crate(lo, visibility, attrs)); } let opt_abi = self.parse_opt_abi(); @@ -5653,9 +5515,9 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } else if self.check(&token::OpenDelim(token::Brace)) { - return Ok(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)); + return Some(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)); } let span = self.span; @@ -5681,7 +5543,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Const) { // CONST ITEM @@ -5698,7 +5560,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Unsafe) && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) @@ -5715,7 +5577,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Unsafe) && self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) @@ -5731,7 +5593,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Fn) { // FUNCTION ITEM @@ -5745,7 +5607,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Unsafe) && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { @@ -5766,7 +5628,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Mod) { // MODULE ITEM @@ -5779,7 +5641,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Type) { // TYPE ITEM @@ -5791,7 +5653,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Enum) { // ENUM ITEM @@ -5803,7 +5665,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Trait) { // TRAIT ITEM @@ -5816,7 +5678,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Impl) { // IMPL ITEM @@ -5828,7 +5690,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Struct) { // STRUCT ITEM @@ -5840,30 +5702,34 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility) } - /// Parse a foreign item; on failure, return `Err(remaining_attrs)`. - fn parse_foreign_item(&mut self, attrs: Vec<Attribute>) - -> Result<P<ForeignItem>, Vec<Attribute>> { + /// Parse a foreign item. + fn parse_foreign_item(&mut self) -> Option<P<ForeignItem>> { let lo = self.span.lo; + let attrs = self.parse_outer_attributes(); let visibility = self.parse_visibility(); if self.check_keyword(keywords::Static) { // FOREIGN STATIC ITEM - return Ok(self.parse_item_foreign_static(visibility, attrs)); + return Some(self.parse_item_foreign_static(visibility, attrs)); } if self.check_keyword(keywords::Fn) || self.check_keyword(keywords::Unsafe) { // FOREIGN FUNCTION ITEM - return Ok(self.parse_item_foreign_fn(visibility, attrs)); + return Some(self.parse_item_foreign_fn(visibility, attrs)); } // FIXME #5668: this will occur for a macro invocation: - let item = try!(self.parse_macro_use_or_failure(attrs, true, lo, visibility)); - self.span_fatal(item.span, "macros cannot expand to foreign items"); + match self.parse_macro_use_or_failure(attrs, true, lo, visibility) { + Some(item) => { + self.span_fatal(item.span, "macros cannot expand to foreign items"); + } + None => None + } } /// This is the fall-through for parsing items. @@ -5873,7 +5739,7 @@ impl<'a> Parser<'a> { macros_allowed: bool, lo: BytePos, visibility: Visibility - ) -> MaybeItem { + ) -> Option<P<Item>> { if macros_allowed && !self.token.is_any_keyword() && self.look_ahead(1, |t| *t == token::Not) && (self.look_ahead(2, |t| t.is_plain_ident()) @@ -5925,7 +5791,7 @@ impl<'a> Parser<'a> { item_, visibility, attrs); - return Ok(item); + return Some(item); } // FAILURE TO PARSE ITEM @@ -5936,16 +5802,22 @@ impl<'a> Parser<'a> { self.span_fatal(last_span, "unmatched visibility `pub`"); } } - Err(attrs) + + if !attrs.is_empty() { + self.expected_item_err(&attrs); + } + None } + // HACK(eddyb) staging required for `quote_item!`. + #[cfg(stage0)] // SNAP 270a677 pub fn parse_item_with_outer_attributes(&mut self) -> Option<P<Item>> { - let attrs = self.parse_outer_attributes(); - self.parse_item(attrs) + self.parse_item() } - pub fn parse_item(&mut self, attrs: Vec<Attribute>) -> Option<P<Item>> { - self.parse_item_(attrs, true).ok() + pub fn parse_item(&mut self) -> Option<P<Item>> { + let attrs = self.parse_outer_attributes(); + self.parse_item_(attrs, true) } /// Matches view_path : MOD? non_global_path as IDENT @@ -6051,52 +5923,13 @@ impl<'a> Parser<'a> { P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))) } - /// Parses a sequence of foreign items. Stops when it finds program - /// text that can't be parsed as an item - fn parse_foreign_items(&mut self, first_item_attrs: Vec<Attribute>) - -> Vec<P<ForeignItem>> { - let mut attrs = first_item_attrs; - attrs.push_all(&self.parse_outer_attributes()); - let mut foreign_items = Vec::new(); - loop { - match self.parse_foreign_item(attrs) { - Ok(foreign_item) => { - foreign_items.push(foreign_item); - } - Err(returned_attrs) => { - if self.check(&token::CloseDelim(token::Brace)) { - attrs = returned_attrs; - break - } - self.unexpected(); - } - } - attrs = self.parse_outer_attributes(); - } - - if !attrs.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attrs[..])); - } - - foreign_items - } - /// Parses a source module as a crate. This is the main /// entry point for the parser. pub fn parse_crate_mod(&mut self) -> Crate { let lo = self.span.lo; - // parse the crate's inner attrs, maybe (oops) one - // of the attrs of an item: - let (inner, next) = self.parse_inner_attrs_and_next(); - let first_item_outer_attrs = next; - // parse the items inside the crate: - let m = self.parse_mod_items(token::Eof, first_item_outer_attrs, lo); - ast::Crate { - module: m, - attrs: inner, + attrs: self.parse_inner_attributes(), + module: self.parse_mod_items(&token::Eof, lo), config: self.cfg.clone(), span: mk_sp(lo, self.span.lo), exported_macros: Vec::new(), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 5e858d8a79f..2a47a696b1c 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -121,13 +121,11 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { debug!("current path: {}", ast_util::path_name_i(&self.cx.path)); - if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { + let i = if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { match i.node { ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _) => { let diag = self.cx.span_diagnostic; - diag.span_fatal(i.span, - "unsafe functions cannot be used for \ - tests"); + diag.span_fatal(i.span, "unsafe functions cannot be used for tests"); } _ => { debug!("this is a test function"); @@ -142,9 +140,19 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { self.tests.push(i.ident); // debug!("have {} test/bench functions", // cx.testfns.len()); + + // Make all tests public so we can call them from outside + // the module (note that the tests are re-exported and must + // be made public themselves to avoid privacy errors). + i.map(|mut i| { + i.vis = ast::Public; + i + }) } } - } + } else { + i + }; // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 89854f5d979..9b570c2b1fe 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -58,14 +58,14 @@ pub fn string_to_expr (source_str : String) -> P<ast::Expr> { /// Parse a string, return an item pub fn string_to_item (source_str : String) -> Option<P<ast::Item>> { with_error_checking_parse(source_str, |p| { - p.parse_item(Vec::new()) + p.parse_item() }) } /// Parse a string, return a stmt pub fn string_to_stmt(source_str : String) -> P<ast::Stmt> { with_error_checking_parse(source_str, |p| { - p.parse_stmt(Vec::new()) + p.parse_stmt().unwrap() }) } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 36225fad221..89960d5d62f 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -57,7 +57,6 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(int_uint)] -#![feature(io)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ca8a60553ab..02ddeea46bf 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -39,13 +39,11 @@ #![feature(collections)] #![feature(core)] #![feature(int_uint)] -#![feature(old_io)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] -#![feature(io)] #![feature(libc)] -#![feature(set_panic)] +#![feature(set_stdio)] extern crate getopts; extern crate serialize; @@ -123,7 +121,6 @@ impl fmt::Display for TestName { #[derive(Clone, Copy)] enum NamePadding { PadNone, - #[allow(dead_code)] PadOnLeft, PadOnRight, } @@ -909,7 +906,6 @@ pub fn run_test(opts: &TestOpts, return; } - #[allow(deprecated)] // set_stdout fn run_test_inner(desc: TestDesc, monitor_ch: Sender<MonitorMsg>, nocapture: bool, @@ -921,11 +917,6 @@ pub fn run_test(opts: &TestOpts, } fn flush(&mut self) -> io::Result<()> { Ok(()) } } - impl Writer for Sink { - fn write_all(&mut self, data: &[u8]) -> std::old_io::IoResult<()> { - Writer::write_all(&mut *self.0.lock().unwrap(), data) - } - } thread::spawn(move || { let data = Arc::new(Mutex::new(Vec::new())); @@ -937,7 +928,7 @@ pub fn run_test(opts: &TestOpts, let result_guard = cfg.spawn(move || { if !nocapture { - std::old_io::stdio::set_stdout(box Sink(data2.clone())); + io::set_print(box Sink(data2.clone())); io::set_panic(box Sink(data2)); } testfn.invoke(()) diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 42812e1e597..84d86c5746c 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -11,9 +11,6 @@ #![allow(missing_docs)] use std::cmp::Ordering::{self, Less, Greater, Equal}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::collections::hash_map; -use std::hash::Hash; use std::mem; use std::num::{Float, FromPrimitive}; @@ -330,22 +327,6 @@ pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) { } } -/// Returns a HashMap with the number of occurrences of every element in the -/// sequence that the iterator exposes. -#[cfg(not(stage0))] -pub fn freq_count<T, U>(iter: T) -> hash_map::HashMap<U, uint> - where T: Iterator<Item=U>, U: Eq + Clone + Hash -{ - let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new(); - for elem in iter { - match map.entry(elem) { - Occupied(mut entry) => { *entry.get_mut() += 1; }, - Vacant(entry) => { entry.insert(1); }, - } - } - map -} - // Test vectors generated from R, using the script src/etc/stat-test-vectors.r. #[cfg(test)] diff --git a/src/libunicode/char.rs b/src/libunicode/char.rs index bcc2820e381..56bc0389b74 100644 --- a/src/libunicode/char.rs +++ b/src/libunicode/char.rs @@ -41,6 +41,7 @@ pub use normalize::{decompose_canonical, decompose_compatible, compose}; pub use tables::normalization::canonical_combining_class; pub use tables::UNICODE_VERSION; +#[cfg(stage0)] /// Functionality for manipulating `char`. #[stable(feature = "rust1", since = "1.0.0")] pub trait CharExt { @@ -374,6 +375,7 @@ pub trait CharExt { fn width(self, is_cjk: bool) -> Option<usize>; } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl CharExt for char { fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) } @@ -467,3 +469,373 @@ impl Iterator for ToUppercase { type Item = char; fn next(&mut self) -> Option<char> { self.0.take() } } + +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "char"] +impl char { + /// Checks if a `char` parses as a numeric digit in the given radix. + /// + /// Compared to `is_numeric()`, this function only recognizes the characters + /// `0-9`, `a-z` and `A-Z`. + /// + /// # Return value + /// + /// Returns `true` if `c` is a valid digit under `radix`, and `false` + /// otherwise. + /// + /// # Panics + /// + /// Panics if given a radix > 36. + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert!(c.is_digit(10)); + /// + /// assert!('f'.is_digit(16)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) } + + /// Converts a character to the corresponding digit. + /// + /// # Return value + /// + /// If `c` is between '0' and '9', the corresponding value between 0 and + /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns + /// none if the character does not refer to a digit in the given radix. + /// + /// # Panics + /// + /// Panics if given a radix outside the range [0..36]. + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert_eq!(c.to_digit(10), Some(1)); + /// + /// assert_eq!('f'.to_digit(16), Some(15)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_digit(self, radix: u32) -> Option<u32> { C::to_digit(self, radix) } + + /// Returns an iterator that yields the hexadecimal Unicode escape of a + /// character, as `char`s. + /// + /// All characters are escaped with Rust syntax of the form `\\u{NNNN}` + /// where `NNNN` is the shortest hexadecimal representation of the code + /// point. + /// + /// # Examples + /// + /// ``` + /// for i in '❤'.escape_unicode() { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// \ + /// u + /// { + /// 2 + /// 7 + /// 6 + /// 4 + /// } + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let heart: String = '❤'.escape_unicode().collect(); + /// + /// assert_eq!(heart, r"\u{2764}"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn escape_unicode(self) -> EscapeUnicode { C::escape_unicode(self) } + + /// Returns an iterator that yields the 'default' ASCII and + /// C++11-like literal escape of a character, as `char`s. + /// + /// The default is chosen with a bias toward producing literals that are + /// legal in a variety of languages, including C++11 and similar C-family + /// languages. The exact rules are: + /// + /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively. + /// * Single-quote, double-quote and backslash chars are backslash- + /// escaped. + /// * Any other chars in the range [0x20,0x7e] are not escaped. + /// * Any other chars are given hex Unicode escapes; see `escape_unicode`. + /// + /// # Examples + /// + /// ``` + /// for i in '"'.escape_default() { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// \ + /// " + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let quote: String = '"'.escape_default().collect(); + /// + /// assert_eq!(quote, "\\\""); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn escape_default(self) -> EscapeDefault { C::escape_default(self) } + + /// Returns the number of bytes this character would need if encoded in + /// UTF-8. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf8(); + /// + /// assert_eq!(n, 2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len_utf8(self) -> usize { C::len_utf8(self) } + + /// Returns the number of 16-bit code units this character would need if + /// encoded in UTF-16. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf16(); + /// + /// assert_eq!(n, 1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len_utf16(self) -> usize { C::len_utf16(self) } + + /// Encodes this character as UTF-8 into the provided byte buffer, and then + /// returns the number of bytes written. + /// + /// If the buffer is not large enough, nothing will be written into it and a + /// `None` will be returned. A buffer of length four is large enough to + /// encode any `char`. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes two bytes to encode. + /// + /// ``` + /// let mut b = [0; 2]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, Some(2)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// let mut b = [0; 1]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, None); + /// ``` + #[unstable(feature = "unicode", + reason = "pending decision about Iterator/Writer/Reader")] + pub fn encode_utf8(self, dst: &mut [u8]) -> Option<usize> { C::encode_utf8(self, dst) } + + /// Encodes this character as UTF-16 into the provided `u16` buffer, and + /// then returns the number of `u16`s written. + /// + /// If the buffer is not large enough, nothing will be written into it and a + /// `None` will be returned. A buffer of length 2 is large enough to encode + /// any `char`. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes one `u16` to encode. + /// + /// ``` + /// let mut b = [0; 1]; + /// + /// let result = 'ß'.encode_utf16(&mut b); + /// + /// assert_eq!(result, Some(1)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// let mut b = [0; 0]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, None); + /// ``` + #[unstable(feature = "unicode", + reason = "pending decision about Iterator/Writer/Reader")] + pub fn encode_utf16(self, dst: &mut [u16]) -> Option<usize> { C::encode_utf16(self, dst) } + + /// Returns whether the specified character is considered a Unicode + /// alphabetic code point. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_alphabetic(self) -> bool { + match self { + 'a' ... 'z' | 'A' ... 'Z' => true, + c if c > '\x7f' => derived_property::Alphabetic(c), + _ => false + } + } + + /// Returns whether the specified character satisfies the 'XID_Start' + /// Unicode property. + /// + /// 'XID_Start' is a Unicode Derived Property specified in + /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), + /// mostly similar to ID_Start but modified for closure under NFKx. + #[unstable(feature = "unicode", + reason = "mainly needed for compiler internals")] + pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) } + + /// Returns whether the specified `char` satisfies the 'XID_Continue' + /// Unicode property. + /// + /// 'XID_Continue' is a Unicode Derived Property specified in + /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), + /// mostly similar to 'ID_Continue' but modified for closure under NFKx. + #[unstable(feature = "unicode", + reason = "mainly needed for compiler internals")] + pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) } + + /// Indicates whether a character is in lowercase. + /// + /// This is defined according to the terms of the Unicode Derived Core + /// Property `Lowercase`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_lowercase(self) -> bool { + match self { + 'a' ... 'z' => true, + c if c > '\x7f' => derived_property::Lowercase(c), + _ => false + } + } + + /// Indicates whether a character is in uppercase. + /// + /// This is defined according to the terms of the Unicode Derived Core + /// Property `Uppercase`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_uppercase(self) -> bool { + match self { + 'A' ... 'Z' => true, + c if c > '\x7f' => derived_property::Uppercase(c), + _ => false + } + } + + /// Indicates whether a character is whitespace. + /// + /// Whitespace is defined in terms of the Unicode Property `White_Space`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_whitespace(self) -> bool { + match self { + ' ' | '\x09' ... '\x0d' => true, + c if c > '\x7f' => property::White_Space(c), + _ => false + } + } + + /// Indicates whether a character is alphanumeric. + /// + /// Alphanumericness is defined in terms of the Unicode General Categories + /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_alphanumeric(self) -> bool { + self.is_alphabetic() || self.is_numeric() + } + + /// Indicates whether a character is a control code point. + /// + /// Control code points are defined in terms of the Unicode General + /// Category `Cc`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_control(self) -> bool { general_category::Cc(self) } + + /// Indicates whether the character is numeric (Nd, Nl, or No). + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_numeric(self) -> bool { + match self { + '0' ... '9' => true, + c if c > '\x7f' => general_category::N(c), + _ => false + } + } + + /// Converts a character to its lowercase equivalent. + /// + /// The case-folding performed is the common or simple mapping. See + /// `to_uppercase()` for references and more information. + /// + /// # Return value + /// + /// Returns an iterator which yields the characters corresponding to the + /// lowercase equivalent of the character. If no conversion is possible then + /// the input character is returned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_lowercase(self) -> ToLowercase { + ToLowercase(Some(conversions::to_lower(self))) + } + + /// Converts a character to its uppercase equivalent. + /// + /// The case-folding performed is the common or simple mapping: it maps + /// one Unicode codepoint to its uppercase equivalent according to the + /// Unicode database [1]. The additional [`SpecialCasing.txt`] is not yet + /// considered here, but the iterator returned will soon support this form + /// of case folding. + /// + /// A full reference can be found here [2]. + /// + /// # Return value + /// + /// Returns an iterator which yields the characters corresponding to the + /// uppercase equivalent of the character. If no conversion is possible then + /// the input character is returned. + /// + /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt + /// + /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt + /// + /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992 + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_uppercase(self) -> ToUppercase { + ToUppercase(Some(conversions::to_upper(self))) + } + + /// Returns this character's displayed width in columns, or `None` if it is a + /// control character other than `'\x00'`. + /// + /// `is_cjk` determines behavior for characters in the Ambiguous category: + /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1. + /// In CJK contexts, `is_cjk` should be `true`, else it should be `false`. + /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) + /// recommends that these characters be treated as 1 column (i.e., + /// `is_cjk` = `false`) if the context cannot be reliably determined. + #[unstable(feature = "unicode", + reason = "needs expert opinion. is_cjk flag stands out as ugly")] + pub fn width(self, is_cjk: bool) -> Option<usize> { charwidth::width(self, is_cjk) } +} diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs index fadf91f33bc..a09c0cb3bd6 100644 --- a/src/libunicode/lib.rs +++ b/src/libunicode/lib.rs @@ -24,6 +24,7 @@ #![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "unicode"] #![unstable(feature = "unicode")] +#![feature(lang_items)] #![feature(staged_api)] #![staged_api] #![crate_type = "rlib"] diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 6152e057df3..917c2d2dfbe 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -26,6 +26,7 @@ use core::num::Int; use core::slice; use core::str::Split; +#[cfg(stage0)] use char::CharExt as UCharExt; // conflicts with core::prelude::CharExt use tables::grapheme::GraphemeCat; diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index aaf6d8df29c..9a87c03f1c4 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -14,11 +14,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" -#if LLVM_VERSION_MINOR >= 5 #include "llvm/IR/CallSite.h" -#else -#include "llvm/Support/CallSite.h" -#endif //===----------------------------------------------------------------------=== // @@ -33,7 +29,6 @@ using namespace llvm::object; static char *LastError; -#if LLVM_VERSION_MINOR >= 5 extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(Path, @@ -45,18 +40,6 @@ LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { } return wrap(buf_or.get().release()); } -#else -extern "C" LLVMMemoryBufferRef -LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { - OwningPtr<MemoryBuffer> buf; - error_code err = MemoryBuffer::getFile(Path, buf, -1, false); - if (err) { - LLVMRustSetLastError(err.message().c_str()); - return NULL; - } - return wrap(buf.take()); -} -#endif extern "C" char *LLVMRustGetLastError(void) { char *ret = LastError; @@ -116,7 +99,6 @@ extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uin } -#if LLVM_VERSION_MINOR >= 5 extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) { CallSite Call = CallSite(unwrap<Instruction>(Instr)); AttrBuilder B; @@ -126,9 +108,6 @@ extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned AttributeSet::get(Call->getContext(), idx, B))); } -#else -extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef, unsigned, uint64_t) {} -#endif extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64_t Val) { Function *A = unwrap<Function>(Fn); @@ -137,16 +116,12 @@ extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64 A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } -#if LLVM_VERSION_MINOR >= 5 extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) { Function *A = unwrap<Function>(Fn); AttrBuilder B; B.addDereferenceableAttr(bytes); A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } -#else -extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef, unsigned, uint64_t) {} -#endif extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) { Function *F = unwrap<Function>(Fn); @@ -199,10 +174,8 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, AtomicOrdering order, AtomicOrdering failure_order) { return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old), - unwrap(source), order -#if LLVM_VERSION_MINOR >= 5 - , failure_order -#endif + unwrap(source), order, + failure_order )); } extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) { @@ -247,11 +220,7 @@ DIT unwrapDI(LLVMMetadataRef ref) { return DIT(ref ? unwrap<MDNode>(ref) : NULL); } -#if LLVM_VERSION_MINOR >= 5 extern "C" const uint32_t LLVMRustDebugMetadataVersion = DEBUG_METADATA_VERSION; -#else -extern "C" const uint32_t LLVMRustDebugMetadataVersion = 1; -#endif extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *name, @@ -383,10 +352,8 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType( unwrapDI<DIType>(DerivedFrom), unwrapDI<DIArray>(Elements), RunTimeLang, - unwrapDI<DIType>(VTableHolder) -#if LLVM_VERSION_MINOR >= 4 - ,UniqueId -#endif + unwrapDI<DIType>(VTableHolder), + UniqueId )); } @@ -465,8 +432,8 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable( #if LLVM_VERSION_MINOR < 6 if (AddrOpsCount > 0) { SmallVector<llvm::Value *, 16> addr_ops; - llvm::Type *Int64Ty = Type::getInt64Ty(VMContext); - for (int i = 0; i < AddrOpsCount; ++i) + llvm::Type *Int64Ty = Type::getInt64Ty(unwrap<MDNode>(Scope)->getContext()); + for (unsigned i = 0; i < AddrOpsCount; ++i) addr_ops.push_back(ConstantInt::get(Int64Ty, AddrOps[i])); return wrap(Builder->createComplexVariable( @@ -522,7 +489,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray( LLVMMetadataRef* Ptr, unsigned Count) { return wrap(Builder->getOrCreateArray( +#if LLVM_VERSION_MINOR >= 6 ArrayRef<Metadata*>(unwrap(Ptr), Count))); +#else + ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count))); +#endif } extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( @@ -627,19 +598,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType( AlignInBits, Flags, unwrapDI<DIArray>(Elements), - RunTimeLang -#if LLVM_VERSION_MINOR >= 4 - ,UniqueId -#endif + RunTimeLang, + UniqueId )); } -#if LLVM_VERSION_MINOR < 5 -extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) { - unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed); -} -#endif - extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter( DIBuilderRef Builder, LLVMMetadataRef Scope, @@ -730,7 +693,6 @@ extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) { os << ")"; } -#if LLVM_VERSION_MINOR >= 5 extern "C" bool LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { Module *Dst = unwrap(dst); @@ -763,28 +725,7 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { } return true; } -#else -extern "C" bool -LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { - Module *Dst = unwrap(dst); - MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len)); - std::string Err; - Module *Src = llvm::getLazyBitcodeModule(buf, Dst->getContext(), &Err); - if (!Src) { - LLVMRustSetLastError(Err.c_str()); - delete buf; - return false; - } - - if (Linker::LinkModules(Dst, Src, Linker::DestroySource, &Err)) { - LLVMRustSetLastError(Err.c_str()); - return false; - } - return true; -} -#endif -#if LLVM_VERSION_MINOR >= 5 extern "C" void* LLVMRustOpenArchive(char *path) { ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path, @@ -817,23 +758,6 @@ LLVMRustOpenArchive(char *path) { return ret; } -#else -extern "C" void* -LLVMRustOpenArchive(char *path) { - OwningPtr<MemoryBuffer> buf; - error_code err = MemoryBuffer::getFile(path, buf, -1, false); - if (err) { - LLVMRustSetLastError(err.message().c_str()); - return NULL; - } - Archive *ret = new Archive(buf.take(), err); - if (err) { - LLVMRustSetLastError(err.message().c_str()); - return NULL; - } - return ret; -} -#endif extern "C" const char* #if LLVM_VERSION_MINOR >= 6 @@ -844,21 +768,12 @@ LLVMRustArchiveReadSection(OwningBinary<Archive> *ob, char *name, size_t *size) LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) { #endif -#if LLVM_VERSION_MINOR >= 5 Archive::child_iterator child = ar->child_begin(), end = ar->child_end(); for (; child != end; ++child) { ErrorOr<StringRef> name_or_err = child->getName(); if (name_or_err.getError()) continue; StringRef sect_name = name_or_err.get(); -#else - Archive::child_iterator child = ar->begin_children(), - end = ar->end_children(); - for (; child != end; ++child) { - StringRef sect_name; - error_code err = child->getName(sect_name); - if (err) continue; -#endif if (sect_name.trim(" ") == name) { StringRef buf = child->getBuffer(); *size = buf.size(); @@ -877,18 +792,11 @@ LLVMRustDestroyArchive(Archive *ar) { delete ar; } -#if LLVM_VERSION_MINOR >= 5 extern "C" void LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) { GlobalValue *V = unwrap<GlobalValue>(Value); V->setDLLStorageClass(GlobalValue::DLLExportStorageClass); } -#else -extern "C" void -LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) { - LLVMSetLinkage(Value, LLVMDLLExportLinkage); -} -#endif extern "C" int LLVMVersionMinor() { @@ -918,11 +826,7 @@ inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { extern "C" int LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) { StringRef ret; -#if LLVM_VERSION_MINOR >= 5 if (std::error_code ec = (*unwrap(SI))->getName(ret)) -#else - if (error_code ec = (*unwrap(SI))->getName(ret)) -#endif report_fatal_error(ec.message()); *ptr = ret.data(); return ret.size(); diff --git a/src/test/auxiliary/privacy_reexport.rs b/src/test/auxiliary/privacy_reexport.rs index 266903169c7..e60dbb290b0 100644 --- a/src/test/auxiliary/privacy_reexport.rs +++ b/src/test/auxiliary/privacy_reexport.rs @@ -10,6 +10,6 @@ pub use foo as bar; -mod foo { +pub mod foo { pub fn frob() {} } diff --git a/src/test/auxiliary/pub_static_array.rs b/src/test/auxiliary/pub_static_array.rs new file mode 100644 index 00000000000..4419a5ae83c --- /dev/null +++ b/src/test/auxiliary/pub_static_array.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub static ARRAY: &'static [u8] = &[1]; diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs index c48f9972ebc..0d68b960f31 100644 --- a/src/test/compile-fail/associated-types-eq-expr-path.rs +++ b/src/test/compile-fail/associated-types-eq-expr-path.rs @@ -22,5 +22,5 @@ impl Foo for isize { pub fn main() { let x: isize = Foo::<A=usize>::bar(); - //~^ERROR unexpected binding of associated item in expression path + //~^ ERROR unexpected binding of associated item in expression path } diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs index e8998dd7a9d..e2fb0fa4f2f 100644 --- a/src/test/compile-fail/integral-indexing.rs +++ b/src/test/compile-fail/integral-indexing.rs @@ -24,11 +24,11 @@ pub fn main() { s.as_bytes()[3_usize]; s.as_bytes()[3]; s.as_bytes()[3u8]; //~ERROR the trait `core::ops::Index<u8>` is not implemented - //~^ERROR the trait `core::ops::Index<u8>` is not implemented + //~^ ERROR the trait `core::ops::Index<u8>` is not implemented s.as_bytes()[3i8]; //~ERROR the trait `core::ops::Index<i8>` is not implemented - //~^ERROR the trait `core::ops::Index<i8>` is not implemented + //~^ ERROR the trait `core::ops::Index<i8>` is not implemented s.as_bytes()[3u32]; //~ERROR the trait `core::ops::Index<u32>` is not implemented - //~^ERROR the trait `core::ops::Index<u32>` is not implemented + //~^ ERROR the trait `core::ops::Index<u32>` is not implemented s.as_bytes()[3i32]; //~ERROR the trait `core::ops::Index<i32>` is not implemented - //~^ERROR the trait `core::ops::Index<i32>` is not implemented + //~^ ERROR the trait `core::ops::Index<i32>` is not implemented } diff --git a/src/test/compile-fail/issue-13407.rs b/src/test/compile-fail/issue-13407.rs new file mode 100644 index 00000000000..f845eba4060 --- /dev/null +++ b/src/test/compile-fail/issue-13407.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod A { + struct C; +} + +fn main() { + A::C = 1; + //~^ ERROR: illegal left-hand side expression + //~| ERROR: mismatched types +} diff --git a/src/test/compile-fail/issue-16922.rs b/src/test/compile-fail/issue-16922.rs new file mode 100644 index 00000000000..b525d5f64fc --- /dev/null +++ b/src/test/compile-fail/issue-16922.rs @@ -0,0 +1,20 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::any::Any; + +fn foo<T: Any>(value: &T) -> Box<Any> { + Box::new(value) as Box<Any> + //~^ ERROR: cannot infer an appropriate lifetime +} + +fn main() { + let _ = foo(&5); +} diff --git a/src/test/compile-fail/issue-18919.rs b/src/test/compile-fail/issue-18919.rs new file mode 100644 index 00000000000..8c2c52e6fad --- /dev/null +++ b/src/test/compile-fail/issue-18919.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +type FuncType<'f> = Fn(&isize) -> isize + 'f; + +fn ho_func(f: Option<FuncType>) { + //~^ ERROR: the trait `core::marker::Sized` is not implemented for the type +} + +fn main() {} diff --git a/src/test/compile-fail/issue-19982.rs b/src/test/compile-fail/issue-19982.rs new file mode 100644 index 00000000000..9dbca997341 --- /dev/null +++ b/src/test/compile-fail/issue-19982.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +struct Foo; + +impl Fn<(&(),)> for Foo { } //~ ERROR missing lifetime specifier + +fn main() {} diff --git a/src/test/compile-fail/issue-20225.rs b/src/test/compile-fail/issue-20225.rs new file mode 100644 index 00000000000..e4bedbbb7e1 --- /dev/null +++ b/src/test/compile-fail/issue-20225.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +struct Foo; + +impl<'a, T> Fn<(&'a T,)> for Foo { + type Output = (); + + extern "rust-call" fn call(&self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait: expected &-ptr +} + +fn main() {} diff --git a/src/test/compile-fail/issue-20261.rs b/src/test/compile-fail/issue-20261.rs new file mode 100644 index 00000000000..33e00f9a823 --- /dev/null +++ b/src/test/compile-fail/issue-20261.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + for (ref i,) in [].iter() { //~ ERROR: type mismatch resolving + i.clone(); + //~^ ERROR: the type of this value must be known in this context + //~| ERROR: reached the recursion limit while auto-dereferencing + } +} diff --git a/src/test/compile-fail/issue-20714.rs b/src/test/compile-fail/issue-20714.rs new file mode 100644 index 00000000000..cb322f00723 --- /dev/null +++ b/src/test/compile-fail/issue-20714.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct G; + +fn main() { + let g = G(); //~ ERROR: expected function, found `G` +} diff --git a/src/test/compile-fail/issue-7950.rs b/src/test/compile-fail/issue-7950.rs new file mode 100644 index 00000000000..01b90f5680f --- /dev/null +++ b/src/test/compile-fail/issue-7950.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// tests the good error message, not "missing module Foo" or something else unexpected + +struct Foo; + +fn main() { + Foo::bar(); //~ ERROR type `Foo` does not implement any method in scope named `bar` +} diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs index f60c39ba020..13ee3f16361 100644 --- a/src/test/compile-fail/lint-dead-code-3.rs +++ b/src/test/compile-fail/lint-dead-code-3.rs @@ -19,7 +19,7 @@ extern crate libc; pub use extern_foo as x; extern { - fn extern_foo(); + pub fn extern_foo(); } struct Foo; //~ ERROR: struct is never used diff --git a/src/test/compile-fail/lint-non-camel-case-types.rs b/src/test/compile-fail/lint-non-camel-case-types.rs index 9f58d5791cb..f6d3d62d0bf 100644 --- a/src/test/compile-fail/lint-non-camel-case-types.rs +++ b/src/test/compile-fail/lint-non-camel-case-types.rs @@ -11,6 +11,9 @@ #![forbid(non_camel_case_types)] #![allow(dead_code)] +struct ONE_TWO_THREE; +//~^ ERROR type `ONE_TWO_THREE` should have a camel case name such as `OneTwoThree` + struct foo { //~ ERROR type `foo` should have a camel case name such as `Foo` bar: isize, } diff --git a/src/test/compile-fail/manual-link-bad-search-path.rs b/src/test/compile-fail/manual-link-bad-search-path.rs new file mode 100644 index 00000000000..2bf61cbe24c --- /dev/null +++ b/src/test/compile-fail/manual-link-bad-search-path.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-L native= +// error-pattern: empty search path given via `-L` + +fn main() { +} diff --git a/src/test/compile-fail/lint-dead-code-variant.rs b/src/test/compile-fail/match-ref-ice.rs index 6146be65e38..d0f7c7ca986 100644 --- a/src/test/compile-fail/lint-dead-code-variant.rs +++ b/src/test/compile-fail/match-ref-ice.rs @@ -8,35 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(dead_code)] - -#[derive(Copy)] -enum Enum { - Variant1, //~ ERROR: variant is never used - Variant2, - Variant3, -} +// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose +// arity is always 0, an ICE occurs. +// +// Related issue: #23009 -fn copy(e: Enum) -> Enum { - use Enum::*; - match e { - Variant1 => Variant1, - Variant2 => Variant2, - Variant3 => Variant3, - } -} +fn main() { + let homura = [1, 2, 3]; -fn max(e: Enum) -> Enum { - use Enum::*; - match e { - Variant1 => Variant3, - Variant2 => Variant3, - Variant3 => Variant3, + match homura { + [1, ref madoka, 3] => (), + [1, 2, 3] => (), //~ ERROR unreachable pattern + [_, _, _] => (), } } - -fn main() { - let e = Enum::Variant2; - copy(e); - max(e); -} diff --git a/src/test/compile-fail/method-suggestion-no-duplication.rs b/src/test/compile-fail/method-suggestion-no-duplication.rs index e807d2b9448..1d0c4254eda 100644 --- a/src/test/compile-fail/method-suggestion-no-duplication.rs +++ b/src/test/compile-fail/method-suggestion-no-duplication.rs @@ -19,6 +19,4 @@ fn main() { //~^ ERROR does not implement any method //~^^ HELP #1: `core::slice::SliceExt` //~^^^ HELP #2: `core::str::StrExt` - //~^^^^ HELP #3: `collections::slice::SliceExt` - //~^^^^^ HELP #4: `collections::str::StrExt` } diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index 1ae79adbad7..67dccb4c93e 100644 --- a/src/test/compile-fail/privacy1.rs +++ b/src/test/compile-fail/privacy1.rs @@ -27,10 +27,6 @@ mod bar { // can't publicly re-export private items pub use self::baz::{foo, bar}; - //~^ ERROR: function `bar` is private - - pub use self::private::ppriv; - //~^ ERROR: function `ppriv` is private pub struct A; impl A { @@ -61,10 +57,8 @@ mod bar { fn bar2(&self) {} } - // both of these are re-exported by `bar`, but only one should be - // validly re-exported pub fn foo() {} - fn bar() {} + pub fn bar() {} } extern { @@ -92,10 +86,6 @@ mod bar { pub fn gpub() {} fn gpriv() {} } - - mod private { - fn ppriv() {} - } } pub fn gpub() {} @@ -142,13 +132,13 @@ mod foo { ::bar::baz::foo(); //~ ERROR: function `foo` is inaccessible //~^ NOTE: module `baz` is private - ::bar::baz::bar(); //~ ERROR: function `bar` is private + ::bar::baz::bar(); //~ ERROR: function `bar` is inaccessible } fn test2() { use bar::baz::{foo, bar}; //~^ ERROR: function `foo` is inaccessible - //~^^ ERROR: function `bar` is private + //~^^ ERROR: function `bar` is inaccessible foo(); bar(); } diff --git a/src/test/compile-fail/single-primitive-inherent-impl.rs b/src/test/compile-fail/single-primitive-inherent-impl.rs new file mode 100644 index 00000000000..b2cfcfab78b --- /dev/null +++ b/src/test/compile-fail/single-primitive-inherent-impl.rs @@ -0,0 +1,24 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![crate_type = "lib"] +#![feature(lang_items)] +#![feature(no_std)] +#![no_std] + +// OK +#[lang = "char"] +impl char {} + +impl char { +//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive +} diff --git a/src/test/compile-fail/static-array-across-crate.rs b/src/test/compile-fail/static-array-across-crate.rs new file mode 100644 index 00000000000..422cf630429 --- /dev/null +++ b/src/test/compile-fail/static-array-across-crate.rs @@ -0,0 +1,20 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:pub_static_array.rs + +extern crate "pub_static_array" as array; + +use array::ARRAY; + +static X: &'static u8 = &ARRAY[0]; +//~^ ERROR: cannot refer to the interior of another static, use a constant + +pub fn main() {} diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index 448b186f6a5..e126a3040e9 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -15,7 +15,7 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. fn foo(_x: Foo + Send) { - //~^ERROR the trait `core::marker::Sized` is not implemented + //~^ ERROR the trait `core::marker::Sized` is not implemented } fn main() { } diff --git a/src/test/parse-fail/column-offset-1-based.rs b/src/test/parse-fail/column-offset-1-based.rs index 621b480fe77..a00ded61758 100644 --- a/src/test/parse-fail/column-offset-1-based.rs +++ b/src/test/parse-fail/column-offset-1-based.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -# //~ ERROR 11:1: 11:2 error: expected one of `!` or `[`, found `<eof>` +# //~ ERROR 11:1: 11:2 error: expected `[`, found `<eof>` diff --git a/src/test/parse-fail/issue-1655.rs b/src/test/parse-fail/issue-1655.rs index a8704f7545f..6bdcf5c5edc 100644 --- a/src/test/parse-fail/issue-1655.rs +++ b/src/test/parse-fail/issue-1655.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected one of `!` or `[`, found `vec` +// error-pattern:expected `[`, found `vec` mod blade_runner { #vec[doc( brief = "Blade Runner is probably the best movie ever", diff --git a/src/test/run-fail/issue-23354-2.rs b/src/test/run-fail/issue-23354-2.rs new file mode 100644 index 00000000000..b120d3222fa --- /dev/null +++ b/src/test/run-fail/issue-23354-2.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:panic evaluated + +#[allow(unused_variables)] +fn main() { + // This used to trigger an LLVM assertion during compilation + let x = [panic!("panic evaluated"); 2]; +} diff --git a/src/test/run-fail/issue-23354.rs b/src/test/run-fail/issue-23354.rs new file mode 100644 index 00000000000..f6b937c8259 --- /dev/null +++ b/src/test/run-fail/issue-23354.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:panic evaluated + +#[allow(unused_variables)] +fn main() { + let x = [panic!("panic evaluated"); 0]; +} diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index 7f7ed586878..020f5f562d2 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -25,7 +25,7 @@ fn syntax_extension(cx: &ExtCtxt) { let a: P<syntax::ast::Expr> = quote_expr!(cx, 1 + 2); let _b: Option<P<syntax::ast::Item>> = quote_item!(cx, static foo : int = $e_toks; ); let _c: P<syntax::ast::Pat> = quote_pat!(cx, (x, 1 .. 4, *) ); - let _d: P<syntax::ast::Stmt> = quote_stmt!(cx, let x = $a; ); + let _d: Option<P<syntax::ast::Stmt>> = quote_stmt!(cx, let x = $a; ); let _d: syntax::ast::Arm = quote_arm!(cx, (ref x, ref y) = (x, y) ); let _e: P<syntax::ast::Expr> = quote_expr!(cx, match foo { $p_toks => 10 } ); diff --git a/src/test/run-pass/issue-11820.rs b/src/test/run-pass/issue-11820.rs new file mode 100644 index 00000000000..f7aaf495377 --- /dev/null +++ b/src/test/run-pass/issue-11820.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct NoClone; + +fn main() { + let rnc = &NoClone; + let rsnc = &Some(NoClone); + + let _: &NoClone = rnc.clone(); + let _: &Option<NoClone> = rsnc.clone(); +} diff --git a/src/test/run-pass/issue-16597.rs b/src/test/run-pass/issue-16597.rs index 72e948e613b..d074095dbde 100644 --- a/src/test/run-pass/issue-16597.rs +++ b/src/test/run-pass/issue-16597.rs @@ -15,5 +15,5 @@ mod test { use super::*; #[test] - fn test(){} + pub fn test(){} } diff --git a/src/test/run-pass/issue-16922.rs b/src/test/run-pass/issue-16922.rs new file mode 100644 index 00000000000..25909bcbfe9 --- /dev/null +++ b/src/test/run-pass/issue-16922.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::any::Any; + +fn foo(_: &u8) { +} + +fn main() { + let _ = &foo as &Any; +} diff --git a/src/test/run-pass/issue-19982.rs b/src/test/run-pass/issue-19982.rs new file mode 100644 index 00000000000..3082fc27a7d --- /dev/null +++ b/src/test/run-pass/issue-19982.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core,unboxed_closures)] + +#[allow(dead_code)] +struct Foo; + +impl<'a> Fn<(&'a (),)> for Foo { + type Output = (); + + extern "rust-call" fn call(&self, (_,): (&(),)) {} +} + +fn main() {} diff --git a/src/test/run-pass/issue-20396.rs b/src/test/run-pass/issue-20396.rs new file mode 100644 index 00000000000..63a88988162 --- /dev/null +++ b/src/test/run-pass/issue-20396.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +trait Foo<T> { + fn noop(&self, _: T); +} + +enum Bar<T> { Bla(T) } + +struct Baz<'a> { + inner: for<'b> Foo<Bar<&'b ()>> + 'a, +} + +fn main() {} diff --git a/src/test/run-pass/issue-20823.rs b/src/test/run-pass/issue-20823.rs index 561b6195476..c297998b649 100644 --- a/src/test/run-pass/issue-20823.rs +++ b/src/test/run-pass/issue-20823.rs @@ -14,4 +14,4 @@ #![deny(unstable)] #[test] -fn foo() {} +pub fn foo() {} diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs index 1ecdd39ca7a..f668cae66c6 100644 --- a/src/test/run-pass/issue-22577.rs +++ b/src/test/run-pass/issue-22577.rs @@ -25,5 +25,8 @@ fn main() { assert_both::<net::TcpListener>(); assert_both::<net::UdpSocket>(); assert_both::<net::SocketAddr>(); - assert_both::<net::IpAddr>(); + assert_both::<net::SocketAddrV4>(); + assert_both::<net::SocketAddrV6>(); + assert_both::<net::Ipv4Addr>(); + assert_both::<net::Ipv6Addr>(); } diff --git a/src/test/run-pass/issue-5950.rs b/src/test/run-pass/issue-5950.rs index c9413258e0f..88bbba44bbe 100644 --- a/src/test/run-pass/issue-5950.rs +++ b/src/test/run-pass/issue-5950.rs @@ -11,6 +11,6 @@ pub use local as local_alias; -mod local { } +pub mod local { } pub fn main() {} diff --git a/src/test/run-pass/issue-9951.rs b/src/test/run-pass/issue-9951.rs new file mode 100644 index 00000000000..210f647e5be --- /dev/null +++ b/src/test/run-pass/issue-9951.rs @@ -0,0 +1,28 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused_variables)] + +trait Bar { + fn noop(&self); +} +impl Bar for u8 { + fn noop(&self) {} +} + +fn main() { + let (a, b) = (&5u8 as &Bar, &9u8 as &Bar); + let (c, d): (&Bar, &Bar) = (a, b); + + let (a, b) = (Box::new(5u8) as Box<Bar>, Box::new(9u8) as Box<Bar>); + let (c, d): (&Bar, &Bar) = (&*a, &*b); + + let (c, d): (&Bar, &Bar) = (&5, &9); +} diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index 3ffac98418a..f1d41a0f422 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -12,7 +12,6 @@ // type is `&mut [u8]`, passes in a pointer to the lvalue and not a // temporary. Issue #19147. -use std::raw; use std::mem; use std::slice; use std::old_io::IoResult; @@ -27,10 +26,10 @@ impl<'a> MyWriter for &'a mut [u8] { let write_len = buf.len(); unsafe { - *self = mem::transmute(raw::Slice { - data: self.as_ptr().offset(write_len as int), - len: self.len() - write_len, - }); + *self = slice::from_raw_parts_mut( + self.as_mut_ptr().offset(write_len as isize), + self.len() - write_len + ); } Ok(()) diff --git a/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs index 7c99c968e35..f7985efbc31 100644 --- a/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs +++ b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs @@ -13,8 +13,8 @@ extern crate test; #[bench] -fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {} +pub fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {} #[test] -fn test_explicit_return_type() -> () {} +pub fn test_explicit_return_type() -> () {} diff --git a/src/test/run-pass/test-should-fail-good-message.rs b/src/test/run-pass/test-should-fail-good-message.rs index b8e05b4d35a..94d20f703a0 100644 --- a/src/test/run-pass/test-should-fail-good-message.rs +++ b/src/test/run-pass/test-should-fail-good-message.rs @@ -13,13 +13,13 @@ #[test] #[should_panic(expected = "foo")] -fn test_foo() { +pub fn test_foo() { panic!("foo bar") } #[test] #[should_panic(expected = "foo")] -fn test_foo_dynamic() { +pub fn test_foo_dynamic() { panic!("{} bar", "foo") } diff --git a/src/test/run-pass/unsized3.rs b/src/test/run-pass/unsized3.rs index 5bd76d093d4..f9185cd2642 100644 --- a/src/test/run-pass/unsized3.rs +++ b/src/test/run-pass/unsized3.rs @@ -15,31 +15,32 @@ use std::mem; use std::raw; +use std::slice; struct Foo<T> { f: [T], } struct Bar { - f1: uint, - f2: [uint], + f1: usize, + f2: [usize], } struct Baz { - f1: uint, + f1: usize, f2: str, } trait Tr { - fn foo(&self) -> uint; + fn foo(&self) -> usize; } struct St { - f: uint + f: usize } impl Tr for St { - fn foo(&self) -> uint { + fn foo(&self) -> usize { self.f } } @@ -67,18 +68,18 @@ pub fn main() { } let data: Box<Foo_<i32>> = box Foo_{f: [1, 2, 3] }; - let x: &Foo<i32> = mem::transmute(raw::Slice { len: 3, data: &*data }); + let x: &Foo<i32> = mem::transmute(slice::from_raw_parts(&*data, 3)); assert!(x.f.len() == 3); assert!(x.f[0] == 1); struct Baz_ { - f1: uint, + f1: usize, f2: [u8; 5], } let data: Box<_> = box Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; - let x: &Baz = mem::transmute( raw::Slice { len: 5, data: &*data } ); + let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5)); assert!(x.f1 == 42); let chs: Vec<char> = x.f2.chars().collect(); assert!(chs.len() == 5); |
