DEPS_rlibc :=
DEPS_alloc := core libc native:jemalloc
DEPS_debug := std
-DEPS_std := core rand libc alloc native:rustrt native:backtrace
+DEPS_std := core rand libc alloc collections native:rustrt native:backtrace
DEPS_graphviz := std
DEPS_green := std native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
-DEPS_syntax := std term serialize collections log fmt_macros debug
+DEPS_syntax := std term serialize log fmt_macros debug
DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
- collections time log graphviz debug
-DEPS_rustdoc := rustc native:hoedown serialize sync getopts collections \
+ time log graphviz debug
+DEPS_rustdoc := rustc native:hoedown serialize sync getopts \
test time debug
DEPS_flate := std native:miniz
-DEPS_arena := std collections
+DEPS_arena := std
DEPS_graphviz := std
DEPS_glob := std
-DEPS_serialize := std collections log
-DEPS_term := std collections log
+DEPS_serialize := std log
+DEPS_term := std log
DEPS_semver := std
DEPS_uuid := std serialize
DEPS_sync := std alloc
DEPS_getopts := std
-DEPS_collections := std debug
+DEPS_collections := core alloc
DEPS_fourcc := syntax std
DEPS_hexfloat := syntax std
DEPS_num := std
-DEPS_test := std collections getopts serialize term time regex
+DEPS_test := std getopts serialize term time regex
DEPS_time := std serialize sync
DEPS_rand := core
-DEPS_url := std collections
+DEPS_url := std
DEPS_log := std sync
-DEPS_regex := std collections
+DEPS_regex := std
DEPS_regex_macros = syntax std regex
DEPS_fmt_macros = std
ONLY_RLIB_rlibc := 1
ONLY_RLIB_alloc := 1
ONLY_RLIB_rand := 1
+ONLY_RLIB_collections := 1
################################################################################
# You should not need to edit below this line
#![allow(missing_doc)]
+use core::prelude::*;
-use std::cmp;
-use std::fmt;
-use std::iter::RandomAccessIterator;
-use std::iter::{Enumerate, Repeat, Map, Zip};
-use std::ops;
-use std::slice;
-use std::uint;
+use core::cmp;
+use core::fmt;
+use core::iter::{Enumerate, Repeat, Map, Zip};
+use core::ops;
+use core::slice;
+use core::uint;
+
+use string::String;
+use vec::Vec;
#[deriving(Clone)]
struct SmallBitv {
///a length (the height of the tree), and lower and upper bounds on the
///number of elements that a given node can contain.
-use std::fmt;
-use std::fmt::Show;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::fmt;
+use core::fmt::Show;
+
+use vec::Vec;
#[allow(missing_doc)]
pub struct BTree<K, V> {
//! Container traits for collections
-use std::container::Mutable;
+use core::prelude::*;
/// A double-ended sequence that allows querying, insertion and deletion at both ends.
pub trait Deque<T> : Mutable {
// Backlinks over DList::prev are raw pointers that form a full chain in
// the reverse direction.
-use std::iter;
-use std::mem;
-use std::ptr;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::iter;
+use core::mem;
+use core::ptr;
use deque::Deque;
//! This module defines a container which uses an efficient bit mask
//! representation to hold C-like enum variants.
-use std::num::Bitwise;
+use core::prelude::*;
+
+use core::num::Bitwise;
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
/// A specialized Set implementation to use enum types.
--- /dev/null
+// 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.
+
+/*!
+ * Generic hashing support.
+ *
+ * This module provides a generic way to compute the hash of a value. The
+ * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
+ *
+ * # Example
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ *
+ * #[deriving(Hash)]
+ * struct Person {
+ * id: uint,
+ * name: String,
+ * phone: u64,
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) != hash::hash(&person2));
+ * ```
+ *
+ * If you need more control over how a value is hashed, you need to implement
+ * the trait `Hash`:
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ * use std::hash::sip::SipState;
+ *
+ * struct Person {
+ * id: uint,
+ * name: String,
+ * phone: u64,
+ * }
+ *
+ * impl Hash for Person {
+ * fn hash(&self, state: &mut SipState) {
+ * self.id.hash(state);
+ * self.phone.hash(state);
+ * }
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) == hash::hash(&person2));
+ * ```
+ */
+
+#![allow(unused_must_use)]
+
+use core::prelude::*;
+
+use alloc::owned::Box;
+use alloc::rc::Rc;
+use core::intrinsics::TypeId;
+
+use vec::Vec;
+
+/// Reexport the `sip::hash` function as our default hasher.
+pub use hash = self::sip::hash;
+
+pub mod sip;
+
+/// A trait that represents a hashable type. The `S` type parameter is an
+/// abstract hash state that is used by the `Hash` to compute the hash.
+/// It defaults to `std::hash::sip::SipState`.
+pub trait Hash<S = sip::SipState> {
+ /// Compute a hash of the value.
+ fn hash(&self, state: &mut S);
+}
+
+/// A trait that computes a hash for a value. The main users of this trait are
+/// containers like `HashMap`, which need a generic way hash multiple types.
+pub trait Hasher<S> {
+ /// Compute a hash of the value.
+ fn hash<T: Hash<S>>(&self, value: &T) -> u64;
+}
+
+pub trait Writer {
+ fn write(&mut self, bytes: &[u8]);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+macro_rules! impl_hash(
+ ( $($ty:ident)* ) => (
+ $(
+ impl<S: Writer> Hash<S> for $ty {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ let a: [u8, ..::core::$ty::BYTES] = unsafe {
+ ::core::mem::transmute(*self)
+ };
+ state.write(a.as_slice())
+ }
+ }
+ )*
+ )
+)
+
+impl_hash!( u8 u16 u32 u64 uint i8 i16 i32 i64 int )
+
+impl<S: Writer> Hash<S> for bool {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ (*self as u8).hash(state);
+ }
+}
+
+impl<S: Writer> Hash<S> for char {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ (*self as u32).hash(state);
+ }
+}
+
+impl<'a, S: Writer> Hash<S> for &'a str {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ state.write(self.as_bytes());
+ 0xffu8.hash(state)
+ }
+}
+
+macro_rules! impl_hash_tuple(
+ () => (
+ impl<S: Writer> Hash<S> for () {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ state.write([]);
+ }
+ }
+ );
+
+ ($A:ident $($B:ident)*) => (
+ impl<
+ S: Writer,
+ $A: Hash<S> $(, $B: Hash<S>)*
+ > Hash<S> for ($A, $($B),*) {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ match *self {
+ (ref $A, $(ref $B),*) => {
+ $A.hash(state);
+ $(
+ $B.hash(state);
+ )*
+ }
+ }
+ }
+ }
+
+ impl_hash_tuple!($($B)*)
+ );
+)
+
+impl_hash_tuple!(a0 a1 a2 a3 a4 a5 a6 a7)
+
+impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ self.len().hash(state);
+ for elt in self.iter() {
+ elt.hash(state);
+ }
+ }
+}
+
+
+impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ self.as_slice().hash(state);
+ }
+}
+
+impl<S: Writer, T: Hash<S>> Hash<S> for ~[T] {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ self.as_slice().hash(state);
+ }
+}
+
+impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ self.as_slice().hash(state);
+ }
+}
+
+impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ (**self).hash(state);
+ }
+}
+
+impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ (**self).hash(state);
+ }
+}
+
+impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ (**self).hash(state);
+ }
+}
+
+impl<S: Writer, T: Hash<S>> Hash<S> for @T {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ (**self).hash(state);
+ }
+}
+
+impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ (**self).hash(state);
+ }
+}
+
+impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ match *self {
+ Some(ref x) => {
+ 0u8.hash(state);
+ x.hash(state);
+ }
+ None => {
+ 1u8.hash(state);
+ }
+ }
+ }
+}
+
+impl<S: Writer, T> Hash<S> for *T {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ // NB: raw-pointer Hash does _not_ dereference
+ // to the target; it just gives you the pointer-bytes.
+ (*self as uint).hash(state);
+ }
+}
+
+impl<S: Writer, T> Hash<S> for *mut T {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ // NB: raw-pointer Hash does _not_ dereference
+ // to the target; it just gives you the pointer-bytes.
+ (*self as uint).hash(state);
+ }
+}
+
+impl<S: Writer> Hash<S> for TypeId {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ self.hash().hash(state)
+ }
+}
+
+impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ match *self {
+ Ok(ref t) => { 1u.hash(state); t.hash(state); }
+ Err(ref t) => { 2u.hash(state); t.hash(state); }
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+#[cfg(test)]
+mod tests {
+ use mem;
+ use io::{IoResult, Writer};
+ use iter::{Iterator};
+ use option::{Some, None};
+ use result::Ok;
+ use slice::ImmutableVector;
+
+ use super::{Hash, Hasher};
+
+ struct MyWriterHasher;
+
+ impl Hasher<MyWriter> for MyWriterHasher {
+ fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
+ let mut state = MyWriter { hash: 0 };
+ value.hash(&mut state);
+ state.hash
+ }
+ }
+
+ struct MyWriter {
+ hash: u64,
+ }
+
+ impl Writer for MyWriter {
+ // Most things we'll just add up the bytes.
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ for byte in buf.iter() {
+ self.hash += *byte as u64;
+ }
+ Ok(())
+ }
+ }
+
+ #[test]
+ fn test_writer_hasher() {
+ let hasher = MyWriterHasher;
+
+ assert_eq!(hasher.hash(&()), 0);
+
+ assert_eq!(hasher.hash(&5u8), 5);
+ assert_eq!(hasher.hash(&5u16), 5);
+ assert_eq!(hasher.hash(&5u32), 5);
+ assert_eq!(hasher.hash(&5u64), 5);
+ assert_eq!(hasher.hash(&5u), 5);
+
+ assert_eq!(hasher.hash(&5i8), 5);
+ assert_eq!(hasher.hash(&5i16), 5);
+ assert_eq!(hasher.hash(&5i32), 5);
+ assert_eq!(hasher.hash(&5i64), 5);
+ assert_eq!(hasher.hash(&5i), 5);
+
+ assert_eq!(hasher.hash(&false), 0);
+ assert_eq!(hasher.hash(&true), 1);
+
+ assert_eq!(hasher.hash(&'a'), 97);
+
+ assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
+ assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);
+
+ unsafe {
+ let ptr: *int = mem::transmute(5);
+ assert_eq!(hasher.hash(&ptr), 5);
+ }
+
+ unsafe {
+ let ptr: *mut int = mem::transmute(5);
+ assert_eq!(hasher.hash(&ptr), 5);
+ }
+ }
+
+ struct Custom {
+ hash: u64
+ }
+
+ impl Hash<u64> for Custom {
+ fn hash(&self, state: &mut u64) {
+ *state = self.hash;
+ }
+ }
+
+ #[test]
+ fn test_custom_state() {
+ let custom = Custom { hash: 5 };
+ let mut state = 0;
+ custom.hash(&mut state);
+ assert_eq!(state, 5);
+ }
+}
--- /dev/null
+// 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.
+
+/*!
+ * Implementation of SipHash 2-4
+ *
+ * See: http://131002.net/siphash/
+ *
+ * Consider this as a main "general-purpose" hash for all hashtables: it
+ * runs at good speed (competitive with spooky and city) and permits
+ * strong _keyed_ hashing. Key your hashtables from a strong RNG,
+ * such as `rand::Rng`.
+ *
+ * Although the SipHash algorithm is considered to be cryptographically
+ * strong, this implementation has not been reviewed for such purposes.
+ * As such, all cryptographic uses of this implementation are strongly
+ * discouraged.
+ */
+
+use core::prelude::*;
+
+use core::default::Default;
+
+use super::{Hash, Hasher, Writer};
+
+/// `SipState` computes a SipHash 2-4 hash over a stream of bytes.
+pub struct SipState {
+ k0: u64,
+ k1: u64,
+ length: uint, // how many bytes we've processed
+ v0: u64, // hash state
+ v1: u64,
+ v2: u64,
+ v3: u64,
+ tail: u64, // unprocessed bytes le
+ ntail: uint, // how many bytes in tail are valid
+}
+
+// sadly, these macro definitions can't appear later,
+// because they're needed in the following defs;
+// this design could be improved.
+
+macro_rules! u8to64_le (
+ ($buf:expr, $i:expr) =>
+ ($buf[0+$i] as u64 |
+ $buf[1+$i] as u64 << 8 |
+ $buf[2+$i] as u64 << 16 |
+ $buf[3+$i] as u64 << 24 |
+ $buf[4+$i] as u64 << 32 |
+ $buf[5+$i] as u64 << 40 |
+ $buf[6+$i] as u64 << 48 |
+ $buf[7+$i] as u64 << 56);
+ ($buf:expr, $i:expr, $len:expr) =>
+ ({
+ let mut t = 0;
+ let mut out = 0u64;
+ while t < $len {
+ out |= $buf[t+$i] as u64 << t*8;
+ t += 1;
+ }
+ out
+ });
+)
+
+macro_rules! rotl (
+ ($x:expr, $b:expr) =>
+ (($x << $b) | ($x >> (64 - $b)))
+)
+
+macro_rules! compress (
+ ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
+ ({
+ $v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
+ $v0 = rotl!($v0, 32);
+ $v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
+ $v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
+ $v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
+ $v2 = rotl!($v2, 32);
+ })
+)
+
+impl SipState {
+ /// Create a `SipState` that is keyed off the provided keys.
+ #[inline]
+ pub fn new() -> SipState {
+ SipState::new_with_keys(0, 0)
+ }
+
+ /// Create a `SipState` that is keyed off the provided keys.
+ #[inline]
+ pub fn new_with_keys(key0: u64, key1: u64) -> SipState {
+ let mut state = SipState {
+ k0: key0,
+ k1: key1,
+ length: 0,
+ v0: 0,
+ v1: 0,
+ v2: 0,
+ v3: 0,
+ tail: 0,
+ ntail: 0,
+ };
+ state.reset();
+ state
+ }
+
+ /// Reset the state back to it's initial state.
+ #[inline]
+ pub fn reset(&mut self) {
+ self.length = 0;
+ self.v0 = self.k0 ^ 0x736f6d6570736575;
+ self.v1 = self.k1 ^ 0x646f72616e646f6d;
+ self.v2 = self.k0 ^ 0x6c7967656e657261;
+ self.v3 = self.k1 ^ 0x7465646279746573;
+ self.ntail = 0;
+ }
+
+ /// Return the computed hash.
+ #[inline]
+ pub fn result(&self) -> u64 {
+ let mut v0 = self.v0;
+ let mut v1 = self.v1;
+ let mut v2 = self.v2;
+ let mut v3 = self.v3;
+
+ let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
+
+ v3 ^= b;
+ compress!(v0, v1, v2, v3);
+ compress!(v0, v1, v2, v3);
+ v0 ^= b;
+
+ v2 ^= 0xff;
+ compress!(v0, v1, v2, v3);
+ compress!(v0, v1, v2, v3);
+ compress!(v0, v1, v2, v3);
+ compress!(v0, v1, v2, v3);
+
+ v0 ^ v1 ^ v2 ^ v3
+ }
+}
+
+impl Writer for SipState {
+ #[inline]
+ fn write(&mut self, msg: &[u8]) {
+ let length = msg.len();
+ self.length += length;
+
+ let mut needed = 0u;
+
+ if self.ntail != 0 {
+ needed = 8 - self.ntail;
+ if length < needed {
+ self.tail |= u8to64_le!(msg, 0, length) << 8*self.ntail;
+ self.ntail += length;
+ return
+ }
+
+ let m = self.tail | u8to64_le!(msg, 0, needed) << 8*self.ntail;
+
+ self.v3 ^= m;
+ compress!(self.v0, self.v1, self.v2, self.v3);
+ compress!(self.v0, self.v1, self.v2, self.v3);
+ self.v0 ^= m;
+
+ self.ntail = 0;
+ }
+
+ // Buffered tail is now flushed, process new input.
+ let len = length - needed;
+ let end = len & (!0x7);
+ let left = len & 0x7;
+
+ let mut i = needed;
+ while i < end {
+ let mi = u8to64_le!(msg, i);
+
+ self.v3 ^= mi;
+ compress!(self.v0, self.v1, self.v2, self.v3);
+ compress!(self.v0, self.v1, self.v2, self.v3);
+ self.v0 ^= mi;
+
+ i += 8;
+ }
+
+ self.tail = u8to64_le!(msg, i, left);
+ self.ntail = left;
+ }
+}
+
+impl Clone for SipState {
+ #[inline]
+ fn clone(&self) -> SipState {
+ *self
+ }
+}
+
+impl Default for SipState {
+ #[inline]
+ fn default() -> SipState {
+ SipState::new()
+ }
+}
+
+/// `SipHasher` computes the SipHash algorithm from a stream of bytes.
+#[deriving(Clone)]
+pub struct SipHasher {
+ k0: u64,
+ k1: u64,
+}
+
+impl SipHasher {
+ /// Create a `Sip`.
+ #[inline]
+ pub fn new() -> SipHasher {
+ SipHasher::new_with_keys(0, 0)
+ }
+
+ /// Create a `Sip` that is keyed off the provided keys.
+ #[inline]
+ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
+ SipHasher {
+ k0: key0,
+ k1: key1,
+ }
+ }
+}
+
+impl Hasher<SipState> for SipHasher {
+ #[inline]
+ fn hash<T: Hash<SipState>>(&self, value: &T) -> u64 {
+ let mut state = SipState::new_with_keys(self.k0, self.k1);
+ value.hash(&mut state);
+ state.result()
+ }
+}
+
+impl Default for SipHasher {
+ #[inline]
+ fn default() -> SipHasher {
+ SipHasher::new()
+ }
+}
+
+/// Hash a value using the SipHash algorithm.
+#[inline]
+pub fn hash<T: Hash<SipState>>(value: &T) -> u64 {
+ let mut state = SipState::new();
+ value.hash(&mut state);
+ state.result()
+}
+
+/// Hash a value with the SipHash algorithm with the provided keys.
+#[inline]
+pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
+ let mut state = SipState::new_with_keys(k0, k1);
+ value.hash(&mut state);
+ state.result()
+}
+
+
+
+#[cfg(test)]
+mod tests {
+ extern crate test;
+ use prelude::*;
+ use num::ToStrRadix;
+ use option::{Some, None};
+ use str::Str;
+ use string::String;
+ use slice::{Vector, ImmutableVector};
+ use self::test::Bencher;
+
+ use super::super::Hash;
+ use super::{SipState, hash, hash_with_keys};
+
+ // Hash just the bytes of the slice, without length prefix
+ struct Bytes<'a>(&'a [u8]);
+
+ impl<'a, S: Writer> Hash<S> for Bytes<'a> {
+ #[allow(unused_must_use)]
+ fn hash(&self, state: &mut S) {
+ let Bytes(v) = *self;
+ state.write(v);
+ }
+ }
+
+ #[test]
+ #[allow(unused_must_use)]
+ fn test_siphash() {
+ let vecs : [[u8, ..8], ..64] = [
+ [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
+ [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
+ [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
+ [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
+ [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
+ [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
+ [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
+ [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
+ [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
+ [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
+ [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
+ [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
+ [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
+ [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
+ [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
+ [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
+ [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
+ [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
+ [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
+ [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
+ [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
+ [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
+ [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
+ [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
+ [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
+ [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
+ [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
+ [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
+ [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
+ [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
+ [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
+ [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
+ [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
+ [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
+ [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
+ [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
+ [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
+ [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
+ [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
+ [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
+ [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
+ [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
+ [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
+ [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
+ [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
+ [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
+ [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
+ [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
+ [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
+ [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
+ [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
+ [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
+ [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
+ [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
+ [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
+ [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
+ [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
+ [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
+ [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
+ [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
+ [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
+ [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
+ [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
+ [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
+ ];
+
+ let k0 = 0x_07_06_05_04_03_02_01_00_u64;
+ let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64;
+ let mut buf = Vec::new();
+ let mut t = 0;
+ let mut state_inc = SipState::new_with_keys(k0, k1);
+ let mut state_full = SipState::new_with_keys(k0, k1);
+
+ fn to_hex_str(r: &[u8, ..8]) -> String {
+ let mut s = String::new();
+ for b in r.iter() {
+ s.push_str((*b as uint).to_str_radix(16u).as_slice());
+ }
+ s
+ }
+
+ fn result_bytes(h: u64) -> ~[u8] {
+ box [(h >> 0) as u8,
+ (h >> 8) as u8,
+ (h >> 16) as u8,
+ (h >> 24) as u8,
+ (h >> 32) as u8,
+ (h >> 40) as u8,
+ (h >> 48) as u8,
+ (h >> 56) as u8,
+ ]
+ }
+
+ fn result_str(h: u64) -> String {
+ let r = result_bytes(h);
+ let mut s = String::new();
+ for b in r.iter() {
+ s.push_str((*b as uint).to_str_radix(16u).as_slice());
+ }
+ s
+ }
+
+ while t < 64 {
+ debug!("siphash test {}", t);
+ let vec = u8to64_le!(vecs[t], 0);
+ let out = hash_with_keys(k0, k1, &Bytes(buf.as_slice()));
+ debug!("got {:?}, expected {:?}", out, vec);
+ assert_eq!(vec, out);
+
+ state_full.reset();
+ state_full.write(buf.as_slice());
+ let f = result_str(state_full.result());
+ let i = result_str(state_inc.result());
+ let v = to_hex_str(&vecs[t]);
+ debug!("{}: ({}) => inc={} full={}", t, v, i, f);
+
+ assert!(f == i && f == v);
+
+ buf.push(t as u8);
+ state_inc.write_u8(t as u8);
+
+ t += 1;
+ }
+ }
+
+ #[test] #[cfg(target_arch = "arm")]
+ fn test_hash_uint() {
+ let val = 0xdeadbeef_deadbeef_u64;
+ assert!(hash(&(val as u64)) != hash(&(val as uint)));
+ assert_eq!(hash(&(val as u32)), hash(&(val as uint)));
+ }
+ #[test] #[cfg(target_arch = "x86_64")]
+ fn test_hash_uint() {
+ let val = 0xdeadbeef_deadbeef_u64;
+ assert_eq!(hash(&(val as u64)), hash(&(val as uint)));
+ assert!(hash(&(val as u32)) != hash(&(val as uint)));
+ }
+ #[test] #[cfg(target_arch = "x86")]
+ fn test_hash_uint() {
+ let val = 0xdeadbeef_deadbeef_u64;
+ assert!(hash(&(val as u64)) != hash(&(val as uint)));
+ assert_eq!(hash(&(val as u32)), hash(&(val as uint)));
+ }
+
+ #[test]
+ fn test_hash_idempotent() {
+ let val64 = 0xdeadbeef_deadbeef_u64;
+ assert_eq!(hash(&val64), hash(&val64));
+ let val32 = 0xdeadbeef_u32;
+ assert_eq!(hash(&val32), hash(&val32));
+ }
+
+ #[test]
+ fn test_hash_no_bytes_dropped_64() {
+ let val = 0xdeadbeef_deadbeef_u64;
+
+ assert!(hash(&val) != hash(&zero_byte(val, 0)));
+ assert!(hash(&val) != hash(&zero_byte(val, 1)));
+ assert!(hash(&val) != hash(&zero_byte(val, 2)));
+ assert!(hash(&val) != hash(&zero_byte(val, 3)));
+ assert!(hash(&val) != hash(&zero_byte(val, 4)));
+ assert!(hash(&val) != hash(&zero_byte(val, 5)));
+ assert!(hash(&val) != hash(&zero_byte(val, 6)));
+ assert!(hash(&val) != hash(&zero_byte(val, 7)));
+
+ fn zero_byte(val: u64, byte: uint) -> u64 {
+ assert!(byte < 8);
+ val & !(0xff << (byte * 8))
+ }
+ }
+
+ #[test]
+ fn test_hash_no_bytes_dropped_32() {
+ let val = 0xdeadbeef_u32;
+
+ assert!(hash(&val) != hash(&zero_byte(val, 0)));
+ assert!(hash(&val) != hash(&zero_byte(val, 1)));
+ assert!(hash(&val) != hash(&zero_byte(val, 2)));
+ assert!(hash(&val) != hash(&zero_byte(val, 3)));
+
+ fn zero_byte(val: u32, byte: uint) -> u32 {
+ assert!(byte < 4);
+ val & !(0xff << (byte * 8))
+ }
+ }
+
+ #[test]
+ fn test_hash_no_concat_alias() {
+ let s = ("aa", "bb");
+ let t = ("aabb", "");
+ let u = ("a", "abb");
+
+ assert!(s != t && t != u);
+ assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
+
+ let v = (&[1u8], &[0u8, 0], &[0u8]);
+ let w = (&[1u8, 0, 0, 0], &[], &[]);
+
+ assert!(v != w);
+ assert!(hash(&v) != hash(&w));
+ }
+
+ #[bench]
+ fn bench_str_under_8_bytes(b: &mut Bencher) {
+ let s = "foo";
+ b.iter(|| {
+ assert_eq!(hash(&s), 16262950014981195938);
+ })
+ }
+
+ #[bench]
+ fn bench_str_of_8_bytes(b: &mut Bencher) {
+ let s = "foobar78";
+ b.iter(|| {
+ assert_eq!(hash(&s), 4898293253460910787);
+ })
+ }
+
+ #[bench]
+ fn bench_str_over_8_bytes(b: &mut Bencher) {
+ let s = "foobarbaz0";
+ b.iter(|| {
+ assert_eq!(hash(&s), 10581415515220175264);
+ })
+ }
+
+ #[bench]
+ fn bench_long_str(b: &mut Bencher) {
+ let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
+incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
+exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
+irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
+pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
+officia deserunt mollit anim id est laborum.";
+ b.iter(|| {
+ assert_eq!(hash(&s), 17717065544121360093);
+ })
+ }
+
+ #[bench]
+ fn bench_u64(b: &mut Bencher) {
+ let u = 16262950014981195938u64;
+ b.iter(|| {
+ assert_eq!(hash(&u), 5254097107239593357);
+ })
+ }
+
+ #[deriving(Hash)]
+ struct Compound {
+ x: u8,
+ y: u64,
+ }
+
+ #[bench]
+ fn bench_compound_1(b: &mut Bencher) {
+ let compound = Compound {
+ x: 1,
+ y: 2,
+ };
+ b.iter(|| {
+ assert_eq!(hash(&compound), 12506681940457338191);
+ })
+ }
+}
+++ /dev/null
-// 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.
-
-//! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types)
-
-use std::container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
-use std::clone::Clone;
-use std::cmp::{PartialEq, Eq, Equiv, max};
-use std::default::Default;
-use std::fmt;
-use std::fmt::Show;
-use std::hash::{Hash, Hasher, sip};
-use std::iter;
-use std::iter::{Iterator, FromIterator, Extendable};
-use std::iter::{FilterMap, Chain, Repeat, Zip};
-use std::iter::{range, range_inclusive};
-use std::mem::replace;
-use std::num;
-use std::option::{Option, Some, None};
-use std::rand;
-use std::rand::Rng;
-use std::result::{Ok, Err};
-use std::slice::ImmutableVector;
-
-mod table {
- use std::clone::Clone;
- use std::cmp;
- use std::cmp::PartialEq;
- use std::hash::{Hash, Hasher};
- use std::kinds::marker;
- use std::num::{CheckedMul, is_power_of_two};
- use std::option::{Option, Some, None};
- use std::prelude::Drop;
- use std::ptr;
- use std::ptr::RawPtr;
- use std::mem::{min_align_of, size_of};
- use std::intrinsics::{move_val_init, set_memory, transmute};
- use std::iter::{Iterator, range_step_inclusive};
- use std::rt::heap::{allocate, deallocate};
-
- static EMPTY_BUCKET: u64 = 0u64;
-
- /// The raw hashtable, providing safe-ish access to the unzipped and highly
- /// optimized arrays of hashes, keys, and values.
- ///
- /// This design uses less memory and is a lot faster than the naive
- /// `Vec<Option<u64, K, V>>`, because we don't pay for the overhead of an
- /// option on every element, and we get a generally more cache-aware design.
- ///
- /// Key invariants of this structure:
- ///
- /// - if hashes[i] == EMPTY_BUCKET, then keys[i] and vals[i] have
- /// 'undefined' contents. Don't read from them. This invariant is
- /// enforced outside this module with the `EmptyIndex`, `FullIndex`,
- /// and `SafeHash` types.
- ///
- /// - An `EmptyIndex` is only constructed for a bucket at an index with
- /// a hash of EMPTY_BUCKET.
- ///
- /// - A `FullIndex` is only constructed for a bucket at an index with a
- /// non-EMPTY_BUCKET hash.
- ///
- /// - A `SafeHash` is only constructed for non-`EMPTY_BUCKET` hash. We get
- /// around hashes of zero by changing them to 0x8000_0000_0000_0000,
- /// which will likely map to the same bucket, while not being confused
- /// with "empty".
- ///
- /// - All three "arrays represented by pointers" are the same length:
- /// `capacity`. This is set at creation and never changes. The arrays
- /// are unzipped to save space (we don't have to pay for the padding
- /// between odd sized elements, such as in a map from u64 to u8), and
- /// be more cache aware (scanning through 8 hashes brings in 2 cache
- /// lines, since they're all right beside each other).
- ///
- /// You can kind of think of this module/data structure as a safe wrapper
- /// around just the "table" part of the hashtable. It enforces some
- /// invariants at the type level and employs some performance trickery,
- /// but in general is just a tricked out `Vec<Option<u64, K, V>>`.
- ///
- /// FIXME(cgaebel):
- ///
- /// Feb 11, 2014: This hashtable was just implemented, and, hard as I tried,
- /// isn't yet totally safe. There's a "known exploit" that you can create
- /// multiple FullIndexes for a bucket, `take` one, and then still `take`
- /// the other causing undefined behavior. Currently, there's no story
- /// for how to protect against this statically. Therefore, there are asserts
- /// on `take`, `get`, `get_mut`, and `put` which check the bucket state.
- /// With time, and when we're confident this works correctly, they should
- /// be removed. Also, the bounds check in `peek` is especially painful,
- /// as that's called in the innermost loops of the hashtable and has the
- /// potential to be a major performance drain. Remove this too.
- ///
- /// Or, better than remove, only enable these checks for debug builds.
- /// There's currently no "debug-only" asserts in rust, so if you're reading
- /// this and going "what? of course there are debug-only asserts!", then
- /// please make this use them!
- #[unsafe_no_drop_flag]
- pub struct RawTable<K, V> {
- capacity: uint,
- size: uint,
- hashes: *mut u64,
- keys: *mut K,
- vals: *mut V,
- }
-
- /// Represents an index into a `RawTable` with no key or value in it.
- pub struct EmptyIndex {
- idx: int,
- nocopy: marker::NoCopy,
- }
-
- /// Represents an index into a `RawTable` with a key, value, and hash
- /// in it.
- pub struct FullIndex {
- idx: int,
- hash: SafeHash,
- nocopy: marker::NoCopy,
- }
-
- impl FullIndex {
- /// Since we get the hash for free whenever we check the bucket state,
- /// this function is provided for fast access, letting us avoid
- /// redundant trips back to the hashtable.
- #[inline(always)]
- pub fn hash(&self) -> SafeHash { self.hash }
-
- /// Same comment as with `hash`.
- #[inline(always)]
- pub fn raw_index(&self) -> uint { self.idx as uint }
- }
-
- /// Represents the state of a bucket: it can either have a key/value
- /// pair (be full) or not (be empty). You cannot `take` empty buckets,
- /// and you cannot `put` into full buckets.
- pub enum BucketState {
- Empty(EmptyIndex),
- Full(FullIndex),
- }
-
- /// A hash that is not zero, since we use a hash of zero to represent empty
- /// buckets.
- #[deriving(PartialEq)]
- pub struct SafeHash {
- hash: u64,
- }
-
- impl SafeHash {
- /// Peek at the hash value, which is guaranteed to be non-zero.
- #[inline(always)]
- pub fn inspect(&self) -> u64 { self.hash }
- }
-
- /// We need to remove hashes of 0. That's reserved for empty buckets.
- /// This function wraps up `hash_keyed` to be the only way outside this
- /// module to generate a SafeHash.
- pub fn make_hash<T: Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
- match hasher.hash(t) {
- // This constant is exceedingly likely to hash to the same
- // bucket, but it won't be counted as empty!
- EMPTY_BUCKET => SafeHash { hash: 0x8000_0000_0000_0000 },
- h => SafeHash { hash: h },
- }
- }
-
- fn round_up_to_next(unrounded: uint, target_alignment: uint) -> uint {
- assert!(is_power_of_two(target_alignment));
- (unrounded + target_alignment - 1) & !(target_alignment - 1)
- }
-
- #[test]
- fn test_rounding() {
- assert_eq!(round_up_to_next(0, 4), 0);
- assert_eq!(round_up_to_next(1, 4), 4);
- assert_eq!(round_up_to_next(2, 4), 4);
- assert_eq!(round_up_to_next(3, 4), 4);
- assert_eq!(round_up_to_next(4, 4), 4);
- assert_eq!(round_up_to_next(5, 4), 8);
- }
-
- // Returns a tuple of (minimum required malloc alignment, hash_offset,
- // key_offset, val_offset, array_size), from the start of a mallocated array.
- fn calculate_offsets(
- hash_size: uint, hash_align: uint,
- keys_size: uint, keys_align: uint,
- vals_size: uint, vals_align: uint) -> (uint, uint, uint, uint, uint) {
-
- let hash_offset = 0;
- let end_of_hashes = hash_offset + hash_size;
-
- let keys_offset = round_up_to_next(end_of_hashes, keys_align);
- let end_of_keys = keys_offset + keys_size;
-
- let vals_offset = round_up_to_next(end_of_keys, vals_align);
- let end_of_vals = vals_offset + vals_size;
-
- let min_align = cmp::max(hash_align, cmp::max(keys_align, vals_align));
-
- (min_align, hash_offset, keys_offset, vals_offset, end_of_vals)
- }
-
- #[test]
- fn test_offset_calculation() {
- assert_eq!(calculate_offsets(128, 8, 15, 1, 4, 4 ), (8, 0, 128, 144, 148));
- assert_eq!(calculate_offsets(3, 1, 2, 1, 1, 1 ), (1, 0, 3, 5, 6));
- assert_eq!(calculate_offsets(6, 2, 12, 4, 24, 8), (8, 0, 8, 24, 48));
- }
-
- impl<K, V> RawTable<K, V> {
-
- /// Does not initialize the buckets. The caller should ensure they,
- /// at the very least, set every hash to EMPTY_BUCKET.
- unsafe fn new_uninitialized(capacity: uint) -> RawTable<K, V> {
- let hashes_size =
- capacity.checked_mul(&size_of::<u64>()).expect("capacity overflow");
- let keys_size =
- capacity.checked_mul(&size_of::< K >()).expect("capacity overflow");
- let vals_size =
- capacity.checked_mul(&size_of::< V >()).expect("capacity overflow");
-
- // Allocating hashmaps is a little tricky. We need to allocate three
- // arrays, but since we know their sizes and alignments up front,
- // we just allocate a single array, and then have the subarrays
- // point into it.
- //
- // This is great in theory, but in practice getting the alignment
- // right is a little subtle. Therefore, calculating offsets has been
- // factored out into a different function.
- let (malloc_alignment, hash_offset, keys_offset, vals_offset, size) =
- calculate_offsets(
- hashes_size, min_align_of::<u64>(),
- keys_size, min_align_of::< K >(),
- vals_size, min_align_of::< V >());
-
- let buffer = allocate(size, malloc_alignment);
-
- let hashes = buffer.offset(hash_offset as int) as *mut u64;
- let keys = buffer.offset(keys_offset as int) as *mut K;
- let vals = buffer.offset(vals_offset as int) as *mut V;
-
- RawTable {
- capacity: capacity,
- size: 0,
- hashes: hashes,
- keys: keys,
- vals: vals,
- }
- }
-
- /// Creates a new raw table from a given capacity. All buckets are
- /// initially empty.
- pub fn new(capacity: uint) -> RawTable<K, V> {
- unsafe {
- let ret = RawTable::new_uninitialized(capacity);
- set_memory(ret.hashes, 0u8, capacity);
- ret
- }
- }
-
- /// Reads a bucket at a given index, returning an enum indicating whether
- /// there's anything there or not. You need to match on this enum to get
- /// the appropriate types to pass on to most of the other functions in
- /// this module.
- pub fn peek(&self, index: uint) -> BucketState {
- debug_assert!(index < self.capacity);
-
- let idx = index as int;
- let hash = unsafe { *self.hashes.offset(idx) };
-
- let nocopy = marker::NoCopy;
-
- match hash {
- EMPTY_BUCKET =>
- Empty(EmptyIndex {
- idx: idx,
- nocopy: nocopy
- }),
- full_hash =>
- Full(FullIndex {
- idx: idx,
- hash: SafeHash { hash: full_hash },
- nocopy: nocopy,
- })
- }
- }
-
- /// Gets references to the key and value at a given index.
- pub fn read<'a>(&'a self, index: &FullIndex) -> (&'a K, &'a V) {
- let idx = index.idx;
-
- unsafe {
- debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
- (&'a *self.keys.offset(idx),
- &'a *self.vals.offset(idx))
- }
- }
-
- /// Gets references to the key and value at a given index, with the
- /// value's reference being mutable.
- pub fn read_mut<'a>(&'a mut self, index: &FullIndex) -> (&'a K, &'a mut V) {
- let idx = index.idx;
-
- unsafe {
- debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
- (&'a *self.keys.offset(idx),
- &'a mut *self.vals.offset(idx))
- }
- }
-
- /// Read everything, mutably.
- pub fn read_all_mut<'a>(&'a mut self, index: &FullIndex)
- -> (&'a mut SafeHash, &'a mut K, &'a mut V) {
- let idx = index.idx;
-
- unsafe {
- debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
- (transmute(self.hashes.offset(idx)),
- &'a mut *self.keys.offset(idx),
- &'a mut *self.vals.offset(idx))
- }
- }
-
- /// Puts a key and value pair, along with the key's hash, into a given
- /// index in the hashtable. Note how the `EmptyIndex` is 'moved' into this
- /// function, because that slot will no longer be empty when we return!
- /// A FullIndex is returned for later use, pointing to the newly-filled
- /// slot in the hashtable.
- ///
- /// Use `make_hash` to construct a `SafeHash` to pass to this function.
- pub fn put(&mut self, index: EmptyIndex, hash: SafeHash, k: K, v: V) -> FullIndex {
- let idx = index.idx;
-
- unsafe {
- debug_assert_eq!(*self.hashes.offset(idx), EMPTY_BUCKET);
- *self.hashes.offset(idx) = hash.inspect();
- move_val_init(&mut *self.keys.offset(idx), k);
- move_val_init(&mut *self.vals.offset(idx), v);
- }
-
- self.size += 1;
-
- FullIndex { idx: idx, hash: hash, nocopy: marker::NoCopy }
- }
-
- /// Removes a key and value from the hashtable.
- ///
- /// This works similarly to `put`, building an `EmptyIndex` out of the
- /// taken FullIndex.
- pub fn take(&mut self, index: FullIndex) -> (EmptyIndex, K, V) {
- let idx = index.idx;
-
- unsafe {
- debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
-
- *self.hashes.offset(idx) = EMPTY_BUCKET;
-
- // Drop the mutable constraint.
- let keys = self.keys as *K;
- let vals = self.vals as *V;
-
- let k = ptr::read(keys.offset(idx));
- let v = ptr::read(vals.offset(idx));
-
- self.size -= 1;
-
- (EmptyIndex { idx: idx, nocopy: marker::NoCopy }, k, v)
- }
- }
-
- /// The hashtable's capacity, similar to a vector's.
- pub fn capacity(&self) -> uint {
- self.capacity
- }
-
- /// The number of elements ever `put` in the hashtable, minus the number
- /// of elements ever `take`n.
- pub fn size(&self) -> uint {
- self.size
- }
-
- pub fn iter<'a>(&'a self) -> Entries<'a, K, V> {
- Entries { table: self, idx: 0, elems_seen: 0 }
- }
-
- pub fn mut_iter<'a>(&'a mut self) -> MutEntries<'a, K, V> {
- MutEntries { table: self, idx: 0, elems_seen: 0 }
- }
-
- pub fn move_iter(self) -> MoveEntries<K, V> {
- MoveEntries { table: self, idx: 0, elems_seen: 0 }
- }
- }
-
- // `read_all_mut` casts a `*u64` to a `*SafeHash`. Since we statically
- // ensure that a `FullIndex` points to an index with a non-zero hash,
- // and a `SafeHash` is just a `u64` with a different name, this is
- // safe.
- //
- // This test ensures that a `SafeHash` really IS the same size as a
- // `u64`. If you need to change the size of `SafeHash` (and
- // consequently made this test fail), `read_all_mut` needs to be
- // modified to no longer assume this.
- #[test]
- fn can_alias_safehash_as_u64() {
- assert_eq!(size_of::<SafeHash>(), size_of::<u64>())
- }
-
- pub struct Entries<'a, K, V> {
- table: &'a RawTable<K, V>,
- idx: uint,
- elems_seen: uint,
- }
-
- pub struct MutEntries<'a, K, V> {
- table: &'a mut RawTable<K, V>,
- idx: uint,
- elems_seen: uint,
- }
-
- pub struct MoveEntries<K, V> {
- table: RawTable<K, V>,
- idx: uint,
- elems_seen: uint,
- }
-
- impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
- fn next(&mut self) -> Option<(&'a K, &'a V)> {
- while self.idx < self.table.capacity() {
- let i = self.idx;
- self.idx += 1;
-
- match self.table.peek(i) {
- Empty(_) => {},
- Full(idx) => {
- self.elems_seen += 1;
- return Some(self.table.read(&idx));
- }
- }
- }
-
- None
- }
-
- fn size_hint(&self) -> (uint, Option<uint>) {
- let size = self.table.size() - self.elems_seen;
- (size, Some(size))
- }
- }
-
- impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
- fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
- while self.idx < self.table.capacity() {
- let i = self.idx;
- self.idx += 1;
-
- match self.table.peek(i) {
- Empty(_) => {},
- // the transmute here fixes:
- // error: lifetime of `self` is too short to guarantee its contents
- // can be safely reborrowed
- Full(idx) => unsafe {
- self.elems_seen += 1;
- return Some(transmute(self.table.read_mut(&idx)));
- }
- }
- }
-
- None
- }
-
- fn size_hint(&self) -> (uint, Option<uint>) {
- let size = self.table.size() - self.elems_seen;
- (size, Some(size))
- }
- }
-
- impl<K, V> Iterator<(SafeHash, K, V)> for MoveEntries<K, V> {
- fn next(&mut self) -> Option<(SafeHash, K, V)> {
- while self.idx < self.table.capacity() {
- let i = self.idx;
- self.idx += 1;
-
- match self.table.peek(i) {
- Empty(_) => {},
- Full(idx) => {
- let h = idx.hash();
- let (_, k, v) = self.table.take(idx);
- return Some((h, k, v));
- }
- }
- }
-
- None
- }
-
- fn size_hint(&self) -> (uint, Option<uint>) {
- let size = self.table.size();
- (size, Some(size))
- }
- }
-
- impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
- fn clone(&self) -> RawTable<K, V> {
- unsafe {
- let mut new_ht = RawTable::new_uninitialized(self.capacity());
-
- for i in range(0, self.capacity()) {
- match self.peek(i) {
- Empty(_) => {
- *new_ht.hashes.offset(i as int) = EMPTY_BUCKET;
- },
- Full(idx) => {
- let hash = idx.hash().inspect();
- let (k, v) = self.read(&idx);
- *new_ht.hashes.offset(i as int) = hash;
- move_val_init(&mut *new_ht.keys.offset(i as int), (*k).clone());
- move_val_init(&mut *new_ht.vals.offset(i as int), (*v).clone());
- }
- }
- }
-
- new_ht.size = self.size();
-
- new_ht
- }
- }
- }
-
- #[unsafe_destructor]
- impl<K, V> Drop for RawTable<K, V> {
- fn drop(&mut self) {
- // This is in reverse because we're likely to have partially taken
- // some elements out with `.move_iter()` from the front.
- for i in range_step_inclusive(self.capacity as int - 1, 0, -1) {
- // Check if the size is 0, so we don't do a useless scan when
- // dropping empty tables such as on resize.
- if self.size == 0 { break }
-
- match self.peek(i as uint) {
- Empty(_) => {},
- Full(idx) => { self.take(idx); }
- }
- }
-
- assert_eq!(self.size, 0);
-
- if self.hashes.is_not_null() {
- let hashes_size = self.capacity * size_of::<u64>();
- let keys_size = self.capacity * size_of::<K>();
- let vals_size = self.capacity * size_of::<V>();
- let (align, _, _, _, size) = calculate_offsets(hashes_size, min_align_of::<u64>(),
- keys_size, min_align_of::<K>(),
- vals_size, min_align_of::<V>());
-
- unsafe {
- deallocate(self.hashes as *mut u8, size, align);
- // Remember how everything was allocated out of one buffer
- // during initialization? We only need one call to free here.
- }
-
- self.hashes = RawPtr::null();
- }
- }
- }
-}
-
-static INITIAL_LOG2_CAP: uint = 5;
-static INITIAL_CAPACITY: uint = 1 << INITIAL_LOG2_CAP; // 2^5
-
-/// The default behavior of HashMap implements a load factor of 90.9%.
-/// This behavior is characterized by the following conditions:
-///
-/// - if `size * 1.1 < cap < size * 4` then shouldn't resize
-/// - if `cap < minimum_capacity * 2` then shouldn't shrink
-#[deriving(Clone)]
-struct DefaultResizePolicy {
- /// Doubled minimal capacity. The capacity must never drop below
- /// the minimum capacity. (The check happens before the capacity
- /// is potentially halved.)
- minimum_capacity2: uint
-}
-
-impl DefaultResizePolicy {
- fn new(new_capacity: uint) -> DefaultResizePolicy {
- DefaultResizePolicy {
- minimum_capacity2: new_capacity << 1
- }
- }
-
- #[inline]
- fn capacity_range(&self, new_size: uint) -> (uint, uint) {
- ((new_size * 11) / 10, max(new_size << 3, self.minimum_capacity2))
- }
-
- #[inline]
- fn reserve(&mut self, new_capacity: uint) {
- self.minimum_capacity2 = new_capacity << 1;
- }
-}
-
-// The main performance trick in this hashmap is called Robin Hood Hashing.
-// It gains its excellent performance from one key invariant:
-//
-// If an insertion collides with an existing element, and that elements
-// "probe distance" (how far away the element is from its ideal location)
-// is higher than how far we've already probed, swap the elements.
-//
-// This massively lowers variance in probe distance, and allows us to get very
-// high load factors with good performance. The 90% load factor I use is rather
-// conservative.
-//
-// > Why a load factor of approximately 90%?
-//
-// In general, all the distances to initial buckets will converge on the mean.
-// At a load factor of α, the odds of finding the target bucket after k
-// probes is approximately 1-α^k. If we set this equal to 50% (since we converge
-// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round
-// this down to make the math easier on the CPU and avoid its FPU.
-// Since on average we start the probing in the middle of a cache line, this
-// strategy pulls in two cache lines of hashes on every lookup. I think that's
-// pretty good, but if you want to trade off some space, it could go down to one
-// cache line on average with an α of 0.84.
-//
-// > Wait, what? Where did you get 1-α^k from?
-//
-// On the first probe, your odds of a collision with an existing element is α.
-// The odds of doing this twice in a row is approximately α^2. For three times,
-// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT
-// colliding after k tries is 1-α^k.
-//
-// Future Improvements (FIXME!)
-// ============================
-//
-// Allow the load factor to be changed dynamically and/or at initialization.
-//
-// Also, would it be possible for us to reuse storage when growing the
-// underlying table? This is exactly the use case for 'realloc', and may
-// be worth exploring.
-//
-// Future Optimizations (FIXME!)
-// =============================
-//
-// The paper cited below mentions an implementation which keeps track of the
-// distance-to-initial-bucket histogram. I'm suspicious of this approach because
-// it requires maintaining an internal map. If this map were replaced with a
-// hashmap, it would be faster, but now our data structure is self-referential
-// and blows up. Also, this allows very good first guesses, but array accesses
-// are no longer linear and in one direction, as we have now. There is also
-// memory and cache pressure that this map would entail that would be very
-// difficult to properly see in a microbenchmark.
-//
-// Another possible design choice that I made without any real reason is
-// parameterizing the raw table over keys and values. Technically, all we need
-// is the size and alignment of keys and values, and the code should be just as
-// efficient (well, we might need one for power-of-two size and one for not...).
-// This has the potential to reduce code bloat in rust executables, without
-// really losing anything except 4 words (key size, key alignment, val size,
-// val alignment) which can be passed in to every call of a `RawTable` function.
-// This would definitely be an avenue worth exploring if people start complaining
-// about the size of rust executables.
-//
-// There's also an "optimization" that has been omitted regarding how the
-// hashtable allocates. The vector type has set the expectation that a hashtable
-// which never has an element inserted should not allocate. I'm suspicious of
-// implementing this for hashtables, because supporting it has no performance
-// benefit over using an `Option<HashMap<K, V>>`, and is significantly more
-// complicated.
-
-/// A hash map implementation which uses linear probing with Robin
-/// Hood bucket stealing.
-///
-/// The hashes are all keyed by the task-local random number generator
-/// on creation by default, this means the ordering of the keys is
-/// randomized, but makes the tables more resistant to
-/// denial-of-service attacks (Hash DoS). This behaviour can be
-/// overridden with one of the constructors.
-///
-/// It is required that the keys implement the `PartialEq` and `Hash` traits, although
-/// this can frequently be achieved by using `#[deriving(PartialEq, Hash)]`.
-///
-/// Relevant papers/articles:
-///
-/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf)
-/// 2. Emmanuel Goossaert. ["Robin Hood
-/// hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/)
-/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift
-/// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/)
-///
-/// # Example
-///
-/// ```rust
-/// use collections::HashMap;
-///
-/// // type inference lets us omit an explicit type signature (which
-/// // would be `HashMap<&str, &str>` in this example).
-/// let mut book_reviews = HashMap::new();
-///
-/// // review some books.
-/// book_reviews.insert("Adventures of Huckleberry Finn", "My favorite book.");
-/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
-/// book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
-/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
-///
-/// // check for a specific one.
-/// if !book_reviews.contains_key(&("Les Misérables")) {
-/// println!("We've got {} reviews, but Les Misérables ain't one.",
-/// book_reviews.len());
-/// }
-///
-/// // oops, this review has a lot of spelling mistakes, let's delete it.
-/// book_reviews.remove(&("The Adventures of Sherlock Holmes"));
-///
-/// // look up the values associated with some keys.
-/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
-/// for book in to_find.iter() {
-/// match book_reviews.find(book) {
-/// Some(review) => println!("{}: {}", *book, *review),
-/// None => println!("{} is unreviewed.", *book)
-/// }
-/// }
-///
-/// // iterate over everything.
-/// for (book, review) in book_reviews.iter() {
-/// println!("{}: \"{}\"", *book, *review);
-/// }
-/// ```
-#[deriving(Clone)]
-pub struct HashMap<K, V, H = sip::SipHasher> {
- // All hashes are keyed on these values, to prevent hash collision attacks.
- hasher: H,
-
- table: table::RawTable<K, V>,
-
- // We keep this at the end since it might as well have tail padding.
- resize_policy: DefaultResizePolicy,
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
- // Probe the `idx`th bucket for a given hash, returning the index of the
- // target bucket.
- //
- // This exploits the power-of-two size of the hashtable. As long as this
- // is always true, we can use a bitmask of cap-1 to do modular arithmetic.
- //
- // Prefer using this with increasing values of `idx` rather than repeatedly
- // calling `probe_next`. This reduces data-dependencies between loops, which
- // can help the optimizer, and certainly won't hurt it. `probe_next` is
- // simply for convenience, and is no more efficient than `probe`.
- fn probe(&self, hash: &table::SafeHash, idx: uint) -> uint {
- let hash_mask = self.table.capacity() - 1;
-
- // So I heard a rumor that unsigned overflow is safe in rust..
- ((hash.inspect() as uint) + idx) & hash_mask
- }
-
- // Generate the next probe in a sequence. Prefer using 'probe' by itself,
- // but this can sometimes be useful.
- fn probe_next(&self, probe: uint) -> uint {
- let hash_mask = self.table.capacity() - 1;
- (probe + 1) & hash_mask
- }
-
- fn make_hash<X: Hash<S>>(&self, x: &X) -> table::SafeHash {
- table::make_hash(&self.hasher, x)
- }
-
- /// Get the distance of the bucket at the given index that it lies
- /// from its 'ideal' location.
- ///
- /// In the cited blog posts above, this is called the "distance to
- /// initial bucket", or DIB.
- fn bucket_distance(&self, index_of_elem: &table::FullIndex) -> uint {
- // where the hash of the element that happens to reside at
- // `index_of_elem` tried to place itself first.
- let first_probe_index = self.probe(&index_of_elem.hash(), 0);
-
- let raw_index = index_of_elem.raw_index();
-
- if first_probe_index <= raw_index {
- // probe just went forward
- raw_index - first_probe_index
- } else {
- // probe wrapped around the hashtable
- raw_index + (self.table.capacity() - first_probe_index)
- }
- }
-
- /// Search for a pre-hashed key.
- fn search_hashed_generic(&self, hash: &table::SafeHash, is_match: |&K| -> bool)
- -> Option<table::FullIndex> {
- for num_probes in range(0u, self.table.size()) {
- let probe = self.probe(hash, num_probes);
-
- let idx = match self.table.peek(probe) {
- table::Empty(_) => return None, // hit an empty bucket
- table::Full(idx) => idx
- };
-
- // We can finish the search early if we hit any bucket
- // with a lower distance to initial bucket than we've probed.
- if self.bucket_distance(&idx) < num_probes { return None }
-
- // If the hash doesn't match, it can't be this one..
- if *hash != idx.hash() { continue }
-
- let (k, _) = self.table.read(&idx);
-
- // If the key doesn't match, it can't be this one..
- if !is_match(k) { continue }
-
- return Some(idx);
- }
-
- return None
- }
-
- fn search_hashed(&self, hash: &table::SafeHash, k: &K) -> Option<table::FullIndex> {
- self.search_hashed_generic(hash, |k_| *k == *k_)
- }
-
- fn search_equiv<Q: Hash<S> + Equiv<K>>(&self, q: &Q) -> Option<table::FullIndex> {
- self.search_hashed_generic(&self.make_hash(q), |k| q.equiv(k))
- }
-
- /// Search for a key, yielding the index if it's found in the hashtable.
- /// If you already have the hash for the key lying around, use
- /// search_hashed.
- fn search(&self, k: &K) -> Option<table::FullIndex> {
- self.search_hashed(&self.make_hash(k), k)
- }
-
- fn pop_internal(&mut self, starting_index: table::FullIndex) -> Option<V> {
- let starting_probe = starting_index.raw_index();
-
- let ending_probe = {
- let mut probe = self.probe_next(starting_probe);
- for _ in range(0u, self.table.size()) {
- match self.table.peek(probe) {
- table::Empty(_) => {}, // empty bucket. this is the end of our shifting.
- table::Full(idx) => {
- // Bucket that isn't us, which has a non-zero probe distance.
- // This isn't the ending index, so keep searching.
- if self.bucket_distance(&idx) != 0 {
- probe = self.probe_next(probe);
- continue;
- }
-
- // if we do have a bucket_distance of zero, we're at the end
- // of what we need to shift.
- }
- }
- break;
- }
-
- probe
- };
-
- let (_, _, retval) = self.table.take(starting_index);
-
- let mut probe = starting_probe;
- let mut next_probe = self.probe_next(probe);
-
- // backwards-shift all the elements after our newly-deleted one.
- while next_probe != ending_probe {
- match self.table.peek(next_probe) {
- table::Empty(_) => {
- // nothing to shift in. just empty it out.
- match self.table.peek(probe) {
- table::Empty(_) => {},
- table::Full(idx) => { self.table.take(idx); }
- }
- },
- table::Full(next_idx) => {
- // something to shift. move it over!
- let next_hash = next_idx.hash();
- let (_, next_key, next_val) = self.table.take(next_idx);
- match self.table.peek(probe) {
- table::Empty(idx) => {
- self.table.put(idx, next_hash, next_key, next_val);
- },
- table::Full(idx) => {
- let (emptyidx, _, _) = self.table.take(idx);
- self.table.put(emptyidx, next_hash, next_key, next_val);
- }
- }
- }
- }
-
- probe = next_probe;
- next_probe = self.probe_next(next_probe);
- }
-
- // Done the backwards shift, but there's still an element left!
- // Empty it out.
- match self.table.peek(probe) {
- table::Empty(_) => {},
- table::Full(idx) => { self.table.take(idx); }
- }
-
- // Now we're done all our shifting. Return the value we grabbed
- // earlier.
- return Some(retval);
- }
-
- /// Like `pop`, but can operate on any type that is equivalent to a key.
- #[experimental]
- pub fn pop_equiv<Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
- if self.table.size() == 0 {
- return None
- }
-
- let potential_new_size = self.table.size() - 1;
- self.make_some_room(potential_new_size);
-
- let starting_index = match self.search_equiv(k) {
- Some(idx) => idx,
- None => return None,
- };
-
- self.pop_internal(starting_index)
- }
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Container for HashMap<K, V, H> {
- /// Return the number of elements in the map
- fn len(&self) -> uint { self.table.size() }
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Mutable for HashMap<K, V, H> {
- /// Clear the map, removing all key-value pairs. Keeps the allocated memory
- /// for reuse.
- fn clear(&mut self) {
- // Prevent reallocations from happening from now on. Makes it possible
- // for the map to be reused but has a downside: reserves permanently.
- self.resize_policy.reserve(self.table.size());
-
- for i in range(0, self.table.capacity()) {
- match self.table.peek(i) {
- table::Empty(_) => {},
- table::Full(idx) => { self.table.take(idx); }
- }
- }
- }
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Map<K, V> for HashMap<K, V, H> {
- fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
- self.search(k).map(|idx| {
- let (_, v) = self.table.read(&idx);
- v
- })
- }
-
- fn contains_key(&self, k: &K) -> bool {
- self.search(k).is_some()
- }
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V, H> {
- fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
- match self.search(k) {
- None => None,
- Some(idx) => {
- let (_, v) = self.table.read_mut(&idx);
- Some(v)
- }
- }
- }
-
- fn swap(&mut self, k: K, v: V) -> Option<V> {
- let hash = self.make_hash(&k);
- let potential_new_size = self.table.size() + 1;
- self.make_some_room(potential_new_size);
-
- for dib in range_inclusive(0u, self.table.size()) {
- let probe = self.probe(&hash, dib);
-
- let idx = match self.table.peek(probe) {
- table::Empty(idx) => {
- // Found a hole!
- self.table.put(idx, hash, k, v);
- return None;
- },
- table::Full(idx) => idx
- };
-
- if idx.hash() == hash {
- let (bucket_k, bucket_v) = self.table.read_mut(&idx);
- if k == *bucket_k {
- // Found an existing value.
- return Some(replace(bucket_v, v));
- }
- }
-
- let probe_dib = self.bucket_distance(&idx);
-
- if probe_dib < dib {
- // Found a luckier bucket. This implies that the key does not
- // already exist in the hashtable. Just do a robin hood
- // insertion, then.
- self.robin_hood(idx, probe_dib, hash, k, v);
- return None;
- }
- }
-
- // We really shouldn't be here.
- fail!("Internal HashMap error: Out of space.");
- }
-
- fn pop(&mut self, k: &K) -> Option<V> {
- if self.table.size() == 0 {
- return None
- }
-
- let potential_new_size = self.table.size() - 1;
- self.make_some_room(potential_new_size);
-
- let starting_index = match self.search(k) {
- Some(idx) => idx,
- None => return None,
- };
-
- self.pop_internal(starting_index)
- }
-
-}
-
-impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
- /// Create an empty HashMap.
- pub fn new() -> HashMap<K, V, sip::SipHasher> {
- HashMap::with_capacity(INITIAL_CAPACITY)
- }
-
- pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> {
- let mut r = rand::task_rng();
- let r0 = r.gen();
- let r1 = r.gen();
- let hasher = sip::SipHasher::new_with_keys(r0, r1);
- HashMap::with_capacity_and_hasher(capacity, hasher)
- }
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
- pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
- HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
- }
-
- /// Create an empty HashMap with space for at least `capacity`
- /// elements, using `hasher` to hash the keys.
- ///
- /// Warning: `hasher` is normally randomly generated, and
- /// is designed to allow HashMaps to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
- pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
- let cap = num::next_power_of_two(max(INITIAL_CAPACITY, capacity));
- HashMap {
- hasher: hasher,
- resize_policy: DefaultResizePolicy::new(cap),
- table: table::RawTable::new(cap),
- }
- }
-
- /// The hashtable will never try to shrink below this size. You can use
- /// this function to reduce reallocations if your hashtable frequently
- /// grows and shrinks by large amounts.
- ///
- /// This function has no effect on the operational semantics of the
- /// hashtable, only on performance.
- pub fn reserve(&mut self, new_minimum_capacity: uint) {
- let cap = num::next_power_of_two(
- max(INITIAL_CAPACITY, new_minimum_capacity));
-
- self.resize_policy.reserve(cap);
-
- if self.table.capacity() < cap {
- self.resize(cap);
- }
- }
-
- /// Resizes the internal vectors to a new capacity. It's your responsibility to:
- /// 1) Make sure the new capacity is enough for all the elements, accounting
- /// for the load factor.
- /// 2) Ensure new_capacity is a power of two.
- fn resize(&mut self, new_capacity: uint) {
- assert!(self.table.size() <= new_capacity);
- assert!(num::is_power_of_two(new_capacity));
-
- let old_table = replace(&mut self.table, table::RawTable::new(new_capacity));
- let old_size = old_table.size();
-
- for (h, k, v) in old_table.move_iter() {
- self.insert_hashed_nocheck(h, k, v);
- }
-
- assert_eq!(self.table.size(), old_size);
- }
-
- /// Performs any necessary resize operations, such that there's space for
- /// new_size elements.
- fn make_some_room(&mut self, new_size: uint) {
- let (grow_at, shrink_at) = self.resize_policy.capacity_range(new_size);
- let cap = self.table.capacity();
-
- // An invalid value shouldn't make us run out of space.
- debug_assert!(grow_at >= new_size);
-
- if cap <= grow_at {
- let new_capacity = cap << 1;
- self.resize(new_capacity);
- } else if shrink_at <= cap {
- let new_capacity = cap >> 1;
- self.resize(new_capacity);
- }
- }
-
- /// Perform robin hood bucket stealing at the given 'index'. You must
- /// also pass that probe's "distance to initial bucket" so we don't have
- /// to recalculate it, as well as the total number of probes already done
- /// so we have some sort of upper bound on the number of probes to do.
- ///
- /// 'hash', 'k', and 'v' are the elements to robin hood into the hashtable.
- fn robin_hood(&mut self, mut index: table::FullIndex, mut dib_param: uint,
- mut hash: table::SafeHash, mut k: K, mut v: V) {
- 'outer: loop {
- let (old_hash, old_key, old_val) = {
- let (old_hash_ref, old_key_ref, old_val_ref) =
- self.table.read_all_mut(&index);
-
- let old_hash = replace(old_hash_ref, hash);
- let old_key = replace(old_key_ref, k);
- let old_val = replace(old_val_ref, v);
-
- (old_hash, old_key, old_val)
- };
-
- let mut probe = self.probe_next(index.raw_index());
-
- for dib in range(dib_param + 1, self.table.size()) {
- let full_index = match self.table.peek(probe) {
- table::Empty(idx) => {
- // Finally. A hole!
- self.table.put(idx, old_hash, old_key, old_val);
- return;
- },
- table::Full(idx) => idx
- };
-
- let probe_dib = self.bucket_distance(&full_index);
-
- // Robin hood! Steal the spot.
- if probe_dib < dib {
- index = full_index;
- dib_param = probe_dib;
- hash = old_hash;
- k = old_key;
- v = old_val;
- continue 'outer;
- }
-
- probe = self.probe_next(probe);
- }
-
- fail!("HashMap fatal error: 100% load factor?");
- }
- }
-
- /// Insert a pre-hashed key-value pair, without first checking
- /// that there's enough room in the buckets. Returns a reference to the
- /// newly insert value.
- ///
- /// If the key already exists, the hashtable will be returned untouched
- /// and a reference to the existing element will be returned.
- fn insert_hashed_nocheck<'a>(
- &'a mut self, hash: table::SafeHash, k: K, v: V) -> &'a mut V {
-
- for dib in range_inclusive(0u, self.table.size()) {
- let probe = self.probe(&hash, dib);
-
- let idx = match self.table.peek(probe) {
- table::Empty(idx) => {
- // Found a hole!
- let fullidx = self.table.put(idx, hash, k, v);
- let (_, val) = self.table.read_mut(&fullidx);
- return val;
- },
- table::Full(idx) => idx
- };
-
- if idx.hash() == hash {
- let (bucket_k, bucket_v) = self.table.read_mut(&idx);
- // FIXME #12147 the conditional return confuses
- // borrowck if we return bucket_v directly
- let bv: *mut V = bucket_v;
- if k == *bucket_k {
- // Key already exists. Get its reference.
- return unsafe {&mut *bv};
- }
- }
-
- let probe_dib = self.bucket_distance(&idx);
-
- if probe_dib < dib {
- // Found a luckier bucket than me. Better steal his spot.
- self.robin_hood(idx, probe_dib, hash, k, v);
-
- // Now that it's stolen, just read the value's pointer
- // right out of the table!
- match self.table.peek(probe) {
- table::Empty(_) => fail!("Just stole a spot, but now that spot's empty."),
- table::Full(idx) => {
- let (_, v) = self.table.read_mut(&idx);
- return v;
- }
- }
- }
- }
-
- // We really shouldn't be here.
- fail!("Internal HashMap error: Out of space.");
- }
-
- /// Inserts an element which has already been hashed, returning a reference
- /// to that element inside the hashtable. This is more efficient that using
- /// `insert`, since the key will not be rehashed.
- fn insert_hashed<'a>(&'a mut self, hash: table::SafeHash, k: K, v: V) -> &'a mut V {
- let potential_new_size = self.table.size() + 1;
- self.make_some_room(potential_new_size);
- self.insert_hashed_nocheck(hash, k, v)
- }
-
- /// Return the value corresponding to the key in the map, or insert
- /// and return the value if it doesn't exist.
- pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V {
- self.find_with_or_insert_with(k, v, |_k, _v, _a| (), |_k, a| a)
- }
-
- /// Return the value corresponding to the key in the map, or create,
- /// insert, and return a new value if it doesn't exist.
- pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: |&K| -> V)
- -> &'a mut V {
- self.find_with_or_insert_with(k, (), |_k, _v, _a| (), |k, _a| f(k))
- }
-
- /// Insert a key-value pair into the map if the key is not already present.
- /// Otherwise, modify the existing value for the key.
- /// Returns the new or modified value for the key.
- pub fn insert_or_update_with<'a>(
- &'a mut self,
- k: K,
- v: V,
- f: |&K, &mut V|)
- -> &'a mut V {
- self.find_with_or_insert_with(k, v, |k, v, _a| f(k, v), |_k, a| a)
- }
-
- /// Modify and return the value corresponding to the key in the map, or
- /// insert and return a new value if it doesn't exist.
- ///
- /// This method allows for all insertion behaviours of a hashmap;
- /// see methods like `insert`, `find_or_insert` and
- /// `insert_or_update_with` for less general and more friendly
- /// variations of this.
- ///
- /// # Example
- ///
- /// ```rust
- /// use collections::HashMap;
- ///
- /// // map some strings to vectors of strings
- /// let mut map = HashMap::new();
- /// map.insert("a key", vec!["value"]);
- /// map.insert("z key", vec!["value"]);
- ///
- /// let new = vec!["a key", "b key", "z key"];
- ///
- /// for k in new.move_iter() {
- /// map.find_with_or_insert_with(
- /// k, "new value",
- /// // if the key does exist either prepend or append this
- /// // new value based on the first letter of the key.
- /// |key, already, new| {
- /// if key.as_slice().starts_with("z") {
- /// already.unshift(new);
- /// } else {
- /// already.push(new);
- /// }
- /// },
- /// // if the key doesn't exist in the map yet, add it in
- /// // the obvious way.
- /// |_k, v| vec![v]);
- /// }
- ///
- /// assert_eq!(map.len(), 3);
- /// assert_eq!(map.get(&"a key"), &vec!["value", "new value"]);
- /// assert_eq!(map.get(&"b key"), &vec!["new value"]);
- /// assert_eq!(map.get(&"z key"), &vec!["new value", "value"]);
- /// ```
- pub fn find_with_or_insert_with<'a, A>(&'a mut self,
- k: K,
- a: A,
- found: |&K, &mut V, A|,
- not_found: |&K, A| -> V)
- -> &'a mut V {
- let hash = self.make_hash(&k);
- match self.search_hashed(&hash, &k) {
- None => {
- let v = not_found(&k, a);
- self.insert_hashed(hash, k, v)
- },
- Some(idx) => {
- let (_, v_ref) = self.table.read_mut(&idx);
- found(&k, v_ref, a);
- v_ref
- }
- }
- }
-
- /// Retrieves a value for the given key, failing if the key is not present.
- pub fn get<'a>(&'a self, k: &K) -> &'a V {
- match self.find(k) {
- Some(v) => v,
- None => fail!("No entry found for key: {:?}", k)
- }
- }
-
- /// Retrieves a (mutable) value for the given key, failing if the key is not present.
- pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
- match self.find_mut(k) {
- Some(v) => v,
- None => fail!("No entry found for key: {:?}", k)
- }
- }
-
- /// Return true if the map contains a value for the specified key,
- /// using equivalence.
- pub fn contains_key_equiv<Q: Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
- self.search_equiv(key).is_some()
- }
-
- /// Return the value corresponding to the key in the map, using
- /// equivalence.
- pub fn find_equiv<'a, Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
- match self.search_equiv(k) {
- None => None,
- Some(idx) => {
- let (_, v_ref) = self.table.read(&idx);
- Some(v_ref)
- }
- }
- }
-
- /// An iterator visiting all keys in arbitrary order.
- /// Iterator element type is &'a K.
- pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
- self.iter().map(|(k, _v)| k)
- }
-
- /// An iterator visiting all values in arbitrary order.
- /// Iterator element type is &'a V.
- pub fn values<'a>(&'a self) -> Values<'a, K, V> {
- self.iter().map(|(_k, v)| v)
- }
-
- /// An iterator visiting all key-value pairs in arbitrary order.
- /// Iterator element type is (&'a K, &'a V).
- pub fn iter<'a>(&'a self) -> Entries<'a, K, V> {
- self.table.iter()
- }
-
- /// An iterator visiting all key-value pairs in arbitrary order,
- /// with mutable references to the values.
- /// Iterator element type is (&'a K, &'a mut V).
- pub fn mut_iter<'a>(&'a mut self) -> MutEntries<'a, K, V> {
- self.table.mut_iter()
- }
-
- /// Creates a consuming iterator, that is, one that moves each key-value
- /// pair out of the map in arbitrary order. The map cannot be used after
- /// calling this.
- pub fn move_iter(self) -> MoveEntries<K, V> {
- self.table.move_iter().map(|(_, k, v)| (k, v))
- }
-}
-
-impl<K: Eq + Hash<S>, V: Clone, S, H: Hasher<S>> HashMap<K, V, H> {
- /// Like `find`, but returns a copy of the value.
- pub fn find_copy(&self, k: &K) -> Option<V> {
- self.find(k).map(|v| (*v).clone())
- }
-
- /// Like `get`, but returns a copy of the value.
- pub fn get_copy(&self, k: &K) -> V {
- (*self.get(k)).clone()
- }
-}
-
-impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, H> {
- fn eq(&self, other: &HashMap<K, V, H>) -> bool {
- if self.len() != other.len() { return false; }
-
- self.iter()
- .all(|(key, value)| {
- match other.find(key) {
- None => false,
- Some(v) => *value == *v
- }
- })
- }
-}
-
-impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, r"\{"));
-
- for (i, (k, v)) in self.iter().enumerate() {
- if i != 0 { try!(write!(f, ", ")); }
- try!(write!(f, "{}: {}", *k, *v));
- }
-
- write!(f, r"\}")
- }
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
- fn default() -> HashMap<K, V, H> {
- HashMap::with_hasher(Default::default())
- }
-}
-
-/// HashMap iterator
-pub type Entries<'a, K, V> = table::Entries<'a, K, V>;
-
-/// HashMap mutable values iterator
-pub type MutEntries<'a, K, V> = table::MutEntries<'a, K, V>;
-
-/// HashMap move iterator
-pub type MoveEntries<K, V> =
- iter::Map<'static, (table::SafeHash, K, V), (K, V), table::MoveEntries<K, V>>;
-
-/// HashMap keys iterator
-pub type Keys<'a, K, V> =
- iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>;
-
-/// HashMap values iterator
-pub type Values<'a, K, V> =
- iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>;
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
- fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
- let (lower, _) = iter.size_hint();
- let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
- map.extend(iter);
- map
- }
-}
-
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Extendable<(K, V)> for HashMap<K, V, H> {
- fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
- for (k, v) in iter {
- self.insert(k, v);
- }
- }
-}
-
-/// HashSet iterator
-pub type SetItems<'a, K> =
- iter::Map<'static, (&'a K, &'a ()), &'a K, Entries<'a, K, ()>>;
-
-/// HashSet move iterator
-pub type SetMoveItems<K> =
- iter::Map<'static, (K, ()), K, MoveEntries<K, ()>>;
-
-/// An implementation of a hash set using the underlying representation of a
-/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
-/// requires that the elements implement the `PartialEq` and `Hash` traits.
-#[deriving(Clone)]
-pub struct HashSet<T, H = sip::SipHasher> {
- map: HashMap<T, (), H>
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
- fn eq(&self, other: &HashSet<T, H>) -> bool {
- if self.len() != other.len() { return false; }
-
- self.iter().all(|key| other.contains(key))
- }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Container for HashSet<T, H> {
- fn len(&self) -> uint { self.map.len() }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> {
- fn clear(&mut self) { self.map.clear() }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
- fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
-
- fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
- self.iter().all(|v| !other.contains(v))
- }
-
- fn is_subset(&self, other: &HashSet<T, H>) -> bool {
- self.iter().all(|v| other.contains(v))
- }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
- fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
-
- fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
-}
-
-impl<T: Hash + Eq> HashSet<T, sip::SipHasher> {
- /// Create an empty HashSet
- pub fn new() -> HashSet<T, sip::SipHasher> {
- HashSet::with_capacity(INITIAL_CAPACITY)
- }
-
- /// Create an empty HashSet with space for at least `n` elements in
- /// the hash table.
- pub fn with_capacity(capacity: uint) -> HashSet<T, sip::SipHasher> {
- HashSet { map: HashMap::with_capacity(capacity) }
- }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
- pub fn with_hasher(hasher: H) -> HashSet<T, H> {
- HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
- }
-
- /// Create an empty HashSet with space for at least `capacity`
- /// elements in the hash table, using `hasher` to hash the keys.
- ///
- /// Warning: `hasher` is normally randomly generated, and
- /// is designed to allow `HashSet`s to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
- pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
- HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
- }
-
- /// Reserve space for at least `n` elements in the hash table.
- pub fn reserve(&mut self, n: uint) {
- self.map.reserve(n)
- }
-
- /// Returns true if the hash set contains a value equivalent to the
- /// given query value.
- pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
- self.map.contains_key_equiv(value)
- }
-
- /// An iterator visiting all elements in arbitrary order.
- /// Iterator element type is &'a T.
- pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
- self.map.keys()
- }
-
- /// Creates a consuming iterator, that is, one that moves each value out
- /// of the set in arbitrary order. The set cannot be used after calling
- /// this.
- pub fn move_iter(self) -> SetMoveItems<T> {
- self.map.move_iter().map(|(k, _)| k)
- }
-
- /// Visit the values representing the difference
- pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
- Repeat::new(other).zip(self.iter())
- .filter_map(|(other, elt)| {
- if !other.contains(elt) { Some(elt) } else { None }
- })
- }
-
- /// Visit the values representing the symmetric difference
- pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
- -> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
- self.difference(other).chain(other.difference(self))
- }
-
- /// Visit the values representing the intersection
- pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
- -> SetAlgebraItems<'a, T, H> {
- Repeat::new(other).zip(self.iter())
- .filter_map(|(other, elt)| {
- if other.contains(elt) { Some(elt) } else { None }
- })
- }
-
- /// Visit the values representing the union
- pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
- -> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
- self.iter().chain(other.difference(self))
- }
-}
-
-impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, r"\{"));
-
- for (i, x) in self.iter().enumerate() {
- if i != 0 { try!(write!(f, ", ")); }
- try!(write!(f, "{}", *x));
- }
-
- write!(f, r"\}")
- }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
- fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> {
- let (lower, _) = iter.size_hint();
- let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
- set.extend(iter);
- set
- }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H> {
- fn extend<I: Iterator<T>>(&mut self, mut iter: I) {
- for k in iter {
- self.insert(k);
- }
- }
-}
-
-impl<T: Eq + Hash> Default for HashSet<T, sip::SipHasher> {
- fn default() -> HashSet<T> { HashSet::new() }
-}
-
-// `Repeat` is used to feed the filter closure an explicit capture
-// of a reference to the other set
-/// Set operations iterator
-pub type SetAlgebraItems<'a, T, H> =
- FilterMap<'static, (&'a HashSet<T, H>, &'a T), &'a T,
- Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>>;
-
-#[cfg(test)]
-mod test_map {
- use super::HashMap;
- use std::cmp::Equiv;
- use std::hash::Hash;
- use std::iter::{Iterator,range_inclusive,range_step_inclusive};
- use std::cell::RefCell;
-
- struct KindaIntLike(int);
-
- impl Equiv<int> for KindaIntLike {
- fn equiv(&self, other: &int) -> bool {
- let KindaIntLike(this) = *self;
- this == *other
- }
- }
- impl<S: Writer> Hash<S> for KindaIntLike {
- fn hash(&self, state: &mut S) {
- let KindaIntLike(this) = *self;
- this.hash(state)
- }
- }
-
- #[test]
- fn test_create_capacity_zero() {
- let mut m = HashMap::with_capacity(0);
-
- assert!(m.insert(1, 1));
-
- assert!(m.contains_key(&1));
- assert!(!m.contains_key(&0));
- }
-
- #[test]
- fn test_insert() {
- let mut m = HashMap::new();
- assert_eq!(m.len(), 0);
- assert!(m.insert(1, 2));
- assert_eq!(m.len(), 1);
- assert!(m.insert(2, 4));
- assert_eq!(m.len(), 2);
- assert_eq!(*m.find(&1).unwrap(), 2);
- assert_eq!(*m.find(&2).unwrap(), 4);
- }
-
- local_data_key!(drop_vector: RefCell<Vec<int>>)
-
- #[deriving(Hash, PartialEq, Eq)]
- struct Dropable {
- k: uint
- }
-
-
- impl Dropable {
- fn new(k: uint) -> Dropable {
- let v = drop_vector.get().unwrap();
- v.borrow_mut().as_mut_slice()[k] += 1;
-
- Dropable { k: k }
- }
- }
-
- impl Drop for Dropable {
- fn drop(&mut self) {
- let v = drop_vector.get().unwrap();
- v.borrow_mut().as_mut_slice()[self.k] -= 1;
- }
- }
-
- #[test]
- fn test_drops() {
- drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0))));
-
- {
- let mut m = HashMap::new();
-
- let v = drop_vector.get().unwrap();
- for i in range(0u, 200) {
- assert_eq!(v.borrow().as_slice()[i], 0);
- }
- drop(v);
-
- for i in range(0u, 100) {
- let d1 = Dropable::new(i);
- let d2 = Dropable::new(i+100);
- m.insert(d1, d2);
- }
-
- let v = drop_vector.get().unwrap();
- for i in range(0u, 200) {
- assert_eq!(v.borrow().as_slice()[i], 1);
- }
- drop(v);
-
- for i in range(0u, 50) {
- let k = Dropable::new(i);
- let v = m.pop(&k);
-
- assert!(v.is_some());
-
- let v = drop_vector.get().unwrap();
- assert_eq!(v.borrow().as_slice()[i], 1);
- assert_eq!(v.borrow().as_slice()[i+100], 1);
- }
-
- let v = drop_vector.get().unwrap();
- for i in range(0u, 50) {
- assert_eq!(v.borrow().as_slice()[i], 0);
- assert_eq!(v.borrow().as_slice()[i+100], 0);
- }
-
- for i in range(50u, 100) {
- assert_eq!(v.borrow().as_slice()[i], 1);
- assert_eq!(v.borrow().as_slice()[i+100], 1);
- }
- }
-
- let v = drop_vector.get().unwrap();
- for i in range(0u, 200) {
- assert_eq!(v.borrow().as_slice()[i], 0);
- }
- }
-
- #[test]
- fn test_empty_pop() {
- let mut m: HashMap<int, bool> = HashMap::new();
- assert_eq!(m.pop(&0), None);
- }
-
- #[test]
- fn test_lots_of_insertions() {
- let mut m = HashMap::new();
-
- // Try this a few times to make sure we never screw up the hashmap's
- // internal state.
- for _ in range(0, 10) {
- assert!(m.is_empty());
-
- for i in range_inclusive(1, 1000) {
- assert!(m.insert(i, i));
-
- for j in range_inclusive(1, i) {
- let r = m.find(&j);
- assert_eq!(r, Some(&j));
- }
-
- for j in range_inclusive(i+1, 1000) {
- let r = m.find(&j);
- assert_eq!(r, None);
- }
- }
-
- for i in range_inclusive(1001, 2000) {
- assert!(!m.contains_key(&i));
- }
-
- // remove forwards
- for i in range_inclusive(1, 1000) {
- assert!(m.remove(&i));
-
- for j in range_inclusive(1, i) {
- assert!(!m.contains_key(&j));
- }
-
- for j in range_inclusive(i+1, 1000) {
- assert!(m.contains_key(&j));
- }
- }
-
- for i in range_inclusive(1, 1000) {
- assert!(!m.contains_key(&i));
- }
-
- for i in range_inclusive(1, 1000) {
- assert!(m.insert(i, i));
- }
-
- // remove backwards
- for i in range_step_inclusive(1000, 1, -1) {
- assert!(m.remove(&i));
-
- for j in range_inclusive(i, 1000) {
- assert!(!m.contains_key(&j));
- }
-
- for j in range_inclusive(1, i-1) {
- assert!(m.contains_key(&j));
- }
- }
- }
- }
-
- #[test]
- fn test_find_mut() {
- let mut m = HashMap::new();
- assert!(m.insert(1, 12));
- assert!(m.insert(2, 8));
- assert!(m.insert(5, 14));
- let new = 100;
- match m.find_mut(&5) {
- None => fail!(), Some(x) => *x = new
- }
- assert_eq!(m.find(&5), Some(&new));
- }
-
- #[test]
- fn test_insert_overwrite() {
- let mut m = HashMap::new();
- assert!(m.insert(1, 2));
- assert_eq!(*m.find(&1).unwrap(), 2);
- assert!(!m.insert(1, 3));
- assert_eq!(*m.find(&1).unwrap(), 3);
- }
-
- #[test]
- fn test_insert_conflicts() {
- let mut m = HashMap::with_capacity(4);
- assert!(m.insert(1, 2));
- assert!(m.insert(5, 3));
- assert!(m.insert(9, 4));
- assert_eq!(*m.find(&9).unwrap(), 4);
- assert_eq!(*m.find(&5).unwrap(), 3);
- assert_eq!(*m.find(&1).unwrap(), 2);
- }
-
- #[test]
- fn test_conflict_remove() {
- let mut m = HashMap::with_capacity(4);
- assert!(m.insert(1, 2));
- assert_eq!(*m.find(&1).unwrap(), 2);
- assert!(m.insert(5, 3));
- assert_eq!(*m.find(&1).unwrap(), 2);
- assert_eq!(*m.find(&5).unwrap(), 3);
- assert!(m.insert(9, 4));
- assert_eq!(*m.find(&1).unwrap(), 2);
- assert_eq!(*m.find(&5).unwrap(), 3);
- assert_eq!(*m.find(&9).unwrap(), 4);
- assert!(m.remove(&1));
- assert_eq!(*m.find(&9).unwrap(), 4);
- assert_eq!(*m.find(&5).unwrap(), 3);
- }
-
- #[test]
- fn test_is_empty() {
- let mut m = HashMap::with_capacity(4);
- assert!(m.insert(1, 2));
- assert!(!m.is_empty());
- assert!(m.remove(&1));
- assert!(m.is_empty());
- }
-
- #[test]
- fn test_pop() {
- let mut m = HashMap::new();
- m.insert(1, 2);
- assert_eq!(m.pop(&1), Some(2));
- assert_eq!(m.pop(&1), None);
- }
-
- #[test]
- #[allow(experimental)]
- fn test_pop_equiv() {
- let mut m = HashMap::new();
- m.insert(1, 2);
- assert_eq!(m.pop_equiv(&KindaIntLike(1)), Some(2));
- assert_eq!(m.pop_equiv(&KindaIntLike(1)), None);
- }
-
- #[test]
- fn test_swap() {
- let mut m = HashMap::new();
- assert_eq!(m.swap(1, 2), None);
- assert_eq!(m.swap(1, 3), Some(2));
- assert_eq!(m.swap(1, 4), Some(3));
- }
-
- #[test]
- fn test_move_iter() {
- let hm = {
- let mut hm = HashMap::new();
-
- hm.insert('a', 1);
- hm.insert('b', 2);
-
- hm
- };
-
- let v = hm.move_iter().collect::<Vec<(char, int)>>();
- assert!([('a', 1), ('b', 2)] == v.as_slice() || [('b', 2), ('a', 1)] == v.as_slice());
- }
-
- #[test]
- fn test_iterate() {
- let mut m = HashMap::with_capacity(4);
- for i in range(0u, 32) {
- assert!(m.insert(i, i*2));
- }
- assert_eq!(m.len(), 32);
-
- let mut observed: u32 = 0;
-
- for (k, v) in m.iter() {
- assert_eq!(*v, *k * 2);
- observed |= 1 << *k;
- }
- assert_eq!(observed, 0xFFFF_FFFF);
- }
-
- #[test]
- fn test_keys() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map = vec.move_iter().collect::<HashMap<int, char>>();
- let keys = map.keys().map(|&k| k).collect::<Vec<int>>();
- assert_eq!(keys.len(), 3);
- assert!(keys.contains(&1));
- assert!(keys.contains(&2));
- assert!(keys.contains(&3));
- }
-
- #[test]
- fn test_values() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map = vec.move_iter().collect::<HashMap<int, char>>();
- let values = map.values().map(|&v| v).collect::<Vec<char>>();
- assert_eq!(values.len(), 3);
- assert!(values.contains(&'a'));
- assert!(values.contains(&'b'));
- assert!(values.contains(&'c'));
- }
-
- #[test]
- fn test_find() {
- let mut m = HashMap::new();
- assert!(m.find(&1).is_none());
- m.insert(1, 2);
- match m.find(&1) {
- None => fail!(),
- Some(v) => assert_eq!(*v, 2)
- }
- }
-
- #[test]
- fn test_eq() {
- let mut m1 = HashMap::new();
- m1.insert(1, 2);
- m1.insert(2, 3);
- m1.insert(3, 4);
-
- let mut m2 = HashMap::new();
- m2.insert(1, 2);
- m2.insert(2, 3);
-
- assert!(m1 != m2);
-
- m2.insert(3, 4);
-
- assert_eq!(m1, m2);
- }
-
- #[test]
- fn test_show() {
- let mut map: HashMap<int, int> = HashMap::new();
- let empty: HashMap<int, int> = HashMap::new();
-
- map.insert(1, 2);
- map.insert(3, 4);
-
- let map_str = format!("{}", map);
-
- assert!(map_str == "{1: 2, 3: 4}".to_string() || map_str == "{3: 4, 1: 2}".to_string());
- assert_eq!(format!("{}", empty), "{}".to_string());
- }
-
- #[test]
- fn test_expand() {
- let mut m = HashMap::new();
-
- assert_eq!(m.len(), 0);
- assert!(m.is_empty());
-
- let mut i = 0u;
- let old_cap = m.table.capacity();
- while old_cap == m.table.capacity() {
- m.insert(i, i);
- i += 1;
- }
-
- assert_eq!(m.len(), i);
- assert!(!m.is_empty());
- }
-
- #[test]
- fn test_resize_policy() {
- let mut m = HashMap::new();
-
- assert_eq!(m.len(), 0);
- assert!(m.is_empty());
-
- let initial_cap = m.table.capacity();
- m.reserve(initial_cap * 2);
- let cap = m.table.capacity();
-
- assert_eq!(cap, initial_cap * 2);
-
- let mut i = 0u;
- for _ in range(0, cap * 3 / 4) {
- m.insert(i, i);
- i += 1;
- }
-
- assert_eq!(m.len(), i);
- assert_eq!(m.table.capacity(), cap);
-
- for _ in range(0, cap / 4) {
- m.insert(i, i);
- i += 1;
- }
-
- let new_cap = m.table.capacity();
- assert_eq!(new_cap, cap * 2);
-
- for _ in range(0, cap / 2) {
- i -= 1;
- m.remove(&i);
- assert_eq!(m.table.capacity(), new_cap);
- }
-
- for _ in range(0, cap / 2 - 1) {
- i -= 1;
- m.remove(&i);
- }
-
- assert_eq!(m.table.capacity(), cap);
- assert_eq!(m.len(), i);
- assert!(!m.is_empty());
- }
-
- #[test]
- fn test_find_equiv() {
- let mut m = HashMap::new();
-
- let (foo, bar, baz) = (1,2,3);
- m.insert("foo".to_string(), foo);
- m.insert("bar".to_string(), bar);
- m.insert("baz".to_string(), baz);
-
-
- assert_eq!(m.find_equiv(&("foo")), Some(&foo));
- assert_eq!(m.find_equiv(&("bar")), Some(&bar));
- assert_eq!(m.find_equiv(&("baz")), Some(&baz));
-
- assert_eq!(m.find_equiv(&("qux")), None);
- }
-
- #[test]
- fn test_from_iter() {
- let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
- let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
-
- for &(k, v) in xs.iter() {
- assert_eq!(map.find(&k), Some(&v));
- }
- }
-
- #[test]
- fn test_size_hint() {
- let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
- let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
-
- let mut iter = map.iter();
-
- for _ in iter.by_ref().take(3) {}
-
- assert_eq!(iter.size_hint(), (3, Some(3)));
- }
-
- #[test]
- fn test_mut_size_hint() {
- let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
- let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
-
- let mut iter = map.mut_iter();
-
- for _ in iter.by_ref().take(3) {}
-
- assert_eq!(iter.size_hint(), (3, Some(3)));
- }
-}
-
-#[cfg(test)]
-mod test_set {
- use super::HashSet;
- use std::container::Container;
- use std::slice::ImmutableEqVector;
-
- #[test]
- fn test_disjoint() {
- let mut xs = HashSet::new();
- let mut ys = HashSet::new();
- assert!(xs.is_disjoint(&ys));
- assert!(ys.is_disjoint(&xs));
- assert!(xs.insert(5));
- assert!(ys.insert(11));
- assert!(xs.is_disjoint(&ys));
- assert!(ys.is_disjoint(&xs));
- assert!(xs.insert(7));
- assert!(xs.insert(19));
- assert!(xs.insert(4));
- assert!(ys.insert(2));
- assert!(ys.insert(-11));
- assert!(xs.is_disjoint(&ys));
- assert!(ys.is_disjoint(&xs));
- assert!(ys.insert(7));
- assert!(!xs.is_disjoint(&ys));
- assert!(!ys.is_disjoint(&xs));
- }
-
- #[test]
- fn test_subset_and_superset() {
- let mut a = HashSet::new();
- assert!(a.insert(0));
- assert!(a.insert(5));
- assert!(a.insert(11));
- assert!(a.insert(7));
-
- let mut b = HashSet::new();
- assert!(b.insert(0));
- assert!(b.insert(7));
- assert!(b.insert(19));
- assert!(b.insert(250));
- assert!(b.insert(11));
- assert!(b.insert(200));
-
- assert!(!a.is_subset(&b));
- assert!(!a.is_superset(&b));
- assert!(!b.is_subset(&a));
- assert!(!b.is_superset(&a));
-
- assert!(b.insert(5));
-
- assert!(a.is_subset(&b));
- assert!(!a.is_superset(&b));
- assert!(!b.is_subset(&a));
- assert!(b.is_superset(&a));
- }
-
- #[test]
- fn test_iterate() {
- let mut a = HashSet::new();
- for i in range(0u, 32) {
- assert!(a.insert(i));
- }
- let mut observed: u32 = 0;
- for k in a.iter() {
- observed |= 1 << *k;
- }
- assert_eq!(observed, 0xFFFF_FFFF);
- }
-
- #[test]
- fn test_intersection() {
- let mut a = HashSet::new();
- let mut b = HashSet::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!(a.insert(-5));
-
- assert!(b.insert(2));
- assert!(b.insert(11));
- assert!(b.insert(77));
- assert!(b.insert(-9));
- assert!(b.insert(-42));
- assert!(b.insert(5));
- assert!(b.insert(3));
-
- let mut i = 0;
- let expected = [3, 5, 11, 77];
- for x in a.intersection(&b) {
- assert!(expected.contains(x));
- i += 1
- }
- assert_eq!(i, expected.len());
- }
-
- #[test]
- fn test_difference() {
- let mut a = HashSet::new();
- let mut b = HashSet::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));
-
- let mut i = 0;
- let expected = [1, 5, 11];
- for x in a.difference(&b) {
- assert!(expected.contains(x));
- i += 1
- }
- assert_eq!(i, expected.len());
- }
-
- #[test]
- fn test_symmetric_difference() {
- let mut a = HashSet::new();
- let mut b = HashSet::new();
-
- assert!(a.insert(1));
- assert!(a.insert(3));
- assert!(a.insert(5));
- assert!(a.insert(9));
- assert!(a.insert(11));
-
- assert!(b.insert(-2));
- assert!(b.insert(3));
- assert!(b.insert(9));
- assert!(b.insert(14));
- assert!(b.insert(22));
-
- let mut i = 0;
- let expected = [-2, 1, 5, 11, 14, 22];
- for x in a.symmetric_difference(&b) {
- assert!(expected.contains(x));
- i += 1
- }
- assert_eq!(i, expected.len());
- }
-
- #[test]
- fn test_union() {
- let mut a = HashSet::new();
- let mut b = HashSet::new();
-
- assert!(a.insert(1));
- assert!(a.insert(3));
- assert!(a.insert(5));
- assert!(a.insert(9));
- assert!(a.insert(11));
- assert!(a.insert(16));
- assert!(a.insert(19));
- assert!(a.insert(24));
-
- assert!(b.insert(-2));
- assert!(b.insert(1));
- assert!(b.insert(5));
- assert!(b.insert(9));
- assert!(b.insert(13));
- assert!(b.insert(19));
-
- let mut i = 0;
- let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
- for x in a.union(&b) {
- assert!(expected.contains(x));
- i += 1
- }
- assert_eq!(i, expected.len());
- }
-
- #[test]
- fn test_from_iter() {
- let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
- let set: HashSet<int> = xs.iter().map(|&x| x).collect();
-
- for x in xs.iter() {
- assert!(set.contains(x));
- }
- }
-
- #[test]
- fn test_move_iter() {
- let hs = {
- let mut hs = HashSet::new();
-
- hs.insert('a');
- hs.insert('b');
-
- hs
- };
-
- let v = hs.move_iter().collect::<Vec<char>>();
- assert!(['a', 'b'] == v.as_slice() || ['b', 'a'] == v.as_slice());
- }
-
- #[test]
- fn test_eq() {
- // These constants once happened to expose a bug in insert().
- // I'm keeping them around to prevent a regression.
- let mut s1 = HashSet::new();
-
- s1.insert(1);
- s1.insert(2);
- s1.insert(3);
-
- let mut s2 = HashSet::new();
-
- s2.insert(1);
- s2.insert(2);
-
- assert!(s1 != s2);
-
- s2.insert(3);
-
- assert_eq!(s1, s2);
- }
-
- #[test]
- fn test_show() {
- let mut set: HashSet<int> = HashSet::new();
- let empty: HashSet<int> = HashSet::new();
-
- set.insert(1);
- set.insert(2);
-
- let set_str = format!("{}", set);
-
- assert!(set_str == "{1, 2}".to_string() || set_str == "{2, 1}".to_string());
- assert_eq!(format!("{}", empty), "{}".to_string());
- }
-}
-
-#[cfg(test)]
-mod bench {
- extern crate test;
- use self::test::Bencher;
- use std::iter::{range_inclusive};
-
- #[bench]
- fn new_drop(b : &mut Bencher) {
- use super::HashMap;
-
- b.iter(|| {
- let m : HashMap<int, int> = HashMap::new();
- assert_eq!(m.len(), 0);
- })
- }
-
- #[bench]
- fn new_insert_drop(b : &mut Bencher) {
- use super::HashMap;
-
- b.iter(|| {
- let mut m = HashMap::new();
- m.insert(0, 0);
- assert_eq!(m.len(), 1);
- })
- }
-
- #[bench]
- fn insert(b: &mut Bencher) {
- use super::HashMap;
-
- let mut m = HashMap::new();
-
- for i in range_inclusive(1, 1000) {
- m.insert(i, i);
- }
-
- let mut k = 1001;
-
- b.iter(|| {
- m.insert(k, k);
- k += 1;
- });
- }
-
- #[bench]
- fn find_existing(b: &mut Bencher) {
- use super::HashMap;
-
- let mut m = HashMap::new();
-
- for i in range_inclusive(1, 1000) {
- m.insert(i, i);
- }
-
- b.iter(|| {
- for i in range_inclusive(1, 1000) {
- m.contains_key(&i);
- }
- });
- }
-
- #[bench]
- fn find_nonexisting(b: &mut Bencher) {
- use super::HashMap;
-
- let mut m = HashMap::new();
-
- for i in range_inclusive(1, 1000) {
- m.insert(i, i);
- }
-
- b.iter(|| {
- for i in range_inclusive(1001, 2000) {
- m.contains_key(&i);
- }
- });
- }
-
- #[bench]
- fn hashmap_as_queue(b: &mut Bencher) {
- use super::HashMap;
-
- let mut m = HashMap::new();
-
- for i in range_inclusive(1, 1000) {
- m.insert(i, i);
- }
-
- let mut k = 1;
-
- b.iter(|| {
- m.pop(&k);
- m.insert(k + 1000, k + 1000);
- k += 1;
- });
- }
-
- #[bench]
- fn find_pop_insert(b: &mut Bencher) {
- use super::HashMap;
-
- let mut m = HashMap::new();
-
- for i in range_inclusive(1, 1000) {
- m.insert(i, i);
- }
-
- let mut k = 1;
-
- b.iter(|| {
- m.find(&(k + 400));
- m.find(&(k + 2000));
- m.pop(&k);
- m.insert(k + 1000, k + 1000);
- k += 1;
- })
- }
-}
#![crate_id = "collections#0.11.0-pre"]
#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
-#![feature(macro_rules, managed_boxes, default_type_params, phase)]
+#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
+#![no_std]
-#![deny(deprecated_owned_vector)]
-
-extern crate debug;
+#[phase(syntax, link)] extern crate core;
+extern crate alloc;
+#[cfg(test)] extern crate native;
+#[cfg(test)] extern crate std;
#[cfg(test)] extern crate test;
#[cfg(test)] #[phase(syntax, link)] extern crate log;
-pub use bitv::Bitv;
+pub use bitv::{Bitv, BitvSet};
pub use btree::BTree;
pub use deque::Deque;
pub use dlist::DList;
pub use enum_set::EnumSet;
-pub use hashmap::{HashMap, HashSet};
-pub use lru_cache::LruCache;
pub use priority_queue::PriorityQueue;
pub use ringbuf::RingBuf;
pub use smallintmap::SmallIntMap;
pub use treemap::{TreeMap, TreeSet};
pub use trie::{TrieMap, TrieSet};
+mod macros;
+
pub mod bitv;
pub mod btree;
pub mod deque;
pub mod dlist;
pub mod enum_set;
-pub mod hashmap;
-pub mod lru_cache;
pub mod priority_queue;
pub mod ringbuf;
pub mod smallintmap;
pub mod treemap;
pub mod trie;
+pub mod slice;
+pub mod str;
+pub mod string;
+pub mod vec;
+pub mod hash;
+
+// Internal unicode fiddly bits for the str module
+mod unicode;
+
+// FIXME(#14008) should this actually exist, or should a method be added?
+fn expect<T>(a: core::option::Option<T>, b: &str) -> T {
+ match a {
+ core::option::Some(a) => a,
+ core::option::None => fail!(b),
+ }
+}
+
+mod std {
+ pub use core::fmt; // necessary for fail!()
+ pub use core::option; // necessary for fail!()
+ pub use core::clone; // deriving(Clone)
+ pub use core::cmp; // deriving(Eq, Ord, etc.)
+ pub use hash; // deriving(Hash)
+}
+++ /dev/null
-// Copyright 2013 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.
-
-
-//! A cache that holds a limited number of key-value pairs. When the
-//! capacity of the cache is exceeded, the least-recently-used
-//! (where "used" means a look-up or putting the pair into the cache)
-//! pair is automatically removed.
-//!
-//! # Example
-//!
-//! ```rust
-//! use collections::LruCache;
-//!
-//! let mut cache: LruCache<int, int> = LruCache::new(2);
-//! cache.put(1, 10);
-//! cache.put(2, 20);
-//! cache.put(3, 30);
-//! assert!(cache.get(&1).is_none());
-//! assert_eq!(*cache.get(&2).unwrap(), 20);
-//! assert_eq!(*cache.get(&3).unwrap(), 30);
-//!
-//! cache.put(2, 22);
-//! assert_eq!(*cache.get(&2).unwrap(), 22);
-//!
-//! cache.put(6, 60);
-//! assert!(cache.get(&3).is_none());
-//!
-//! cache.change_capacity(1);
-//! assert!(cache.get(&2).is_none());
-//! ```
-
-use std::container::Container;
-use std::hash::Hash;
-use std::fmt;
-use std::mem;
-use std::ptr;
-
-use HashMap;
-
-struct KeyRef<K> { k: *K }
-
-struct LruEntry<K, V> {
- next: *mut LruEntry<K, V>,
- prev: *mut LruEntry<K, V>,
- key: K,
- value: V,
-}
-
-/// An LRU Cache.
-pub struct LruCache<K, V> {
- map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>>,
- max_size: uint,
- head: *mut LruEntry<K, V>,
-}
-
-impl<S, K: Hash<S>> Hash<S> for KeyRef<K> {
- fn hash(&self, state: &mut S) {
- unsafe { (*self.k).hash(state) }
- }
-}
-
-impl<K: PartialEq> PartialEq for KeyRef<K> {
- fn eq(&self, other: &KeyRef<K>) -> bool {
- unsafe{ (*self.k).eq(&*other.k) }
- }
-}
-
-impl<K: Eq> Eq for KeyRef<K> {}
-
-impl<K, V> LruEntry<K, V> {
- fn new(k: K, v: V) -> LruEntry<K, V> {
- LruEntry {
- key: k,
- value: v,
- next: ptr::mut_null(),
- prev: ptr::mut_null(),
- }
- }
-}
-
-impl<K: Hash + Eq, V> LruCache<K, V> {
- /// Create an LRU Cache that holds at most `capacity` items.
- pub fn new(capacity: uint) -> LruCache<K, V> {
- let cache = LruCache {
- map: HashMap::new(),
- max_size: capacity,
- head: unsafe{ mem::transmute(box mem::uninitialized::<LruEntry<K, V>>()) },
- };
- unsafe {
- (*cache.head).next = cache.head;
- (*cache.head).prev = cache.head;
- }
- return cache;
- }
-
- /// Put a key-value pair into cache.
- pub fn put(&mut self, k: K, v: V) {
- let (node_ptr, node_opt) = match self.map.find_mut(&KeyRef{k: &k}) {
- Some(node) => {
- node.value = v;
- let node_ptr: *mut LruEntry<K, V> = &mut **node;
- (node_ptr, None)
- }
- None => {
- let mut node = box LruEntry::new(k, v);
- let node_ptr: *mut LruEntry<K, V> = &mut *node;
- (node_ptr, Some(node))
- }
- };
- match node_opt {
- None => {
- // Existing node, just update LRU position
- self.detach(node_ptr);
- self.attach(node_ptr);
- }
- Some(node) => {
- let keyref = unsafe { &(*node_ptr).key };
- self.map.swap(KeyRef{k: keyref}, node);
- self.attach(node_ptr);
- if self.len() > self.capacity() {
- self.remove_lru();
- }
- }
- }
- }
-
- /// Return a value corresponding to the key in the cache.
- pub fn get<'a>(&'a mut self, k: &K) -> Option<&'a V> {
- let (value, node_ptr_opt) = match self.map.find_mut(&KeyRef{k: k}) {
- None => (None, None),
- Some(node) => {
- let node_ptr: *mut LruEntry<K, V> = &mut **node;
- (Some(unsafe { &(*node_ptr).value }), Some(node_ptr))
- }
- };
- match node_ptr_opt {
- None => (),
- Some(node_ptr) => {
- self.detach(node_ptr);
- self.attach(node_ptr);
- }
- }
- return value;
- }
-
- /// Remove and return a value corresponding to the key from the cache.
- pub fn pop(&mut self, k: &K) -> Option<V> {
- match self.map.pop(&KeyRef{k: k}) {
- None => None,
- Some(lru_entry) => Some(lru_entry.value)
- }
- }
-
- /// Return the maximum number of key-value pairs the cache can hold.
- pub fn capacity(&self) -> uint {
- self.max_size
- }
-
- /// Change the number of key-value pairs the cache can hold. Remove
- /// least-recently-used key-value pairs if necessary.
- pub fn change_capacity(&mut self, capacity: uint) {
- for _ in range(capacity, self.len()) {
- self.remove_lru();
- }
- self.max_size = capacity;
- }
-
- #[inline]
- fn remove_lru(&mut self) {
- if self.len() > 0 {
- let lru = unsafe { (*self.head).prev };
- self.detach(lru);
- self.map.pop(&KeyRef{k: unsafe { &(*lru).key }});
- }
- }
-
- #[inline]
- fn detach(&mut self, node: *mut LruEntry<K, V>) {
- unsafe {
- (*(*node).prev).next = (*node).next;
- (*(*node).next).prev = (*node).prev;
- }
- }
-
- #[inline]
- fn attach(&mut self, node: *mut LruEntry<K, V>) {
- unsafe {
- (*node).next = (*self.head).next;
- (*node).prev = self.head;
- (*self.head).next = node;
- (*(*node).next).prev = node;
- }
- }
-}
-
-impl<A: fmt::Show + Hash + Eq, B: fmt::Show> fmt::Show for LruCache<A, B> {
- /// Return a string that lists the key-value pairs from most-recently
- /// used to least-recently used.
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, r"\{"));
- let mut cur = self.head;
- for i in range(0, self.len()) {
- if i > 0 { try!(write!(f, ", ")) }
- unsafe {
- cur = (*cur).next;
- try!(write!(f, "{}", (*cur).key));
- }
- try!(write!(f, ": "));
- unsafe {
- try!(write!(f, "{}", (*cur).value));
- }
- }
- write!(f, r"\}")
- }
-}
-
-impl<K: Hash + Eq, V> Container for LruCache<K, V> {
- /// Return the number of key-value pairs in the cache.
- fn len(&self) -> uint {
- self.map.len()
- }
-}
-
-impl<K: Hash + Eq, V> Mutable for LruCache<K, V> {
- /// Clear the cache of all key-value pairs.
- fn clear(&mut self) {
- self.map.clear();
- }
-}
-
-#[unsafe_destructor]
-impl<K, V> Drop for LruCache<K, V> {
- fn drop(&mut self) {
- unsafe {
- let node: Box<LruEntry<K, V>> = mem::transmute(self.head);
- // Prevent compiler from trying to drop the un-initialized field in the sigil node.
- let box LruEntry { key: k, value: v, .. } = node;
- mem::forget(k);
- mem::forget(v);
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::LruCache;
-
- fn assert_opt_eq<V: PartialEq>(opt: Option<&V>, v: V) {
- assert!(opt.is_some());
- assert!(opt.unwrap() == &v);
- }
-
- #[test]
- fn test_put_and_get() {
- let mut cache: LruCache<int, int> = LruCache::new(2);
- cache.put(1, 10);
- cache.put(2, 20);
- assert_opt_eq(cache.get(&1), 10);
- assert_opt_eq(cache.get(&2), 20);
- assert_eq!(cache.len(), 2);
- }
-
- #[test]
- fn test_put_update() {
- let mut cache: LruCache<String, Vec<u8>> = LruCache::new(1);
- cache.put("1".to_string(), vec![10, 10]);
- cache.put("1".to_string(), vec![10, 19]);
- assert_opt_eq(cache.get(&"1".to_string()), vec![10, 19]);
- assert_eq!(cache.len(), 1);
- }
-
- #[test]
- fn test_expire_lru() {
- let mut cache: LruCache<String, String> = LruCache::new(2);
- cache.put("foo1".to_string(), "bar1".to_string());
- cache.put("foo2".to_string(), "bar2".to_string());
- cache.put("foo3".to_string(), "bar3".to_string());
- assert!(cache.get(&"foo1".to_string()).is_none());
- cache.put("foo2".to_string(), "bar2update".to_string());
- cache.put("foo4".to_string(), "bar4".to_string());
- assert!(cache.get(&"foo3".to_string()).is_none());
- }
-
- #[test]
- fn test_pop() {
- let mut cache: LruCache<int, int> = LruCache::new(2);
- cache.put(1, 10);
- cache.put(2, 20);
- assert_eq!(cache.len(), 2);
- let opt1 = cache.pop(&1);
- assert!(opt1.is_some());
- assert_eq!(opt1.unwrap(), 10);
- assert!(cache.get(&1).is_none());
- assert_eq!(cache.len(), 1);
- }
-
- #[test]
- fn test_change_capacity() {
- let mut cache: LruCache<int, int> = LruCache::new(2);
- assert_eq!(cache.capacity(), 2);
- cache.put(1, 10);
- cache.put(2, 20);
- cache.change_capacity(1);
- assert!(cache.get(&1).is_none());
- assert_eq!(cache.capacity(), 1);
- }
-
- #[test]
- fn test_to_str() {
- let mut cache: LruCache<int, int> = LruCache::new(3);
- cache.put(1, 10);
- cache.put(2, 20);
- cache.put(3, 30);
- assert_eq!(cache.to_str(), "{3: 30, 2: 20, 1: 10}".to_string());
- cache.put(2, 22);
- assert_eq!(cache.to_str(), "{2: 22, 3: 30, 1: 10}".to_string());
- cache.put(6, 60);
- assert_eq!(cache.to_str(), "{6: 60, 2: 22, 3: 30}".to_string());
- cache.get(&3);
- assert_eq!(cache.to_str(), "{3: 30, 6: 60, 2: 22}".to_string());
- cache.change_capacity(2);
- assert_eq!(cache.to_str(), "{3: 30, 6: 60}".to_string());
- }
-
- #[test]
- fn test_clear() {
- let mut cache: LruCache<int, int> = LruCache::new(2);
- cache.put(1, 10);
- cache.put(2, 20);
- cache.clear();
- assert!(cache.get(&1).is_none());
- assert!(cache.get(&2).is_none());
- assert_eq!(cache.to_str(), "{}".to_string());
- }
-}
--- /dev/null
+// 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.
+
+#![macro_escape]
+
+/// Create a `std::vec::Vec` containing the arguments.
+macro_rules! vec(
+ ($($e:expr),*) => ({
+ // leading _ to allow empty construction without a warning.
+ let mut _temp = ::vec::Vec::new();
+ $(_temp.push($e);)*
+ _temp
+ });
+ ($($e:expr),+,) => (vec!($($e),+))
+)
#![allow(missing_doc)]
-use std::clone::Clone;
-use std::mem::{zeroed, replace, swap};
-use std::ptr;
-use std::slice;
+use core::prelude::*;
+
+use core::mem::{overwrite, zeroed, replace, swap};
+
+use slice;
+use vec::Vec;
/// A priority queue implemented with a binary heap
#[deriving(Clone)]
//! RingBuf implements the trait Deque. It should be imported with `use
//! collections::deque::Deque`.
-use std::cmp;
-use std::fmt;
-use std::fmt::Show;
-use std::iter::RandomAccessIterator;
+use core::prelude::*;
+
+use core::cmp;
+use core::fmt;
+use core::iter::RandomAccessIterator;
use deque::Deque;
+use vec::Vec;
static INITIAL_CAPACITY: uint = 8u; // 2^3
static MINIMUM_CAPACITY: uint = 2u;
}
}
-impl<T: Show> Show for RingBuf<T> {
+impl<T: fmt::Show> fmt::Show for RingBuf<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "["));
--- /dev/null
+// 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.
+
+/*!
+
+Utilities for vector manipulation
+
+The `vec` module contains useful code to help work with vector values.
+Vectors are Rust's list type. Vectors contain zero or more values of
+homogeneous types:
+
+```rust
+let int_vector = [1,2,3];
+let str_vector = ["one", "two", "three"];
+```
+
+This is a big module, but for a high-level overview:
+
+## Structs
+
+Several structs that are useful for vectors, such as `Items`, which
+represents iteration over a vector.
+
+## Traits
+
+A number of traits add methods that allow you to accomplish tasks with vectors.
+
+Traits defined for the `&[T]` type (a vector slice), have methods that can be
+called on either owned vectors, denoted `~[T]`, or on vector slices themselves.
+These traits include `ImmutableVector`, and `MutableVector` for the `&mut [T]`
+case.
+
+An example is the method `.slice(a, b)` that returns an immutable "view" into
+a vector or a vector slice from the index interval `[a, b)`:
+
+```rust
+let numbers = [0, 1, 2];
+let last_numbers = numbers.slice(1, 3);
+// last_numbers is now &[1, 2]
+```
+
+Traits defined for the `~[T]` type, like `OwnedVector`, can only be called
+on such vectors. These methods deal with adding elements or otherwise changing
+the allocation of the vector.
+
+An example is the method `.push(element)` that will add an element at the end
+of the vector:
+
+```rust
+let mut numbers = vec![0, 1, 2];
+numbers.push(7);
+// numbers is now vec![0, 1, 2, 7];
+```
+
+## Implementations of other traits
+
+Vectors are a very useful type, and so there's several implementations of
+traits from other modules. Some notable examples:
+
+* `Clone`
+* `Eq`, `Ord`, `Eq`, `Ord` -- vectors can be compared,
+ if the element type defines the corresponding trait.
+
+## Iteration
+
+The method `iter()` returns an iteration value for a vector or a vector slice.
+The iterator yields references to the vector's elements, so if the element
+type of the vector is `int`, the element type of the iterator is `&int`.
+
+```rust
+let numbers = [0, 1, 2];
+for &x in numbers.iter() {
+ println!("{} is a number!", x);
+}
+```
+
+* `.mut_iter()` returns an iterator that allows modifying each value.
+* `.move_iter()` converts an owned vector into an iterator that
+ moves out a value from the vector each iteration.
+* Further iterators exist that split, chunk or permute the vector.
+
+## Function definitions
+
+There are a number of free functions that create or take vectors, for example:
+
+* Creating a vector, like `from_elem` and `from_fn`
+* Creating a vector with a given size: `with_capacity`
+* Modifying a vector and returning it, like `append`
+* Operations on paired elements, like `unzip`.
+
+*/
+
+#![doc(primitive = "slice")]
+
+use core::prelude::*;
+
+use alloc::heap::{allocate, deallocate};
+use core::cmp;
+use core::finally::try_finally;
+use core::mem::size_of;
+use core::mem::transmute;
+use core::mem;
+use core::ptr;
+use core::iter::{range_step, MultiplicativeIterator};
+use vec::Vec;
+
+pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
+pub use core::slice::{Chunks, Vector, ImmutableVector, ImmutableEqVector};
+pub use core::slice::{ImmutableOrdVector, MutableVector, Items, MutItems};
+pub use core::slice::{MutSplits, MutChunks};
+pub use core::slice::{bytes, MutableCloneableVector};
+
+// Functional utilities
+
+#[allow(missing_doc)]
+pub trait VectorVector<T> {
+ // FIXME #5898: calling these .concat and .connect conflicts with
+ // StrVector::con{cat,nect}, since they have generic contents.
+ /// Flattens a vector of vectors of T into a single vector of T.
+ fn concat_vec(&self) -> Vec<T>;
+
+ /// Concatenate a vector of vectors, placing a given separator between each.
+ fn connect_vec(&self, sep: &T) -> Vec<T>;
+}
+
+impl<'a, T: Clone, V: Vector<T>> VectorVector<T> for &'a [V] {
+ fn concat_vec(&self) -> Vec<T> {
+ let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
+ let mut result = Vec::with_capacity(size);
+ for v in self.iter() {
+ result.push_all(v.as_slice())
+ }
+ result
+ }
+
+ fn connect_vec(&self, sep: &T) -> Vec<T> {
+ let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
+ let mut result = Vec::with_capacity(size + self.len());
+ let mut first = true;
+ for v in self.iter() {
+ if first { first = false } else { result.push(sep.clone()) }
+ result.push_all(v.as_slice())
+ }
+ result
+ }
+}
+
+/// An Iterator that yields the element swaps needed to produce
+/// a sequence of all possible permutations for an indexed sequence of
+/// elements. Each permutation is only a single swap apart.
+///
+/// The Steinhaus–Johnson–Trotter algorithm is used.
+///
+/// Generates even and odd permutations alternately.
+///
+/// The last generated swap is always (0, 1), and it returns the
+/// sequence to its initial order.
+pub struct ElementSwaps {
+ sdir: Vec<SizeDirection>,
+ /// If true, emit the last swap that returns the sequence to initial state
+ emit_reset: bool,
+ swaps_made : uint,
+}
+
+impl ElementSwaps {
+ /// Create an `ElementSwaps` iterator for a sequence of `length` elements
+ pub fn new(length: uint) -> ElementSwaps {
+ // Initialize `sdir` with a direction that position should move in
+ // (all negative at the beginning) and the `size` of the
+ // element (equal to the original index).
+ ElementSwaps{
+ emit_reset: true,
+ sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(),
+ swaps_made: 0
+ }
+ }
+}
+
+enum Direction { Pos, Neg }
+
+/// An Index and Direction together
+struct SizeDirection {
+ size: uint,
+ dir: Direction,
+}
+
+impl Iterator<(uint, uint)> for ElementSwaps {
+ #[inline]
+ fn next(&mut self) -> Option<(uint, uint)> {
+ fn new_pos(i: uint, s: Direction) -> uint {
+ i + match s { Pos => 1, Neg => -1 }
+ }
+
+ // Find the index of the largest mobile element:
+ // The direction should point into the vector, and the
+ // swap should be with a smaller `size` element.
+ let max = self.sdir.iter().map(|&x| x).enumerate()
+ .filter(|&(i, sd)|
+ new_pos(i, sd.dir) < self.sdir.len() &&
+ self.sdir.get(new_pos(i, sd.dir)).size < sd.size)
+ .max_by(|&(_, sd)| sd.size);
+ match max {
+ Some((i, sd)) => {
+ let j = new_pos(i, sd.dir);
+ self.sdir.as_mut_slice().swap(i, j);
+
+ // Swap the direction of each larger SizeDirection
+ for x in self.sdir.mut_iter() {
+ if x.size > sd.size {
+ x.dir = match x.dir { Pos => Neg, Neg => Pos };
+ }
+ }
+ self.swaps_made += 1;
+ Some((i, j))
+ },
+ None => if self.emit_reset {
+ self.emit_reset = false;
+ if self.sdir.len() > 1 {
+ // The last swap
+ self.swaps_made += 1;
+ Some((0, 1))
+ } else {
+ // Vector is of the form [] or [x], and the only permutation is itself
+ self.swaps_made += 1;
+ Some((0,0))
+ }
+ } else { None }
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ // For a vector of size n, there are exactly n! permutations.
+ let n = range(2, self.sdir.len() + 1).product();
+ (n - self.swaps_made, Some(n - self.swaps_made))
+ }
+}
+
+/// An Iterator that uses `ElementSwaps` to iterate through
+/// all possible permutations of a vector.
+///
+/// The first iteration yields a clone of the vector as it is,
+/// then each successive element is the vector with one
+/// swap applied.
+///
+/// Generates even and odd permutations alternately.
+pub struct Permutations<T> {
+ swaps: ElementSwaps,
+ v: ~[T],
+}
+
+impl<T: Clone> Iterator<~[T]> for Permutations<T> {
+ #[inline]
+ fn next(&mut self) -> Option<~[T]> {
+ match self.swaps.next() {
+ None => None,
+ Some((0,0)) => Some(self.v.clone()),
+ Some((a, b)) => {
+ let elt = self.v.clone();
+ self.v.swap(a, b);
+ Some(elt)
+ }
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ self.swaps.size_hint()
+ }
+}
+
+/// Extension methods for vector slices with cloneable elements
+pub trait CloneableVector<T> {
+ /// Copy `self` into a new owned vector
+ fn to_owned(&self) -> ~[T];
+
+ /// Convert `self` into an owned vector, not making a copy if possible.
+ fn into_owned(self) -> ~[T];
+}
+
+/// Extension methods for vector slices
+impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
+ /// Returns a copy of `v`.
+ #[inline]
+ fn to_owned(&self) -> ~[T] {
+ use RawVec = core::raw::Vec;
+ use core::num::{CheckedAdd, CheckedMul};
+
+ let len = self.len();
+ let data_size = len.checked_mul(&mem::size_of::<T>());
+ let data_size = ::expect(data_size, "overflow in to_owned()");
+ let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
+ let size = ::expect(size, "overflow in to_owned()");
+
+ unsafe {
+ // this should pass the real required alignment
+ let ret = allocate(size, 8) as *mut RawVec<()>;
+
+ let a_size = mem::size_of::<T>();
+ let a_size = if a_size == 0 {1} else {a_size};
+ (*ret).fill = len * a_size;
+ (*ret).alloc = len * a_size;
+
+ // Be careful with the following loop. We want it to be optimized
+ // to a memcpy (or something similarly fast) when T is Copy. LLVM
+ // is easily confused, so any extra operations during the loop can
+ // prevent this optimization.
+ let mut i = 0;
+ let p = &mut (*ret).data as *mut _ as *mut T;
+ try_finally(
+ &mut i, (),
+ |i, ()| while *i < len {
+ mem::overwrite(
+ &mut(*p.offset(*i as int)),
+ self.unsafe_ref(*i).clone());
+ *i += 1;
+ },
+ |i| if *i < len {
+ // we must be failing, clean up after ourselves
+ for j in range(0, *i as int) {
+ ptr::read(&*p.offset(j));
+ }
+ // FIXME: #13994 (should pass align and size here)
+ deallocate(ret as *mut u8, 0, 8);
+ });
+ mem::transmute(ret)
+ }
+ }
+
+ #[inline(always)]
+ fn into_owned(self) -> ~[T] { self.to_owned() }
+}
+
+/// Extension methods for owned vectors
+impl<T: Clone> CloneableVector<T> for ~[T] {
+ #[inline]
+ fn to_owned(&self) -> ~[T] { self.clone() }
+
+ #[inline(always)]
+ fn into_owned(self) -> ~[T] { self }
+}
+
+/// Extension methods for vectors containing `Clone` elements.
+pub trait ImmutableCloneableVector<T> {
+ /// Partitions the vector into two vectors `(A,B)`, where all
+ /// elements of `A` satisfy `f` and all elements of `B` do not.
+ fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
+
+ /// Create an iterator that yields every possible permutation of the
+ /// vector in succession.
+ fn permutations(self) -> Permutations<T>;
+}
+
+impl<'a,T:Clone> ImmutableCloneableVector<T> for &'a [T] {
+ #[inline]
+ fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
+ let mut lefts = Vec::new();
+ let mut rights = Vec::new();
+
+ for elt in self.iter() {
+ if f(elt) {
+ lefts.push((*elt).clone());
+ } else {
+ rights.push((*elt).clone());
+ }
+ }
+
+ (lefts, rights)
+ }
+
+ fn permutations(self) -> Permutations<T> {
+ Permutations{
+ swaps: ElementSwaps::new(self.len()),
+ v: self.to_owned(),
+ }
+ }
+
+}
+
+/// Extension methods for owned vectors.
+pub trait OwnedVector<T> {
+ /// Creates a consuming iterator, that is, one that moves each
+ /// value out of the vector (from start to end). The vector cannot
+ /// be used after calling this.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let v = ~["a".to_string(), "b".to_string()];
+ /// for s in v.move_iter() {
+ /// // s has type ~str, not &~str
+ /// println!("{}", s);
+ /// }
+ /// ```
+ fn move_iter(self) -> MoveItems<T>;
+
+ /**
+ * Partitions the vector into two vectors `(A,B)`, where all
+ * elements of `A` satisfy `f` and all elements of `B` do not.
+ */
+ fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
+}
+
+impl<T> OwnedVector<T> for ~[T] {
+ #[inline]
+ fn move_iter(self) -> MoveItems<T> {
+ unsafe {
+ let iter = transmute(self.iter());
+ let ptr = transmute(self);
+ MoveItems { allocation: ptr, iter: iter }
+ }
+ }
+
+ #[inline]
+ fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
+ let mut lefts = Vec::new();
+ let mut rights = Vec::new();
+
+ for elt in self.move_iter() {
+ if f(&elt) {
+ lefts.push(elt);
+ } else {
+ rights.push(elt);
+ }
+ }
+
+ (lefts, rights)
+ }
+}
+
+fn insertion_sort<T>(v: &mut [T], compare: |&T, &T| -> Ordering) {
+ let len = v.len() as int;
+ let buf_v = v.as_mut_ptr();
+
+ // 1 <= i < len;
+ for i in range(1, len) {
+ // j satisfies: 0 <= j <= i;
+ let mut j = i;
+ unsafe {
+ // `i` is in bounds.
+ let read_ptr = buf_v.offset(i) as *T;
+
+ // find where to insert, we need to do strict <,
+ // rather than <=, to maintain stability.
+
+ // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
+ while j > 0 &&
+ compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
+ j -= 1;
+ }
+
+ // shift everything to the right, to make space to
+ // insert this value.
+
+ // j + 1 could be `len` (for the last `i`), but in
+ // that case, `i == j` so we don't copy. The
+ // `.offset(j)` is always in bounds.
+
+ if i != j {
+ let tmp = ptr::read(read_ptr);
+ ptr::copy_memory(buf_v.offset(j + 1),
+ &*buf_v.offset(j),
+ (i - j) as uint);
+ ptr::copy_nonoverlapping_memory(buf_v.offset(j),
+ &tmp as *T,
+ 1);
+ mem::forget(tmp);
+ }
+ }
+ }
+}
+
+fn merge_sort<T>(v: &mut [T], compare: |&T, &T| -> Ordering) {
+ // warning: this wildly uses unsafe.
+ static BASE_INSERTION: uint = 32;
+ static LARGE_INSERTION: uint = 16;
+
+ // FIXME #12092: smaller insertion runs seems to make sorting
+ // vectors of large elements a little faster on some platforms,
+ // but hasn't been tested/tuned extensively
+ let insertion = if size_of::<T>() <= 16 {
+ BASE_INSERTION
+ } else {
+ LARGE_INSERTION
+ };
+
+ let len = v.len();
+
+ // short vectors get sorted in-place via insertion sort to avoid allocations
+ if len <= insertion {
+ insertion_sort(v, compare);
+ return;
+ }
+
+ // allocate some memory to use as scratch memory, we keep the
+ // length 0 so we can keep shallow copies of the contents of `v`
+ // without risking the dtors running on an object twice if
+ // `compare` fails.
+ let mut working_space = Vec::with_capacity(2 * len);
+ // these both are buffers of length `len`.
+ let mut buf_dat = working_space.as_mut_ptr();
+ let mut buf_tmp = unsafe {buf_dat.offset(len as int)};
+
+ // length `len`.
+ let buf_v = v.as_ptr();
+
+ // step 1. sort short runs with insertion sort. This takes the
+ // values from `v` and sorts them into `buf_dat`, leaving that
+ // with sorted runs of length INSERTION.
+
+ // 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) {
+ // start <= i < len;
+ for i in range(start, cmp::min(start + insertion, len)) {
+ // j satisfies: start <= j <= i;
+ let mut j = i as int;
+ unsafe {
+ // `i` is in bounds.
+ let read_ptr = buf_v.offset(i as int);
+
+ // find where to insert, we need to do strict <,
+ // rather than <=, to maintain stability.
+
+ // start <= j - 1 < len, so .offset(j - 1) is in
+ // bounds.
+ while j > start as int &&
+ compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less {
+ j -= 1;
+ }
+
+ // shift everything to the right, to make space to
+ // insert this value.
+
+ // j + 1 could be `len` (for the last `i`), but in
+ // that case, `i == j` so we don't copy. The
+ // `.offset(j)` is always in bounds.
+ ptr::copy_memory(buf_dat.offset(j + 1),
+ &*buf_dat.offset(j),
+ i - j as uint);
+ ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
+ }
+ }
+ }
+
+ // step 2. merge the sorted runs.
+ let mut width = insertion;
+ while width < len {
+ // merge the sorted runs of length `width` in `buf_dat` two at
+ // a time, placing the result in `buf_tmp`.
+
+ // 0 <= start <= len.
+ for start in range_step(0, len, 2 * width) {
+ // manipulate pointers directly for speed (rather than
+ // using a `for` loop with `range` and `.offset` inside
+ // that loop).
+ unsafe {
+ // the end of the first run & start of the
+ // second. Offset of `len` is defined, since this is
+ // precisely one byte past the end of the object.
+ let right_start = buf_dat.offset(cmp::min(start + width, len) as int);
+ // end of the second. Similar reasoning to the above re safety.
+ let right_end_idx = cmp::min(start + 2 * width, len);
+ let right_end = buf_dat.offset(right_end_idx as int);
+
+ // the pointers to the elements under consideration
+ // from the two runs.
+
+ // both of these are in bounds.
+ let mut left = buf_dat.offset(start as int);
+ let mut right = right_start;
+
+ // where we're putting the results, it is a run of
+ // length `2*width`, so we step it once for each step
+ // of either `left` or `right`. `buf_tmp` has length
+ // `len`, so these are in bounds.
+ let mut out = buf_tmp.offset(start as int);
+ let out_end = buf_tmp.offset(right_end_idx as int);
+
+ while out < out_end {
+ // Either the left or the right run are exhausted,
+ // so just copy the remainder from the other run
+ // and move on; this gives a huge speed-up (order
+ // of 25%) for mostly sorted vectors (the best
+ // case).
+ if left == right_start {
+ // the number remaining in this run.
+ let elems = (right_end as uint - right as uint) / mem::size_of::<T>();
+ ptr::copy_nonoverlapping_memory(out, &*right, elems);
+ break;
+ } else if right == right_end {
+ let elems = (right_start as uint - left as uint) / mem::size_of::<T>();
+ ptr::copy_nonoverlapping_memory(out, &*left, elems);
+ break;
+ }
+
+ // check which side is smaller, and that's the
+ // next element for the new run.
+
+ // `left < right_start` and `right < right_end`,
+ // so these are valid.
+ let to_copy = if compare(&*left, &*right) == Greater {
+ step(&mut right)
+ } else {
+ step(&mut left)
+ };
+ ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
+ step(&mut out);
+ }
+ }
+ }
+
+ mem::swap(&mut buf_dat, &mut buf_tmp);
+
+ width *= 2;
+ }
+
+ // write the result to `v` in one go, so that there are never two copies
+ // of the same object in `v`.
+ unsafe {
+ ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
+ }
+
+ // increment the pointer, returning the old pointer.
+ #[inline(always)]
+ unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
+ let old = *ptr;
+ *ptr = ptr.offset(1);
+ old
+ }
+}
+
+/// Extension methods for vectors such that their elements are
+/// mutable.
+pub trait MutableVectorAllocating<'a, T> {
+ /// Sort the vector, 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`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut v = [5i, 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]);
+ /// ```
+ fn sort_by(self, compare: |&T, &T| -> Ordering);
+
+ /**
+ * 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 `str` to stop copying from
+ */
+ fn move_from(self, src: ~[T], start: uint, end: uint) -> uint;
+}
+
+impl<'a,T> MutableVectorAllocating<'a, T> for &'a mut [T] {
+ #[inline]
+ fn sort_by(self, compare: |&T, &T| -> Ordering) {
+ merge_sort(self, compare)
+ }
+
+ #[inline]
+ fn move_from(self, mut src: ~[T], start: uint, end: uint) -> uint {
+ for (a, b) in self.mut_iter().zip(src.mut_slice(start, end).mut_iter()) {
+ mem::swap(a, b);
+ }
+ cmp::min(self.len(), end-start)
+ }
+}
+
+/// Methods for mutable vectors with orderable elements, such as
+/// in-place sorting.
+pub trait MutableOrdVector<T> {
+ /// Sort the vector, in place.
+ ///
+ /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut v = [-5, 4, 1, -3, 2];
+ ///
+ /// v.sort();
+ /// assert!(v == [-5, -3, 1, 2, 4]);
+ /// ```
+ fn sort(self);
+
+ /// Mutates the slice to the next lexicographic permutation.
+ ///
+ /// Returns `true` if successful, `false` if the slice is at the last-ordered permutation.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let v = &mut [0, 1, 2];
+ /// v.next_permutation();
+ /// assert_eq!(v, &mut [0, 2, 1]);
+ /// v.next_permutation();
+ /// assert_eq!(v, &mut [1, 0, 2]);
+ /// ```
+ fn next_permutation(self) -> bool;
+
+ /// Mutates the slice to the previous lexicographic permutation.
+ ///
+ /// Returns `true` if successful, `false` if the slice is at the first-ordered permutation.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let v = &mut [1, 0, 2];
+ /// v.prev_permutation();
+ /// assert_eq!(v, &mut [0, 2, 1]);
+ /// v.prev_permutation();
+ /// assert_eq!(v, &mut [0, 1, 2]);
+ /// ```
+ fn prev_permutation(self) -> bool;
+}
+
+impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
+ #[inline]
+ fn sort(self) {
+ self.sort_by(|a,b| a.cmp(b))
+ }
+
+ fn next_permutation(self) -> bool {
+ // These cases only have 1 permutation each, so we can't do anything.
+ if self.len() < 2 { return false; }
+
+ // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
+ let mut i = self.len() - 1;
+ while i > 0 && self[i-1] >= self[i] {
+ i -= 1;
+ }
+
+ // If that is the entire vector, this is the last-ordered permutation.
+ if i == 0 {
+ return false;
+ }
+
+ // Step 2: Find the rightmost element larger than the pivot (i-1)
+ let mut j = self.len() - 1;
+ while j >= i && self[j] <= self[i-1] {
+ j -= 1;
+ }
+
+ // Step 3: Swap that element with the pivot
+ self.swap(j, i-1);
+
+ // Step 4: Reverse the (previously) weakly decreasing part
+ self.mut_slice_from(i).reverse();
+
+ true
+ }
+
+ fn prev_permutation(self) -> bool {
+ // These cases only have 1 permutation each, so we can't do anything.
+ if self.len() < 2 { return false; }
+
+ // Step 1: Identify the longest, rightmost weakly increasing part of the vector
+ let mut i = self.len() - 1;
+ while i > 0 && self[i-1] <= self[i] {
+ i -= 1;
+ }
+
+ // If that is the entire vector, this is the first-ordered permutation.
+ if i == 0 {
+ return false;
+ }
+
+ // Step 2: Reverse the weakly increasing part
+ self.mut_slice_from(i).reverse();
+
+ // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
+ let mut j = self.len() - 1;
+ while j >= i && self[j-1] < self[i-1] {
+ j -= 1;
+ }
+
+ // Step 4: Swap that element with the pivot
+ self.swap(i-1, j);
+
+ true
+ }
+}
+
+/// Unsafe operations
+pub mod raw {
+ pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};
+ pub use core::slice::raw::{shift_ptr, pop_ptr};
+}
+
+/// An iterator that moves out of a vector.
+pub struct MoveItems<T> {
+ allocation: *mut u8, // the block of memory allocated for the vector
+ iter: Items<'static, T>
+}
+
+impl<T> Iterator<T> for MoveItems<T> {
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ unsafe {
+ self.iter.next().map(|x| ptr::read(x))
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<T> DoubleEndedIterator<T> for MoveItems<T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<T> {
+ unsafe {
+ self.iter.next_back().map(|x| ptr::read(x))
+ }
+ }
+}
+
+#[unsafe_destructor]
+impl<T> Drop for MoveItems<T> {
+ fn drop(&mut self) {
+ // destroy the remaining elements
+ for _x in *self {}
+ unsafe {
+ // FIXME: #13994 (should pass align and size here)
+ deallocate(self.allocation, 0, 8)
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use prelude::*;
+ use cmp::*;
+ use mem;
+ use owned::Box;
+ use rand::{Rng, task_rng};
+ use slice::*;
+
+ fn square(n: uint) -> uint { n * n }
+
+ fn is_odd(n: &uint) -> bool { *n % 2u == 1u }
+
+ #[test]
+ fn test_from_fn() {
+ // Test on-stack from_fn.
+ let mut v = Vec::from_fn(3u, square);
+ {
+ let v = v.as_slice();
+ assert_eq!(v.len(), 3u);
+ assert_eq!(v[0], 0u);
+ assert_eq!(v[1], 1u);
+ assert_eq!(v[2], 4u);
+ }
+
+ // Test on-heap from_fn.
+ v = Vec::from_fn(5u, square);
+ {
+ let v = v.as_slice();
+ assert_eq!(v.len(), 5u);
+ assert_eq!(v[0], 0u);
+ assert_eq!(v[1], 1u);
+ assert_eq!(v[2], 4u);
+ assert_eq!(v[3], 9u);
+ assert_eq!(v[4], 16u);
+ }
+ }
+
+ #[test]
+ fn test_from_elem() {
+ // Test on-stack from_elem.
+ let mut v = Vec::from_elem(2u, 10u);
+ {
+ let v = v.as_slice();
+ assert_eq!(v.len(), 2u);
+ assert_eq!(v[0], 10u);
+ assert_eq!(v[1], 10u);
+ }
+
+ // Test on-heap from_elem.
+ v = Vec::from_elem(6u, 20u);
+ {
+ let v = v.as_slice();
+ assert_eq!(v[0], 20u);
+ assert_eq!(v[1], 20u);
+ assert_eq!(v[2], 20u);
+ assert_eq!(v[3], 20u);
+ assert_eq!(v[4], 20u);
+ assert_eq!(v[5], 20u);
+ }
+ }
+
+ #[test]
+ fn test_is_empty() {
+ let xs: [int, ..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 = box [11];
+ assert_eq!(a.get(1), None);
+ a = box [11, 12];
+ assert_eq!(a.get(1).unwrap(), &12);
+ a = box [11, 12, 13];
+ assert_eq!(a.get(1).unwrap(), &12);
+ }
+
+ #[test]
+ fn test_head() {
+ let mut a = box [];
+ assert_eq!(a.head(), None);
+ a = box [11];
+ assert_eq!(a.head().unwrap(), &11);
+ a = box [11, 12];
+ assert_eq!(a.head().unwrap(), &11);
+ }
+
+ #[test]
+ fn test_tail() {
+ let mut a = box [11];
+ assert_eq!(a.tail(), &[]);
+ a = box [11, 12];
+ assert_eq!(a.tail(), &[12]);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_tail_empty() {
+ let a: ~[int] = box [];
+ a.tail();
+ }
+
+ #[test]
+ fn test_tailn() {
+ let mut a = box [11, 12, 13];
+ assert_eq!(a.tailn(0), &[11, 12, 13]);
+ a = box [11, 12, 13];
+ assert_eq!(a.tailn(2), &[13]);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_tailn_empty() {
+ let a: ~[int] = box [];
+ a.tailn(2);
+ }
+
+ #[test]
+ fn test_init() {
+ let mut a = box [11];
+ assert_eq!(a.init(), &[]);
+ a = box [11, 12];
+ assert_eq!(a.init(), &[11]);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_init_empty() {
+ let a: ~[int] = box [];
+ a.init();
+ }
+
+ #[test]
+ fn test_initn() {
+ let mut a = box [11, 12, 13];
+ assert_eq!(a.initn(0), &[11, 12, 13]);
+ a = box [11, 12, 13];
+ assert_eq!(a.initn(2), &[11]);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_initn_empty() {
+ let a: ~[int] = box [];
+ a.initn(2);
+ }
+
+ #[test]
+ fn test_last() {
+ let mut a = box [];
+ assert_eq!(a.last(), None);
+ a = box [11];
+ assert_eq!(a.last().unwrap(), &11);
+ a = box [11, 12];
+ assert_eq!(a.last().unwrap(), &12);
+ }
+
+ #[test]
+ fn test_slice() {
+ // Test fixed length vector.
+ let vec_fixed = [1, 2, 3, 4];
+ let v_a = vec_fixed.slice(1u, vec_fixed.len()).to_owned();
+ assert_eq!(v_a.len(), 3u);
+ 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.slice(1u, 3u).to_owned();
+ assert_eq!(v_b.len(), 2u);
+ assert_eq!(v_b[0], 2);
+ assert_eq!(v_b[1], 3);
+
+ // Test `Box<[T]>`
+ let vec_unique = box [1, 2, 3, 4, 5, 6];
+ let v_d = vec_unique.slice(1u, 6u).to_owned();
+ assert_eq!(v_d.len(), 5u);
+ 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.slice_from(0), vec);
+ assert_eq!(vec.slice_from(2), &[3, 4]);
+ assert_eq!(vec.slice_from(4), &[]);
+ }
+
+ #[test]
+ fn test_slice_to() {
+ let vec = &[1, 2, 3, 4];
+ assert_eq!(vec.slice_to(4), vec);
+ assert_eq!(vec.slice_to(2), &[1, 2]);
+ assert_eq!(vec.slice_to(0), &[]);
+ }
+
+
+ #[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, Some(1));
+ assert_eq!(v, vec![5, 2, 3, 4]);
+ e = v.swap_remove(3);
+ assert_eq!(e, Some(4));
+ assert_eq!(v, vec![5, 2, 3]);
+
+ e = v.swap_remove(3);
+ assert_eq!(e, None);
+ assert_eq!(v, vec![5, 2, 3]);
+ }
+
+ #[test]
+ fn test_swap_remove_noncopyable() {
+ // Tests that we don't accidentally run destructors twice.
+ let mut v = vec![::unstable::sync::Exclusive::new(()),
+ ::unstable::sync::Exclusive::new(()),
+ ::unstable::sync::Exclusive::new(())];
+ 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(), 1u);
+ assert_eq!(v.as_slice()[0], 1);
+
+ // Test on-heap push().
+ v.push(2);
+ assert_eq!(v.len(), 2u);
+ assert_eq!(v.as_slice()[0], 1);
+ assert_eq!(v.as_slice()[1], 2);
+ }
+
+ #[test]
+ fn test_grow() {
+ // Test on-stack grow().
+ let mut v = vec![];
+ v.grow(2u, &1);
+ {
+ let v = v.as_slice();
+ assert_eq!(v.len(), 2u);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 1);
+ }
+
+ // Test on-heap grow().
+ v.grow(3u, &2);
+ {
+ let v = v.as_slice();
+ assert_eq!(v.len(), 5u);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 1);
+ assert_eq!(v[2], 2);
+ assert_eq!(v[3], 2);
+ assert_eq!(v[4], 2);
+ }
+ }
+
+ #[test]
+ fn test_grow_fn() {
+ let mut v = vec![];
+ v.grow_fn(3u, square);
+ let v = v.as_slice();
+ assert_eq!(v.len(), 3u);
+ assert_eq!(v[0], 0u);
+ assert_eq!(v[1], 1u);
+ assert_eq!(v[2], 4u);
+ }
+
+ #[test]
+ fn test_grow_set() {
+ let mut v = vec![1, 2, 3];
+ v.grow_set(4u, &4, 5);
+ let v = v.as_slice();
+ assert_eq!(v.len(), 5u);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 2);
+ assert_eq!(v[2], 3);
+ assert_eq!(v[3], 4);
+ assert_eq!(v[4], 5);
+ }
+
+ #[test]
+ fn test_truncate() {
+ let mut v = vec![box 6,box 5,box 4];
+ v.truncate(1);
+ let v = v.as_slice();
+ 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 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<uint>, b: Vec<uint>) {
+ 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 1, box 1, box 2, box 3];
+ v0.dedup();
+ let mut v1 = vec![box 1, box 2, box 2, box 3];
+ v1.dedup();
+ let mut v2 = vec![box 1, box 2, box 3, box 3];
+ v2.dedup();
+ /*
+ * If the boxed pointers were leaked or otherwise misused, valgrind
+ * and/or rustrt should raise errors.
+ */
+ }
+
+ #[test]
+ fn test_dedup_shared() {
+ let mut v0 = vec![box 1, box 1, box 2, box 3];
+ v0.dedup();
+ let mut v1 = vec![box 1, box 2, box 2, box 3];
+ v1.dedup();
+ let mut v2 = vec![box 1, box 2, box 3, box 3];
+ v2.dedup();
+ /*
+ * If the pointers were leaked or otherwise misused, valgrind and/or
+ * rustrt should raise errors.
+ */
+ }
+
+ #[test]
+ fn test_retain() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ v.retain(is_odd);
+ assert_eq!(v, vec![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]),
+ _ => fail!(),
+ }
+ }
+ }
+
+ #[test]
+ fn test_permutations() {
+ {
+ let v: [int, ..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.as_slice().to_owned()));
+ 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.as_slice().to_owned()));
+ 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(box [1,2,3]));
+ assert_eq!(it.next(), Some(box [1,3,2]));
+ assert_eq!(it.next(), Some(box [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(box [3,2,1]));
+ assert_eq!(it.next(), Some(box [2,3,1]));
+ assert_eq!(it.next(), Some(box [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 {
+ 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[int] = &mut[1, 2, 3, 4, 5];
+ assert!(v.prev_permutation() == false);
+ assert!(v.next_permutation());
+ assert_eq!(v, &mut[1, 2, 3, 5, 4]);
+ assert!(v.prev_permutation());
+ assert_eq!(v, &mut[1, 2, 3, 4, 5]);
+ assert!(v.next_permutation());
+ assert!(v.next_permutation());
+ assert_eq!(v, &mut[1, 2, 4, 3, 5]);
+ assert!(v.next_permutation());
+ assert_eq!(v, &mut[1, 2, 4, 5, 3]);
+
+ let v : &mut[int] = &mut[1, 0, 0, 0];
+ assert!(v.next_permutation() == false);
+ assert!(v.prev_permutation());
+ assert_eq!(v, &mut[0, 1, 0, 0]);
+ assert!(v.prev_permutation());
+ assert_eq!(v, &mut[0, 0, 1, 0]);
+ assert!(v.prev_permutation());
+ assert_eq!(v, &mut[0, 0, 0, 1]);
+ assert!(v.prev_permutation() == false);
+ }
+
+ #[test]
+ fn test_lexicographic_permutations_empty_and_short() {
+ let empty : &mut[int] = &mut[];
+ assert!(empty.next_permutation() == false);
+ assert_eq!(empty, &mut[]);
+ assert!(empty.prev_permutation() == false);
+ assert_eq!(empty, &mut[]);
+
+ let one_elem : &mut[int] = &mut[4];
+ assert!(one_elem.prev_permutation() == false);
+ assert_eq!(one_elem, &mut[4]);
+ assert!(one_elem.next_permutation() == false);
+ assert_eq!(one_elem, &mut[4]);
+
+ let two_elem : &mut[int] = &mut[1, 2];
+ assert!(two_elem.prev_permutation() == false);
+ assert_eq!(two_elem, &mut[1, 2]);
+ assert!(two_elem.next_permutation());
+ assert_eq!(two_elem, &mut[2, 1]);
+ assert!(two_elem.next_permutation() == false);
+ assert_eq!(two_elem, &mut[2, 1]);
+ assert!(two_elem.prev_permutation());
+ assert_eq!(two_elem, &mut[1, 2]);
+ assert!(two_elem.prev_permutation() == false);
+ assert_eq!(two_elem, &mut[1, 2]);
+ }
+
+ #[test]
+ fn test_position_elem() {
+ assert!([].position_elem(&1).is_none());
+
+ let v1 = box [1, 2, 3, 3, 2, 5];
+ assert_eq!(v1.position_elem(&1), Some(0u));
+ assert_eq!(v1.position_elem(&2), Some(1u));
+ assert_eq!(v1.position_elem(&5), Some(5u));
+ assert!(v1.position_elem(&4).is_none());
+ }
+
+ #[test]
+ fn test_bsearch_elem() {
+ assert_eq!([1,2,3,4,5].bsearch_elem(&5), Some(4));
+ assert_eq!([1,2,3,4,5].bsearch_elem(&4), Some(3));
+ assert_eq!([1,2,3,4,5].bsearch_elem(&3), Some(2));
+ assert_eq!([1,2,3,4,5].bsearch_elem(&2), Some(1));
+ assert_eq!([1,2,3,4,5].bsearch_elem(&1), Some(0));
+
+ assert_eq!([2,4,6,8,10].bsearch_elem(&1), None);
+ assert_eq!([2,4,6,8,10].bsearch_elem(&5), None);
+ assert_eq!([2,4,6,8,10].bsearch_elem(&4), Some(1));
+ assert_eq!([2,4,6,8,10].bsearch_elem(&10), Some(4));
+
+ assert_eq!([2,4,6,8].bsearch_elem(&1), None);
+ assert_eq!([2,4,6,8].bsearch_elem(&5), None);
+ assert_eq!([2,4,6,8].bsearch_elem(&4), Some(1));
+ assert_eq!([2,4,6,8].bsearch_elem(&8), Some(3));
+
+ assert_eq!([2,4,6].bsearch_elem(&1), None);
+ assert_eq!([2,4,6].bsearch_elem(&5), None);
+ assert_eq!([2,4,6].bsearch_elem(&4), Some(1));
+ assert_eq!([2,4,6].bsearch_elem(&6), Some(2));
+
+ assert_eq!([2,4].bsearch_elem(&1), None);
+ assert_eq!([2,4].bsearch_elem(&5), None);
+ assert_eq!([2,4].bsearch_elem(&2), Some(0));
+ assert_eq!([2,4].bsearch_elem(&4), Some(1));
+
+ assert_eq!([2].bsearch_elem(&1), None);
+ assert_eq!([2].bsearch_elem(&5), None);
+ assert_eq!([2].bsearch_elem(&2), Some(0));
+
+ assert_eq!([].bsearch_elem(&1), None);
+ assert_eq!([].bsearch_elem(&5), None);
+
+ assert!([1,1,1,1,1].bsearch_elem(&1) != None);
+ assert!([1,1,1,1,2].bsearch_elem(&1) != None);
+ assert!([1,1,1,2,2].bsearch_elem(&1) != None);
+ assert!([1,1,2,2,2].bsearch_elem(&1) != None);
+ assert_eq!([1,2,2,2,2].bsearch_elem(&1), Some(0));
+
+ assert_eq!([1,2,3,4,5].bsearch_elem(&6), None);
+ assert_eq!([1,2,3,4,5].bsearch_elem(&0), None);
+ }
+
+ #[test]
+ fn test_reverse() {
+ let mut v: ~[int] = box [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: ~[int] = box [];
+ v3.reverse();
+ assert!(v3.is_empty());
+ }
+
+ #[test]
+ fn test_sort() {
+ use realstd::slice::Vector;
+ use realstd::clone::Clone;
+ for len in range(4u, 25) {
+ for _ in range(0, 100) {
+ let mut v = task_rng().gen_iter::<uint>().take(len)
+ .collect::<Vec<uint>>();
+ let mut v1 = v.clone();
+
+ v.as_mut_slice().sort();
+ assert!(v.as_slice().windows(2).all(|w| w[0] <= w[1]));
+
+ v1.as_mut_slice().sort_by(|a, b| a.cmp(b));
+ assert!(v1.as_slice().windows(2).all(|w| w[0] <= w[1]));
+
+ v1.as_mut_slice().sort_by(|a, b| b.cmp(a));
+ assert!(v1.as_slice().windows(2).all(|w| w[0] >= w[1]));
+ }
+ }
+
+ // shouldn't fail/crash
+ let mut v: [uint, .. 0] = [];
+ v.sort();
+
+ let mut v = [0xDEADBEEFu];
+ v.sort();
+ assert!(v == [0xDEADBEEF]);
+ }
+
+ #[test]
+ fn test_sort_stability() {
+ for len in range(4, 25) {
+ for _ in range(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 = range(0, len).map(|_| {
+ let n = task_rng().gen::<uint>() % 10;
+ counts[n] += 1;
+ (n, counts[n])
+ }).collect::<Vec<(uint, int)>>();
+
+ // 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.as_slice().windows(2).all(|w| w[0] <= w[1]));
+ }
+ }
+ }
+
+ #[test]
+ fn test_partition() {
+ assert_eq!((box []).partition(|x: &int| *x < 3), (vec![], vec![]));
+ assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+ }
+
+ #[test]
+ fn test_partitioned() {
+ assert_eq!(([]).partitioned(|x: &int| *x < 3), (vec![], vec![]));
+ assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+ }
+
+ #[test]
+ fn test_concat() {
+ let v: [~[int], ..0] = [];
+ assert_eq!(v.concat_vec(), vec![]);
+ assert_eq!([box [1], box [2,3]].concat_vec(), vec![1, 2, 3]);
+
+ assert_eq!([&[1], &[2,3]].concat_vec(), vec![1, 2, 3]);
+ }
+
+ #[test]
+ fn test_connect() {
+ let v: [~[int], ..0] = [];
+ assert_eq!(v.connect_vec(&0), vec![]);
+ assert_eq!([box [1], box [2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
+ assert_eq!([box [1], box [2], box [3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
+
+ assert_eq!([&[1], &[2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
+ assert_eq!([&[1], &[2], &[3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
+ }
+
+ #[test]
+ fn test_shift() {
+ let mut x = vec![1, 2, 3];
+ assert_eq!(x.shift(), Some(1));
+ assert_eq!(&x, &vec![2, 3]);
+ assert_eq!(x.shift(), Some(2));
+ assert_eq!(x.shift(), Some(3));
+ assert_eq!(x.shift(), None);
+ assert_eq!(x.len(), 0);
+ }
+
+ #[test]
+ fn test_unshift() {
+ let mut x = vec![1, 2, 3];
+ x.unshift(0);
+ assert_eq!(x, vec![0, 1, 2, 3]);
+ }
+
+ #[test]
+ fn test_insert() {
+ let mut a = vec![1, 2, 4];
+ a.insert(2, 3);
+ assert_eq!(a, vec![1, 2, 3, 4]);
+
+ let mut a = vec![1, 2, 3];
+ a.insert(0, 0);
+ assert_eq!(a, vec![0, 1, 2, 3]);
+
+ let mut a = vec![1, 2, 3];
+ a.insert(3, 4);
+ assert_eq!(a, vec![1, 2, 3, 4]);
+
+ let mut a = vec![];
+ a.insert(0, 1);
+ assert_eq!(a, vec![1]);
+ }
+
+ #[test]
+ #[should_fail]
+ 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), Some(3));
+ assert_eq!(a, vec![1,2,4]);
+
+ assert_eq!(a.remove(2), Some(4));
+ assert_eq!(a, vec![1,2]);
+
+ assert_eq!(a.remove(2), None);
+ assert_eq!(a, vec![1,2]);
+
+ assert_eq!(a.remove(0), Some(1));
+ assert_eq!(a, vec![2]);
+
+ assert_eq!(a.remove(0), Some(2));
+ assert_eq!(a, vec![]);
+
+ assert_eq!(a.remove(0), None);
+ assert_eq!(a.remove(10), None);
+ }
+
+ #[test]
+ fn test_capacity() {
+ let mut v = vec![0u64];
+ v.reserve_exact(10u);
+ assert_eq!(v.capacity(), 10u);
+ let mut v = vec![0u32];
+ v.reserve_exact(10u);
+ assert_eq!(v.capacity(), 10u);
+ }
+
+ #[test]
+ fn test_slice_2() {
+ let v = vec![1, 2, 3, 4, 5];
+ let v = v.slice(1u, 3u);
+ assert_eq!(v.len(), 2u);
+ assert_eq!(v[0], 2);
+ assert_eq!(v[1], 3);
+ }
+
+
+ #[test]
+ #[should_fail]
+ fn test_from_fn_fail() {
+ Vec::from_fn(100, |v| {
+ if v == 50 { fail!() }
+ box 0
+ });
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_from_elem_fail() {
+ use cell::Cell;
+ use rc::Rc;
+
+ struct S {
+ f: Cell<int>,
+ boxes: (Box<int>, Rc<int>)
+ }
+
+ impl Clone for S {
+ fn clone(&self) -> S {
+ self.f.set(self.f.get() + 1);
+ if self.f.get() == 10 { fail!() }
+ S { f: self.f, boxes: self.boxes.clone() }
+ }
+ }
+
+ let s = S { f: Cell::new(0), boxes: (box 0, Rc::new(0)) };
+ let _ = Vec::from_elem(100, s);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_grow_fn_fail() {
+ use rc::Rc;
+ let mut v = vec![];
+ v.grow_fn(100, |i| {
+ if i == 50 {
+ fail!()
+ }
+ (box 0, Rc::new(0))
+ })
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_permute_fail() {
+ use rc::Rc;
+ let v = [(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 {
+ fail!()
+ }
+ i += 1;
+ }
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_copy_memory_oob() {
+ unsafe {
+ let mut a = [1, 2, 3, 4];
+ let b = [1, 2, 3, 4, 5];
+ a.copy_memory(b);
+ }
+ }
+
+ #[test]
+ fn test_total_ord() {
+ [1, 2, 3, 4].cmp(& &[1, 2, 3]) == Greater;
+ [1, 2, 3].cmp(& &[1, 2, 3, 4]) == Less;
+ [1, 2, 3, 4].cmp(& &[1, 2, 3, 4]) == Equal;
+ [1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less;
+ [2, 2].cmp(& &[1, 2, 3, 4]) == Greater;
+ }
+
+ #[test]
+ fn test_iterator() {
+ use iter::*;
+ 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() {
+ use iter::*;
+ 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() {
+ use iter::*;
+ let mut xs = [1, 2, 5, 10, 11];
+ assert_eq!(xs.iter().size_hint(), (5, Some(5)));
+ assert_eq!(xs.mut_iter().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() {
+ use iter::*;
+ let mut xs = [1, 2, 3, 4, 5];
+ for x in xs.mut_iter() {
+ *x += 1;
+ }
+ assert!(xs == [2, 3, 4, 5, 6])
+ }
+
+ #[test]
+ fn test_rev_iterator() {
+ use iter::*;
+
+ 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() {
+ use iter::*;
+ let mut xs = [1u, 2, 3, 4, 5];
+ for (i,x) in xs.mut_iter().rev().enumerate() {
+ *x += i;
+ }
+ assert!(xs == [5, 5, 5, 5, 5])
+ }
+
+ #[test]
+ fn test_move_iterator() {
+ use iter::*;
+ let xs = box [1u,2,3,4,5];
+ assert_eq!(xs.move_iter().fold(0, |a: uint, b: uint| 10*a + b), 12345);
+ }
+
+ #[test]
+ fn test_move_rev_iterator() {
+ use iter::*;
+ let xs = box [1u,2,3,4,5];
+ assert_eq!(xs.move_iter().rev().fold(0, |a: uint, b: uint| 10*a + b), 54321);
+ }
+
+ #[test]
+ fn test_splitator() {
+ let xs = &[1i,2,3,4,5];
+
+ assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1], &[3], &[5]]);
+ assert_eq!(xs.split(|x| *x == 1).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[2,3,4,5]]);
+ assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4], &[]]);
+ assert_eq!(xs.split(|x| *x == 10).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
+ assert_eq!(xs.split(|_| true).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[], &[], &[], &[], &[]]);
+
+ let xs: &[int] = &[];
+ assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
+ }
+
+ #[test]
+ fn test_splitnator() {
+ let xs = &[1i,2,3,4,5];
+
+ assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
+ assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1], &[3,4,5]]);
+ assert_eq!(xs.splitn(3, |_| true).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[], &[], &[4,5]]);
+
+ let xs: &[int] = &[];
+ assert_eq!(xs.splitn(1, |x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
+ }
+
+ #[test]
+ fn test_rsplitator() {
+ let xs = &[1i,2,3,4,5];
+
+ assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[5], &[3], &[1]]);
+ assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[2,3,4,5], &[]]);
+ assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[1,2,3,4]]);
+ assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
+
+ let xs: &[int] = &[];
+ assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[int]>>().as_slice(), &[&[]]);
+ }
+
+ #[test]
+ fn test_rsplitnator() {
+ let xs = &[1,2,3,4,5];
+
+ assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
+ assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[5], &[1,2,3]]);
+ assert_eq!(xs.rsplitn(3, |_| true).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[], &[], &[1,2]]);
+
+ let xs: &[int] = &[];
+ assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
+ }
+
+ #[test]
+ fn test_windowsator() {
+ let v = &[1i,2,3,4];
+
+ assert_eq!(v.windows(2).collect::<Vec<&[int]>>().as_slice(), &[&[1,2], &[2,3], &[3,4]]);
+ assert_eq!(v.windows(3).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3], &[2,3,4]]);
+ assert!(v.windows(6).next().is_none());
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_windowsator_0() {
+ let v = &[1i,2,3,4];
+ let _it = v.windows(0);
+ }
+
+ #[test]
+ fn test_chunksator() {
+ let v = &[1i,2,3,4,5];
+
+ assert_eq!(v.chunks(2).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2], &[3,4], &[5]]);
+ assert_eq!(v.chunks(3).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3], &[4,5]]);
+ assert_eq!(v.chunks(6).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3,4,5]]);
+
+ assert_eq!(v.chunks(2).rev().collect::<Vec<&[int]>>().as_slice(), &[&[5i], &[3,4], &[1,2]]);
+ let mut it = v.chunks(2);
+ assert_eq!(it.indexable(), 3);
+ assert_eq!(it.idx(0).unwrap(), &[1,2]);
+ assert_eq!(it.idx(1).unwrap(), &[3,4]);
+ assert_eq!(it.idx(2).unwrap(), &[5]);
+ assert_eq!(it.idx(3), None);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_chunksator_0() {
+ let v = &[1i,2,3,4];
+ let _it = v.chunks(0);
+ }
+
+ #[test]
+ fn test_move_from() {
+ let mut a = [1,2,3,4,5];
+ let b = box [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 = box [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 = box [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 = box [5,6,7,8,9,0];
+ assert_eq!(a.mut_slice(2,4).move_from(b,1,6), 2);
+ assert!(a == [1,2,6,7,5]);
+ }
+
+ #[test]
+ fn test_copy_from() {
+ let mut a = [1,2,3,4,5];
+ let b = [6,7,8];
+ assert_eq!(a.copy_from(b), 3);
+ assert!(a == [6,7,8,4,5]);
+ let mut c = [7,2,8,1];
+ let d = [3,1,4,1,5,9];
+ assert_eq!(c.copy_from(d), 4);
+ assert!(c == [3,1,4,1]);
+ }
+
+ #[test]
+ fn test_reverse_part() {
+ let mut values = [1,2,3,4,5];
+ values.mut_slice(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.as_slice()), x_str);
+ })
+ )
+ let empty: ~[int] = box [];
+ test_show_vec!(empty, "[]".to_string());
+ test_show_vec!(box [1], "[1]".to_string());
+ test_show_vec!(box [1, 2, 3], "[1, 2, 3]".to_string());
+ test_show_vec!(box [box [], box [1u], box [1u, 1u]],
+ "[[], [1], [1, 1]]".to_string());
+
+ let empty_mut: &mut [int] = &mut[];
+ test_show_vec!(empty_mut, "[]".to_string());
+ test_show_vec!(&mut[1], "[1]".to_string());
+ test_show_vec!(&mut[1, 2, 3], "[1, 2, 3]".to_string());
+ test_show_vec!(&mut[&mut[], &mut[1u], &mut[1u, 1u]],
+ "[[], [1], [1, 1]]".to_string());
+ }
+
+ #[test]
+ fn test_vec_default() {
+ use default::Default;
+ macro_rules! t (
+ ($ty:ty) => {{
+ let v: $ty = Default::default();
+ assert!(v.is_empty());
+ }}
+ );
+
+ t!(&[int]);
+ t!(~[int]);
+ t!(Vec<int>);
+ }
+
+ #[test]
+ fn test_bytes_set_memory() {
+ use slice::bytes::MutableByteVector;
+ let mut values = [1u8,2,3,4,5];
+ values.mut_slice(0,5).set_memory(0xAB);
+ assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]);
+ values.mut_slice(2,4).set_memory(0xFF);
+ assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_overflow_does_not_cause_segfault() {
+ let mut v = vec![];
+ v.reserve_exact(-1);
+ v.push(1);
+ v.push(2);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_overflow_does_not_cause_segfault_managed() {
+ use rc::Rc;
+ 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.mut_split_at(2);
+ assert!(left.slice(0, left.len()) == [1, 2]);
+ for p in left.mut_iter() {
+ *p += 1;
+ }
+
+ assert!(right.slice(0, right.len()) == [3, 4, 5]);
+ for p in right.mut_iter() {
+ *p += 2;
+ }
+ }
+
+ assert!(values == [2, 3, 5, 6, 7]);
+ }
+
+ #[deriving(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.iter() {
+ assert!(*f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 3);
+
+ for f in v.slice(1, 3).iter() {
+ assert!(*f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 5);
+
+ for f in v.mut_iter() {
+ assert!(*f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 8);
+
+ for f in v.move_iter() {
+ assert!(f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 11);
+
+ let xs: [Foo, ..3] = [Foo, Foo, Foo];
+ cnt = 0;
+ for f in xs.iter() {
+ 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 range(4, 100) {
+ xs.push(i)
+ }
+ assert_eq!(xs.capacity(), 128);
+ xs.shrink_to_fit();
+ assert_eq!(xs.capacity(), 100);
+ assert_eq!(xs, range(0, 100).collect::<Vec<_>>());
+ }
+
+ #[test]
+ fn test_starts_with() {
+ assert!(bytes!("foobar").starts_with(bytes!("foo")));
+ assert!(!bytes!("foobar").starts_with(bytes!("oob")));
+ assert!(!bytes!("foobar").starts_with(bytes!("bar")));
+ assert!(!bytes!("foo").starts_with(bytes!("foobar")));
+ assert!(!bytes!("bar").starts_with(bytes!("foobar")));
+ assert!(bytes!("foobar").starts_with(bytes!("foobar")));
+ let empty: &[u8] = [];
+ assert!(empty.starts_with(empty));
+ assert!(!empty.starts_with(bytes!("foo")));
+ assert!(bytes!("foobar").starts_with(empty));
+ }
+
+ #[test]
+ fn test_ends_with() {
+ assert!(bytes!("foobar").ends_with(bytes!("bar")));
+ assert!(!bytes!("foobar").ends_with(bytes!("oba")));
+ assert!(!bytes!("foobar").ends_with(bytes!("foo")));
+ assert!(!bytes!("foo").ends_with(bytes!("foobar")));
+ assert!(!bytes!("bar").ends_with(bytes!("foobar")));
+ assert!(bytes!("foobar").ends_with(bytes!("foobar")));
+ let empty: &[u8] = [];
+ assert!(empty.ends_with(empty));
+ assert!(!empty.ends_with(bytes!("foo")));
+ assert!(bytes!("foobar").ends_with(empty));
+ }
+
+ #[test]
+ fn test_shift_ref() {
+ let mut x: &[int] = [1, 2, 3, 4, 5];
+ let h = x.shift_ref();
+ assert_eq!(*h.unwrap(), 1);
+ assert_eq!(x.len(), 4);
+ assert_eq!(x[0], 2);
+ assert_eq!(x[3], 5);
+
+ let mut y: &[int] = [];
+ assert_eq!(y.shift_ref(), None);
+ }
+
+ #[test]
+ fn test_pop_ref() {
+ let mut x: &[int] = [1, 2, 3, 4, 5];
+ let h = x.pop_ref();
+ assert_eq!(*h.unwrap(), 5);
+ assert_eq!(x.len(), 4);
+ assert_eq!(x[0], 1);
+ assert_eq!(x[3], 4);
+
+ let mut y: &[int] = [];
+ assert!(y.pop_ref().is_none());
+ }
+
+ #[test]
+ fn test_mut_splitator() {
+ let mut xs = [0,1,0,2,3,0,0,4,5,0];
+ assert_eq!(xs.mut_split(|x| *x == 0).len(), 6);
+ for slice in xs.mut_split(|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.mut_split(|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.mut_split(|x| *x == 0).rev().take(4) {
+ slice.reverse();
+ }
+ assert!(xs == [1,2,0,4,3,0,0,6,5,0]);
+ }
+
+ #[test]
+ fn test_mut_chunks() {
+ let mut v = [0u8, 1, 2, 3, 4, 5, 6];
+ for (i, chunk) in v.mut_chunks(3).enumerate() {
+ for x in chunk.mut_iter() {
+ *x = i as u8;
+ }
+ }
+ let result = [0u8, 0, 0, 1, 1, 1, 2];
+ assert!(v == result);
+ }
+
+ #[test]
+ fn test_mut_chunks_rev() {
+ let mut v = [0u8, 1, 2, 3, 4, 5, 6];
+ for (i, chunk) in v.mut_chunks(3).rev().enumerate() {
+ for x in chunk.mut_iter() {
+ *x = i as u8;
+ }
+ }
+ let result = [2u8, 2, 2, 1, 1, 1, 0];
+ assert!(v == result);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_mut_chunks_0() {
+ let mut v = [1, 2, 3, 4];
+ let _it = v.mut_chunks(0);
+ }
+
+ #[test]
+ fn test_mut_shift_ref() {
+ let mut x: &mut [int] = [1, 2, 3, 4, 5];
+ let h = x.mut_shift_ref();
+ assert_eq!(*h.unwrap(), 1);
+ assert_eq!(x.len(), 4);
+ assert_eq!(x[0], 2);
+ assert_eq!(x[3], 5);
+
+ let mut y: &mut [int] = [];
+ assert!(y.mut_shift_ref().is_none());
+ }
+
+ #[test]
+ fn test_mut_pop_ref() {
+ let mut x: &mut [int] = [1, 2, 3, 4, 5];
+ let h = x.mut_pop_ref();
+ assert_eq!(*h.unwrap(), 5);
+ assert_eq!(x.len(), 4);
+ assert_eq!(x[0], 1);
+ assert_eq!(x[3], 4);
+
+ let mut y: &mut [int] = [];
+ assert!(y.mut_pop_ref().is_none());
+ }
+
+ #[test]
+ fn test_mut_last() {
+ let mut x = [1, 2, 3, 4, 5];
+ let h = x.mut_last();
+ assert_eq!(*h.unwrap(), 5);
+
+ let y: &mut [int] = [];
+ assert!(y.mut_last().is_none());
+ }
+}
+
+#[cfg(test)]
+mod bench {
+ extern crate test;
+ use self::test::Bencher;
+ use mem;
+ use prelude::*;
+ use ptr;
+ use rand::{weak_rng, Rng};
+
+ #[bench]
+ fn iterator(b: &mut Bencher) {
+ // peculiar numbers to stop LLVM from optimising the summation
+ // out.
+ let v = Vec::from_fn(100, |i| i ^ (i << 1) ^ (i >> 1));
+
+ b.iter(|| {
+ let mut sum = 0;
+ for x in v.iter() {
+ sum += *x;
+ }
+ // sum == 11806, to stop dead code elimination.
+ if sum == 0 {fail!()}
+ })
+ }
+
+ #[bench]
+ fn mut_iterator(b: &mut Bencher) {
+ let mut v = Vec::from_elem(100, 0);
+
+ b.iter(|| {
+ let mut i = 0;
+ for x in v.mut_iter() {
+ *x = i;
+ i += 1;
+ }
+ })
+ }
+
+ #[bench]
+ fn concat(b: &mut Bencher) {
+ let xss: Vec<Vec<uint>> = Vec::from_fn(100, |i| range(0, i).collect());
+ b.iter(|| {
+ xss.as_slice().concat_vec()
+ });
+ }
+
+ #[bench]
+ fn connect(b: &mut Bencher) {
+ let xss: Vec<Vec<uint>> = Vec::from_fn(100, |i| range(0, i).collect());
+ b.iter(|| {
+ xss.as_slice().connect_vec(&0)
+ });
+ }
+
+ #[bench]
+ fn push(b: &mut Bencher) {
+ let mut vec: Vec<uint> = vec![];
+ b.iter(|| {
+ vec.push(0);
+ &vec
+ })
+ }
+
+ #[bench]
+ fn starts_with_same_vector(b: &mut Bencher) {
+ let vec: Vec<uint> = Vec::from_fn(100, |i| i);
+ b.iter(|| {
+ vec.as_slice().starts_with(vec.as_slice())
+ })
+ }
+
+ #[bench]
+ fn starts_with_single_element(b: &mut Bencher) {
+ let vec: Vec<uint> = vec![0];
+ b.iter(|| {
+ vec.as_slice().starts_with(vec.as_slice())
+ })
+ }
+
+ #[bench]
+ fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
+ let vec: Vec<uint> = Vec::from_fn(100, |i| i);
+ let mut match_vec: Vec<uint> = Vec::from_fn(99, |i| i);
+ match_vec.push(0);
+ b.iter(|| {
+ vec.as_slice().starts_with(match_vec.as_slice())
+ })
+ }
+
+ #[bench]
+ fn ends_with_same_vector(b: &mut Bencher) {
+ let vec: Vec<uint> = Vec::from_fn(100, |i| i);
+ b.iter(|| {
+ vec.as_slice().ends_with(vec.as_slice())
+ })
+ }
+
+ #[bench]
+ fn ends_with_single_element(b: &mut Bencher) {
+ let vec: Vec<uint> = vec![0];
+ b.iter(|| {
+ vec.as_slice().ends_with(vec.as_slice())
+ })
+ }
+
+ #[bench]
+ fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
+ let vec: Vec<uint> = Vec::from_fn(100, |i| i);
+ let mut match_vec: Vec<uint> = Vec::from_fn(100, |i| i);
+ match_vec.as_mut_slice()[0] = 200;
+ b.iter(|| {
+ vec.as_slice().starts_with(match_vec.as_slice())
+ })
+ }
+
+ #[bench]
+ fn contains_last_element(b: &mut Bencher) {
+ let vec: Vec<uint> = Vec::from_fn(100, |i| i);
+ b.iter(|| {
+ vec.contains(&99u)
+ })
+ }
+
+ #[bench]
+ fn zero_1kb_from_elem(b: &mut Bencher) {
+ b.iter(|| {
+ Vec::from_elem(1024, 0u8)
+ });
+ }
+
+ #[bench]
+ fn zero_1kb_set_memory(b: &mut Bencher) {
+ b.iter(|| {
+ let mut v: Vec<uint> = Vec::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_fixed_repeat(b: &mut Bencher) {
+ b.iter(|| {
+ box [0u8, ..1024]
+ });
+ }
+
+ #[bench]
+ fn zero_1kb_loop_set(b: &mut Bencher) {
+ b.iter(|| {
+ let mut v: Vec<uint> = Vec::with_capacity(1024);
+ unsafe {
+ v.set_len(1024);
+ }
+ for i in range(0u, 1024) {
+ *v.get_mut(i) = 0;
+ }
+ });
+ }
+
+ #[bench]
+ fn zero_1kb_mut_iter(b: &mut Bencher) {
+ b.iter(|| {
+ let mut v = Vec::with_capacity(1024);
+ unsafe {
+ v.set_len(1024);
+ }
+ for x in v.mut_iter() {
+ *x = 0;
+ }
+ v
+ });
+ }
+
+ #[bench]
+ fn random_inserts(b: &mut Bencher) {
+ let mut rng = weak_rng();
+ b.iter(|| {
+ let mut v = Vec::from_elem(30, (0u, 0u));
+ for _ in range(0, 100) {
+ let l = v.len();
+ v.insert(rng.gen::<uint>() % (l + 1),
+ (1, 1));
+ }
+ })
+ }
+ #[bench]
+ fn random_removes(b: &mut Bencher) {
+ let mut rng = weak_rng();
+ b.iter(|| {
+ let mut v = Vec::from_elem(130, (0u, 0u));
+ for _ in range(0, 100) {
+ let l = v.len();
+ v.remove(rng.gen::<uint>() % l);
+ }
+ })
+ }
+
+ #[bench]
+ fn sort_random_small(b: &mut Bencher) {
+ let mut rng = weak_rng();
+ b.iter(|| {
+ let mut v = rng.gen_iter::<u64>().take(5).collect::<Vec<u64>>();
+ v.as_mut_slice().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 = rng.gen_iter::<u64>().take(100).collect::<Vec<u64>>();
+ v.as_mut_slice().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 = rng.gen_iter::<u64>().take(10000).collect::<Vec<u64>>();
+ v.as_mut_slice().sort();
+ });
+ b.bytes = 10000 * mem::size_of::<u64>() as u64;
+ }
+
+ #[bench]
+ fn sort_sorted(b: &mut Bencher) {
+ let mut v = Vec::from_fn(10000, |i| i);
+ b.iter(|| {
+ v.sort();
+ });
+ b.bytes = (v.len() * mem::size_of_val(v.get(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::from_fn(10000u, |i| (i, i, i, i));
+ b.iter(|| {
+ v.sort();
+ });
+ b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64;
+ }
+}
#![allow(missing_doc)]
-use std::iter::{Enumerate, FilterMap};
-use std::mem::replace;
-use std::{vec, slice};
+use core::prelude::*;
+
+use core::iter::{Enumerate, FilterMap};
+use core::mem::replace;
+
+use {vec, slice};
+use vec::Vec;
#[allow(missing_doc)]
pub struct SmallIntMap<T> {
}
pub fn get<'a>(&'a self, key: &uint) -> &'a V {
- self.find(key).expect("key not present")
+ ::expect(self.find(key), "key not present")
}
/// An iterator visiting all key-value pairs in ascending order by the keys.
--- /dev/null
+// 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.
+
+/*!
+
+Unicode string manipulation (`str` type)
+
+# Basic Usage
+
+Rust's string type is one of the core primitive types of the language. While
+represented by the name `str`, the name `str` is not actually a valid type in
+Rust. Each string must also be decorated with a pointer. `String` is used
+for an owned string, so there is only one commonly-used `str` type in Rust:
+`&str`.
+
+`&str` is the borrowed string type. This type of string can only be created
+from other strings, unless it is a static string (see below). As the word
+"borrowed" implies, this type of string is owned elsewhere, and this string
+cannot be moved out of.
+
+As an example, here's some code that uses a string.
+
+```rust
+fn main() {
+ let borrowed_string = "This string is borrowed with the 'static lifetime";
+}
+```
+
+From the example above, you can see that Rust's string literals have the
+`'static` lifetime. This is akin to C's concept of a static string.
+
+String literals are allocated statically in the rodata of the
+executable/library. The string then has the type `&'static str` meaning that
+the string is valid for the `'static` lifetime, otherwise known as the
+lifetime of the entire program. As can be inferred from the type, these static
+strings are not mutable.
+
+# Mutability
+
+Many languages have immutable strings by default, and Rust has a particular
+flavor on this idea. As with the rest of Rust types, strings are immutable by
+default. If a string is declared as `mut`, however, it may be mutated. This
+works the same way as the rest of Rust's type system in the sense that if
+there's a mutable reference to a string, there may only be one mutable reference
+to that string. With these guarantees, strings can easily transition between
+being mutable/immutable with the same benefits of having mutable strings in
+other languages.
+
+# Representation
+
+Rust's string type, `str`, is a sequence of unicode codepoints encoded as a
+stream of UTF-8 bytes. All safely-created strings are guaranteed to be validly
+encoded UTF-8 sequences. Additionally, strings are not null-terminated
+and can contain null codepoints.
+
+The actual representation of strings have direct mappings to vectors: `&str`
+is the same as `&[u8]`.
+
+*/
+
+#![doc(primitive = "str")]
+
+use core::prelude::*;
+
+use core::char;
+use core::default::Default;
+use core::fmt;
+use core::cmp;
+use core::iter::AdditiveIterator;
+use core::mem;
+
+use hash;
+use slice::CloneableVector;
+use string::String;
+use vec::Vec;
+
+pub use core::str::{from_utf8, CharEq, Chars, CharOffsets};
+pub use core::str::{Bytes, CharSplits};
+pub use core::str::{CharSplitsN, Words, AnyLines, MatchIndices, StrSplits};
+pub use core::str::{eq_slice, is_utf8, is_utf16, Utf16Items};
+pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items};
+pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange};
+pub use core::str::{Str, StrSlice};
+
+/*
+Section: Creating a string
+*/
+
+/// Consumes a vector of bytes to create a new utf-8 string.
+///
+/// Returns `Err` with the original vector if the vector contains invalid
+/// UTF-8.
+pub fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>> {
+ String::from_utf8(vv)
+}
+
+/// Convert a byte to a UTF-8 string
+///
+/// # Failure
+///
+/// Fails if invalid UTF-8
+pub fn from_byte(b: u8) -> String {
+ assert!(b < 128u8);
+ String::from_char(1, b as char)
+}
+
+/// Convert a char to a string
+pub fn from_char(ch: char) -> String {
+ let mut buf = String::new();
+ buf.push_char(ch);
+ buf
+}
+
+/// Convert a vector of chars to a string
+pub fn from_chars(chs: &[char]) -> String {
+ chs.iter().map(|c| *c).collect()
+}
+
+/// Methods for vectors of strings
+pub trait StrVector {
+ /// Concatenate a vector of strings.
+ fn concat(&self) -> String;
+
+ /// Concatenate a vector of strings, placing a given separator between each.
+ fn connect(&self, sep: &str) -> String;
+}
+
+impl<'a, S: Str> StrVector for &'a [S] {
+ fn concat(&self) -> String {
+ if self.is_empty() {
+ return String::new();
+ }
+
+ // `len` calculation may overflow but push_str but will check boundaries
+ let len = self.iter().map(|s| s.as_slice().len()).sum();
+
+ let mut result = String::with_capacity(len);
+
+ for s in self.iter() {
+ result.push_str(s.as_slice())
+ }
+
+ result
+ }
+
+ fn connect(&self, sep: &str) -> String {
+ if self.is_empty() {
+ return String::new();
+ }
+
+ // concat is faster
+ if sep.is_empty() {
+ return self.concat();
+ }
+
+ // this is wrong without the guarantee that `self` is non-empty
+ // `len` calculation may overflow but push_str but will check boundaries
+ let len = sep.len() * (self.len() - 1)
+ + self.iter().map(|s| s.as_slice().len()).sum();
+ let mut result = String::with_capacity(len);
+ let mut first = true;
+
+ for s in self.iter() {
+ if first {
+ first = false;
+ } else {
+ result.push_str(sep);
+ }
+ result.push_str(s.as_slice());
+ }
+ result
+ }
+}
+
+impl<'a, S: Str> StrVector for Vec<S> {
+ #[inline]
+ fn concat(&self) -> String {
+ self.as_slice().concat()
+ }
+
+ #[inline]
+ fn connect(&self, sep: &str) -> String {
+ self.as_slice().connect(sep)
+ }
+}
+
+/*
+Section: Iterators
+*/
+
+// Helper functions used for Unicode normalization
+fn canonical_sort(comb: &mut [(char, u8)]) {
+ let len = comb.len();
+ for i in range(0, len) {
+ let mut swapped = false;
+ for j in range(1, len-i) {
+ let class_a = *comb[j-1].ref1();
+ let class_b = *comb[j].ref1();
+ if class_a != 0 && class_b != 0 && class_a > class_b {
+ comb.swap(j-1, j);
+ swapped = true;
+ }
+ }
+ if !swapped { break; }
+ }
+}
+
+#[deriving(Clone)]
+enum DecompositionType {
+ Canonical,
+ Compatible
+}
+
+/// External iterator for a string's decomposition's characters.
+/// Use with the `std::iter` module.
+#[deriving(Clone)]
+pub struct Decompositions<'a> {
+ kind: DecompositionType,
+ iter: Chars<'a>,
+ buffer: Vec<(char, u8)>,
+ sorted: bool
+}
+
+impl<'a> Iterator<char> for Decompositions<'a> {
+ #[inline]
+ fn next(&mut self) -> Option<char> {
+ use unicode::normalization::canonical_combining_class;
+
+ match self.buffer.as_slice().head() {
+ Some(&(c, 0)) => {
+ self.sorted = false;
+ self.buffer.shift();
+ return Some(c);
+ }
+ Some(&(c, _)) if self.sorted => {
+ self.buffer.shift();
+ return Some(c);
+ }
+ _ => self.sorted = false
+ }
+
+ let decomposer = match self.kind {
+ Canonical => char::decompose_canonical,
+ Compatible => char::decompose_compatible
+ };
+
+ if !self.sorted {
+ for ch in self.iter {
+ let buffer = &mut self.buffer;
+ let sorted = &mut self.sorted;
+ decomposer(ch, |d| {
+ let class = canonical_combining_class(d);
+ if class == 0 && !*sorted {
+ canonical_sort(buffer.as_mut_slice());
+ *sorted = true;
+ }
+ buffer.push((d, class));
+ });
+ if *sorted { break }
+ }
+ }
+
+ if !self.sorted {
+ canonical_sort(self.buffer.as_mut_slice());
+ self.sorted = true;
+ }
+
+ match self.buffer.shift() {
+ Some((c, 0)) => {
+ self.sorted = false;
+ Some(c)
+ }
+ Some((c, _)) => Some(c),
+ None => None
+ }
+ }
+
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ let (lower, _) = self.iter.size_hint();
+ (lower, None)
+ }
+}
+
+/// Replace all occurrences of one string with another
+///
+/// # Arguments
+///
+/// * s - The string containing substrings to replace
+/// * from - The string to replace
+/// * to - The replacement string
+///
+/// # Return value
+///
+/// The original string with all occurrences of `from` replaced with `to`
+pub fn replace(s: &str, from: &str, to: &str) -> String {
+ let mut result = String::new();
+ let mut last_end = 0;
+ for (start, end) in s.match_indices(from) {
+ result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
+ result.push_str(to);
+ last_end = end;
+ }
+ result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
+ result
+}
+
+/*
+Section: Misc
+*/
+
+/// Decode a UTF-16 encoded vector `v` into a string, returning `None`
+/// if `v` contains any invalid data.
+///
+/// # Example
+///
+/// ```rust
+/// use std::str;
+///
+/// // 𝄞music
+/// let mut v = [0xD834, 0xDD1E, 0x006d, 0x0075,
+/// 0x0073, 0x0069, 0x0063];
+/// assert_eq!(str::from_utf16(v), Some("𝄞music".to_string()));
+///
+/// // 𝄞mu<invalid>ic
+/// v[4] = 0xD800;
+/// assert_eq!(str::from_utf16(v), None);
+/// ```
+pub fn from_utf16(v: &[u16]) -> Option<String> {
+ let mut s = String::with_capacity(v.len() / 2);
+ for c in utf16_items(v) {
+ match c {
+ ScalarValue(c) => s.push_char(c),
+ LoneSurrogate(_) => return None
+ }
+ }
+ Some(s)
+}
+
+/// Decode a UTF-16 encoded vector `v` into a string, replacing
+/// invalid data with the replacement character (U+FFFD).
+///
+/// # Example
+/// ```rust
+/// use std::str;
+///
+/// // 𝄞mus<invalid>ic<invalid>
+/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
+/// 0x0073, 0xDD1E, 0x0069, 0x0063,
+/// 0xD834];
+///
+/// assert_eq!(str::from_utf16_lossy(v),
+/// "𝄞mus\uFFFDic\uFFFD".to_string());
+/// ```
+pub fn from_utf16_lossy(v: &[u16]) -> String {
+ utf16_items(v).map(|c| c.to_char_lossy()).collect()
+}
+
+// Return the initial codepoint accumulator for the first byte.
+// The first byte is special, only want bottom 5 bits for width 2, 4 bits
+// for width 3, and 3 bits for width 4
+macro_rules! utf8_first_byte(
+ ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
+)
+
+// return the value of $ch updated with continuation byte $byte
+macro_rules! utf8_acc_cont_byte(
+ ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
+)
+
+static TAG_CONT_U8: u8 = 128u8;
+
+/// Converts a vector of bytes to a new utf-8 string.
+/// Any invalid utf-8 sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
+///
+/// # Example
+///
+/// ```rust
+/// let input = bytes!("Hello ", 0xF0, 0x90, 0x80, "World");
+/// let output = std::str::from_utf8_lossy(input);
+/// assert_eq!(output.as_slice(), "Hello \uFFFDWorld");
+/// ```
+pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> {
+ if is_utf8(v) {
+ return Slice(unsafe { mem::transmute(v) })
+ }
+
+ static REPLACEMENT: &'static [u8] = bytes!(0xEF, 0xBF, 0xBD); // U+FFFD in UTF-8
+ let mut i = 0;
+ let total = v.len();
+ fn unsafe_get(xs: &[u8], i: uint) -> u8 {
+ unsafe { *xs.unsafe_ref(i) }
+ }
+ fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 {
+ if i >= total {
+ 0
+ } else {
+ unsafe_get(xs, i)
+ }
+ }
+
+ let mut res = String::with_capacity(total);
+
+ if i > 0 {
+ unsafe {
+ res.push_bytes(v.slice_to(i))
+ };
+ }
+
+ // subseqidx is the index of the first byte of the subsequence we're looking at.
+ // It's used to copy a bunch of contiguous good codepoints at once instead of copying
+ // them one by one.
+ let mut subseqidx = 0;
+
+ while i < total {
+ let i_ = i;
+ let byte = unsafe_get(v, i);
+ i += 1;
+
+ macro_rules! error(() => ({
+ unsafe {
+ if subseqidx != i_ {
+ res.push_bytes(v.slice(subseqidx, i_));
+ }
+ subseqidx = i;
+ res.push_bytes(REPLACEMENT);
+ }
+ }))
+
+ if byte < 128u8 {
+ // subseqidx handles this
+ } else {
+ let w = utf8_char_width(byte);
+
+ match w {
+ 2 => {
+ if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
+ error!();
+ continue;
+ }
+ i += 1;
+ }
+ 3 => {
+ match (byte, safe_get(v, i, total)) {
+ (0xE0 , 0xA0 .. 0xBF) => (),
+ (0xE1 .. 0xEC, 0x80 .. 0xBF) => (),
+ (0xED , 0x80 .. 0x9F) => (),
+ (0xEE .. 0xEF, 0x80 .. 0xBF) => (),
+ _ => {
+ error!();
+ continue;
+ }
+ }
+ i += 1;
+ if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
+ error!();
+ continue;
+ }
+ i += 1;
+ }
+ 4 => {
+ match (byte, safe_get(v, i, total)) {
+ (0xF0 , 0x90 .. 0xBF) => (),
+ (0xF1 .. 0xF3, 0x80 .. 0xBF) => (),
+ (0xF4 , 0x80 .. 0x8F) => (),
+ _ => {
+ error!();
+ continue;
+ }
+ }
+ i += 1;
+ if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
+ error!();
+ continue;
+ }
+ i += 1;
+ if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
+ error!();
+ continue;
+ }
+ i += 1;
+ }
+ _ => {
+ error!();
+ continue;
+ }
+ }
+ }
+ }
+ if subseqidx < total {
+ unsafe {
+ res.push_bytes(v.slice(subseqidx, total))
+ };
+ }
+ Owned(res.into_string())
+}
+
+/*
+Section: MaybeOwned
+*/
+
+/// A `MaybeOwned` is a string that can hold either a `String` or a `&str`.
+/// This can be useful as an optimization when an allocation is sometimes
+/// needed but not always.
+pub enum MaybeOwned<'a> {
+ /// A borrowed string
+ Slice(&'a str),
+ /// An owned string
+ Owned(String)
+}
+
+/// `SendStr` is a specialization of `MaybeOwned` to be sendable
+pub type SendStr = MaybeOwned<'static>;
+
+impl<'a> MaybeOwned<'a> {
+ /// Returns `true` if this `MaybeOwned` wraps an owned string
+ #[inline]
+ pub fn is_owned(&self) -> bool {
+ match *self {
+ Slice(_) => false,
+ Owned(_) => true
+ }
+ }
+
+ /// Returns `true` if this `MaybeOwned` wraps a borrowed string
+ #[inline]
+ pub fn is_slice(&self) -> bool {
+ match *self {
+ Slice(_) => true,
+ Owned(_) => false
+ }
+ }
+}
+
+/// Trait for moving into a `MaybeOwned`
+pub trait IntoMaybeOwned<'a> {
+ /// Moves self into a `MaybeOwned`
+ fn into_maybe_owned(self) -> MaybeOwned<'a>;
+}
+
+impl<'a> IntoMaybeOwned<'a> for String {
+ #[inline]
+ fn into_maybe_owned(self) -> MaybeOwned<'a> {
+ Owned(self)
+ }
+}
+
+impl<'a> IntoMaybeOwned<'a> for &'a str {
+ #[inline]
+ fn into_maybe_owned(self) -> MaybeOwned<'a> { Slice(self) }
+}
+
+impl<'a> IntoMaybeOwned<'a> for MaybeOwned<'a> {
+ #[inline]
+ fn into_maybe_owned(self) -> MaybeOwned<'a> { self }
+}
+
+impl<'a> PartialEq for MaybeOwned<'a> {
+ #[inline]
+ fn eq(&self, other: &MaybeOwned) -> bool {
+ self.as_slice() == other.as_slice()
+ }
+}
+
+impl<'a> Eq for MaybeOwned<'a> {}
+
+impl<'a> PartialOrd for MaybeOwned<'a> {
+ #[inline]
+ fn lt(&self, other: &MaybeOwned) -> bool {
+ self.as_slice().lt(&other.as_slice())
+ }
+}
+
+impl<'a> Ord for MaybeOwned<'a> {
+ #[inline]
+ fn cmp(&self, other: &MaybeOwned) -> Ordering {
+ self.as_slice().cmp(&other.as_slice())
+ }
+}
+
+impl<'a, S: Str> Equiv<S> for MaybeOwned<'a> {
+ #[inline]
+ fn equiv(&self, other: &S) -> bool {
+ self.as_slice() == other.as_slice()
+ }
+}
+
+impl<'a> Str for MaybeOwned<'a> {
+ #[inline]
+ fn as_slice<'b>(&'b self) -> &'b str {
+ match *self {
+ Slice(s) => s,
+ Owned(ref s) => s.as_slice()
+ }
+ }
+}
+
+impl<'a> StrAllocating for MaybeOwned<'a> {
+ #[inline]
+ fn into_string(self) -> String {
+ match self {
+ Slice(s) => s.to_string(),
+ Owned(s) => s
+ }
+ }
+}
+
+impl<'a> Container for MaybeOwned<'a> {
+ #[inline]
+ fn len(&self) -> uint { self.as_slice().len() }
+}
+
+impl<'a> Clone for MaybeOwned<'a> {
+ #[inline]
+ fn clone(&self) -> MaybeOwned<'a> {
+ match *self {
+ Slice(s) => Slice(s),
+ Owned(ref s) => Owned(s.to_string())
+ }
+ }
+}
+
+impl<'a> Default for MaybeOwned<'a> {
+ #[inline]
+ fn default() -> MaybeOwned<'a> { Slice("") }
+}
+
+impl<'a, H: hash::Writer> hash::Hash<H> for MaybeOwned<'a> {
+ #[inline]
+ fn hash(&self, hasher: &mut H) {
+ self.as_slice().hash(hasher)
+ }
+}
+
+impl<'a> fmt::Show for MaybeOwned<'a> {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Slice(ref s) => s.fmt(f),
+ Owned(ref s) => s.fmt(f)
+ }
+ }
+}
+
+/// Unsafe operations
+pub mod raw {
+ use core::prelude::*;
+ use core::mem;
+ use core::raw::Slice;
+
+ use string::String;
+ use vec::Vec;
+
+ pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
+ pub use core::str::raw::{slice_unchecked};
+
+ /// Create a Rust string from a *u8 buffer of the given length
+ pub unsafe fn from_buf_len(buf: *u8, len: uint) -> String {
+ let mut result = String::new();
+ result.push_bytes(mem::transmute(Slice {
+ data: buf,
+ len: len,
+ }));
+ result
+ }
+
+ /// Create a Rust string from a null-terminated C string
+ pub unsafe fn from_c_str(c_string: *i8) -> String {
+ let mut buf = String::new();
+ let mut len = 0;
+ while *c_string.offset(len) != 0 {
+ len += 1;
+ }
+ buf.push_bytes(mem::transmute(Slice {
+ data: c_string,
+ len: len as uint,
+ }));
+ buf
+ }
+
+ /// Converts an owned vector of bytes to a new owned string. This assumes
+ /// that the utf-8-ness of the vector has already been validated
+ #[inline]
+ pub unsafe fn from_utf8_owned(v: Vec<u8>) -> String {
+ mem::transmute(v)
+ }
+
+ /// Converts a byte to a string.
+ pub unsafe fn from_byte(u: u8) -> String {
+ from_utf8_owned(vec![u])
+ }
+
+ /// Sets the length of a string
+ ///
+ /// This will explicitly set the size of the string, without actually
+ /// modifying its buffers, so it is up to the caller to ensure that
+ /// the string is actually the specified size.
+ #[test]
+ fn test_from_buf_len() {
+ use slice::ImmutableVector;
+ use str::StrAllocating;
+
+ unsafe {
+ let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
+ let b = a.as_ptr();
+ let c = from_buf_len(b, 3u);
+ assert_eq!(c, "AAA".to_string());
+ }
+ }
+}
+
+/*
+Section: Trait implementations
+*/
+
+/// Any string that can be represented as a slice
+pub trait StrAllocating: Str {
+ /// Convert `self` into a `String`, not making a copy if possible.
+ fn into_string(self) -> String;
+
+ /// Convert `self` into a `String`.
+ #[inline]
+ fn to_string(&self) -> String {
+ String::from_str(self.as_slice())
+ }
+
+ #[allow(missing_doc)]
+ #[deprecated = "replaced by .into_string()"]
+ fn into_owned(self) -> String {
+ self.into_string()
+ }
+
+ /// Escape each char in `s` with `char::escape_default`.
+ fn escape_default(&self) -> String {
+ let me = self.as_slice();
+ let mut out = String::with_capacity(me.len());
+ for c in me.chars() {
+ c.escape_default(|c| out.push_char(c));
+ }
+ out
+ }
+
+ /// Escape each char in `s` with `char::escape_unicode`.
+ fn escape_unicode(&self) -> String {
+ let me = self.as_slice();
+ let mut out = String::with_capacity(me.len());
+ for c in me.chars() {
+ c.escape_unicode(|c| out.push_char(c));
+ }
+ out
+ }
+
+ /// Replace all occurrences of one string with another.
+ ///
+ /// # Arguments
+ ///
+ /// * `from` - The string to replace
+ /// * `to` - The replacement string
+ ///
+ /// # Return value
+ ///
+ /// The original string with all occurrences of `from` replaced with `to`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let s = "Do you know the muffin man,
+ /// The muffin man, the muffin man, ...".to_string();
+ ///
+ /// assert_eq!(s.replace("muffin man", "little lamb"),
+ /// "Do you know the little lamb,
+ /// The little lamb, the little lamb, ...".to_string());
+ ///
+ /// // not found, so no change.
+ /// assert_eq!(s.replace("cookie monster", "little lamb"), s);
+ /// ```
+ fn replace(&self, from: &str, to: &str) -> String {
+ let me = self.as_slice();
+ let mut result = String::new();
+ let mut last_end = 0;
+ for (start, end) in me.match_indices(from) {
+ result.push_str(unsafe{raw::slice_bytes(me, last_end, start)});
+ result.push_str(to);
+ last_end = end;
+ }
+ result.push_str(unsafe{raw::slice_bytes(me, last_end, me.len())});
+ result
+ }
+
+ #[allow(missing_doc)]
+ #[deprecated = "obsolete, use `to_string`"]
+ #[inline]
+ fn to_owned(&self) -> String {
+ unsafe {
+ mem::transmute(Vec::from_slice(self.as_slice().as_bytes()))
+ }
+ }
+
+ /// Converts to a vector of `u16` encoded as UTF-16.
+ fn to_utf16(&self) -> Vec<u16> {
+ let me = self.as_slice();
+ let mut u = Vec::new();
+ for ch in me.chars() {
+ let mut buf = [0u16, ..2];
+ let n = ch.encode_utf16(buf /* as mut slice! */);
+ u.push_all(buf.slice_to(n));
+ }
+ u
+ }
+
+ /// Given a string, make a new string with repeated copies of it.
+ fn repeat(&self, nn: uint) -> String {
+ let me = self.as_slice();
+ let mut ret = String::with_capacity(nn * me.len());
+ for _ in range(0, nn) {
+ ret.push_str(me);
+ }
+ ret
+ }
+
+ /// Levenshtein Distance between two strings.
+ fn lev_distance(&self, t: &str) -> uint {
+ let me = self.as_slice();
+ let slen = me.len();
+ let tlen = t.len();
+
+ if slen == 0 { return tlen; }
+ if tlen == 0 { return slen; }
+
+ let mut dcol = Vec::from_fn(tlen + 1, |x| x);
+
+ for (i, sc) in me.chars().enumerate() {
+
+ let mut current = i;
+ *dcol.get_mut(0) = current + 1;
+
+ for (j, tc) in t.chars().enumerate() {
+
+ let next = *dcol.get(j + 1);
+
+ if sc == tc {
+ *dcol.get_mut(j + 1) = current;
+ } else {
+ *dcol.get_mut(j + 1) = cmp::min(current, next);
+ *dcol.get_mut(j + 1) = cmp::min(*dcol.get(j + 1),
+ *dcol.get(j)) + 1;
+ }
+
+ current = next;
+ }
+ }
+
+ return *dcol.get(tlen);
+ }
+
+ /// An Iterator over the string in Unicode Normalization Form D
+ /// (canonical decomposition).
+ #[inline]
+ fn nfd_chars<'a>(&'a self) -> Decompositions<'a> {
+ Decompositions {
+ iter: self.as_slice().chars(),
+ buffer: Vec::new(),
+ sorted: false,
+ kind: Canonical
+ }
+ }
+
+ /// An Iterator over the string in Unicode Normalization Form KD
+ /// (compatibility decomposition).
+ #[inline]
+ fn nfkd_chars<'a>(&'a self) -> Decompositions<'a> {
+ Decompositions {
+ iter: self.as_slice().chars(),
+ buffer: Vec::new(),
+ sorted: false,
+ kind: Compatible
+ }
+ }
+}
+
+impl<'a> StrAllocating for &'a str {
+ #[inline]
+ fn into_string(self) -> String {
+ self.to_string()
+ }
+}
+
+/// Methods for owned strings
+pub trait OwnedStr {
+ /// Consumes the string, returning the underlying byte buffer.
+ ///
+ /// The buffer does not have a null terminator.
+ fn into_bytes(self) -> Vec<u8>;
+
+ /// Pushes the given string onto this string, returning the concatenation of the two strings.
+ fn append(self, rhs: &str) -> String;
+}
+
+impl OwnedStr for String {
+ #[inline]
+ fn into_bytes(self) -> Vec<u8> {
+ unsafe { mem::transmute(self) }
+ }
+
+ #[inline]
+ fn append(mut self, rhs: &str) -> String {
+ self.push_str(rhs);
+ self
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use iter::AdditiveIterator;
+ use default::Default;
+ use prelude::*;
+ use str::*;
+ use string::String;
+
+ #[test]
+ fn test_eq_slice() {
+ assert!((eq_slice("foobar".slice(0, 3), "foo")));
+ assert!((eq_slice("barfoo".slice(3, 6), "foo")));
+ assert!((!eq_slice("foo1", "foo2")));
+ }
+
+ #[test]
+ fn test_le() {
+ assert!("" <= "");
+ assert!("" <= "foo");
+ assert!("foo" <= "foo");
+ assert!("foo" != "bar");
+ }
+
+ #[test]
+ fn test_len() {
+ assert_eq!("".len(), 0u);
+ assert_eq!("hello world".len(), 11u);
+ assert_eq!("\x63".len(), 1u);
+ assert_eq!("\xa2".len(), 2u);
+ assert_eq!("\u03c0".len(), 2u);
+ assert_eq!("\u2620".len(), 3u);
+ assert_eq!("\U0001d11e".len(), 4u);
+
+ assert_eq!("".char_len(), 0u);
+ assert_eq!("hello world".char_len(), 11u);
+ assert_eq!("\x63".char_len(), 1u);
+ assert_eq!("\xa2".char_len(), 1u);
+ assert_eq!("\u03c0".char_len(), 1u);
+ assert_eq!("\u2620".char_len(), 1u);
+ assert_eq!("\U0001d11e".char_len(), 1u);
+ assert_eq!("ประเทศไทย中华Việt Nam".char_len(), 19u);
+ }
+
+ #[test]
+ fn test_find() {
+ assert_eq!("hello".find('l'), Some(2u));
+ assert_eq!("hello".find(|c:char| c == 'o'), Some(4u));
+ assert!("hello".find('x').is_none());
+ assert!("hello".find(|c:char| c == 'x').is_none());
+ assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30u));
+ assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30u));
+ }
+
+ #[test]
+ fn test_rfind() {
+ assert_eq!("hello".rfind('l'), Some(3u));
+ assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4u));
+ assert!("hello".rfind('x').is_none());
+ assert!("hello".rfind(|c:char| c == 'x').is_none());
+ assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30u));
+ assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30u));
+ }
+
+ #[test]
+ fn test_collect() {
+ let empty = "".to_string();
+ let s: String = empty.as_slice().chars().collect();
+ assert_eq!(empty, s);
+ let data = "ประเทศไทย中".to_string();
+ let s: String = data.as_slice().chars().collect();
+ assert_eq!(data, s);
+ }
+
+ #[test]
+ fn test_into_bytes() {
+ let data = "asdf".to_string();
+ let buf = data.into_bytes();
+ assert_eq!(bytes!("asdf"), buf.as_slice());
+ }
+
+ #[test]
+ fn test_find_str() {
+ // byte positions
+ assert_eq!("".find_str(""), Some(0u));
+ assert!("banana".find_str("apple pie").is_none());
+
+ let data = "abcabc";
+ assert_eq!(data.slice(0u, 6u).find_str("ab"), Some(0u));
+ assert_eq!(data.slice(2u, 6u).find_str("ab"), Some(3u - 2u));
+ assert!(data.slice(2u, 4u).find_str("ab").is_none());
+
+ let string = "ประเทศไทย中华Việt Nam";
+ let mut data = string.to_string();
+ data.push_str(string);
+ assert!(data.as_slice().find_str("ไท华").is_none());
+ assert_eq!(data.as_slice().slice(0u, 43u).find_str(""), Some(0u));
+ assert_eq!(data.as_slice().slice(6u, 43u).find_str(""), Some(6u - 6u));
+
+ assert_eq!(data.as_slice().slice(0u, 43u).find_str("ประ"), Some( 0u));
+ assert_eq!(data.as_slice().slice(0u, 43u).find_str("ทศไ"), Some(12u));
+ assert_eq!(data.as_slice().slice(0u, 43u).find_str("ย中"), Some(24u));
+ assert_eq!(data.as_slice().slice(0u, 43u).find_str("iệt"), Some(34u));
+ assert_eq!(data.as_slice().slice(0u, 43u).find_str("Nam"), Some(40u));
+
+ assert_eq!(data.as_slice().slice(43u, 86u).find_str("ประ"), Some(43u - 43u));
+ assert_eq!(data.as_slice().slice(43u, 86u).find_str("ทศไ"), Some(55u - 43u));
+ assert_eq!(data.as_slice().slice(43u, 86u).find_str("ย中"), Some(67u - 43u));
+ assert_eq!(data.as_slice().slice(43u, 86u).find_str("iệt"), Some(77u - 43u));
+ assert_eq!(data.as_slice().slice(43u, 86u).find_str("Nam"), Some(83u - 43u));
+ }
+
+ #[test]
+ fn test_slice_chars() {
+ fn t(a: &str, b: &str, start: uint) {
+ assert_eq!(a.slice_chars(start, start + b.char_len()), b);
+ }
+ t("", "", 0);
+ t("hello", "llo", 2);
+ t("hello", "el", 1);
+ t("αβλ", "β", 1);
+ t("αβλ", "", 3);
+ assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8));
+ }
+
+ #[test]
+ fn test_concat() {
+ fn t(v: &[String], s: &str) {
+ assert_eq!(v.concat(), s.to_str().into_string());
+ }
+ t(["you".to_string(), "know".to_string(), "I'm".to_string(),
+ "no".to_string(), "good".to_string()], "youknowI'mnogood");
+ let v: &[String] = [];
+ t(v, "");
+ t(["hi".to_string()], "hi");
+ }
+
+ #[test]
+ fn test_connect() {
+ fn t(v: &[String], sep: &str, s: &str) {
+ assert_eq!(v.connect(sep), s.to_str().into_string());
+ }
+ t(["you".to_string(), "know".to_string(), "I'm".to_string(),
+ "no".to_string(), "good".to_string()],
+ " ", "you know I'm no good");
+ let v: &[String] = [];
+ t(v, " ", "");
+ t(["hi".to_string()], " ", "hi");
+ }
+
+ #[test]
+ fn test_concat_slices() {
+ fn t(v: &[&str], s: &str) {
+ assert_eq!(v.concat(), s.to_str().into_string());
+ }
+ t(["you", "know", "I'm", "no", "good"], "youknowI'mnogood");
+ let v: &[&str] = [];
+ t(v, "");
+ t(["hi"], "hi");
+ }
+
+ #[test]
+ fn test_connect_slices() {
+ fn t(v: &[&str], sep: &str, s: &str) {
+ assert_eq!(v.connect(sep), s.to_str().into_string());
+ }
+ t(["you", "know", "I'm", "no", "good"],
+ " ", "you know I'm no good");
+ t([], " ", "");
+ t(["hi"], " ", "hi");
+ }
+
+ #[test]
+ fn test_repeat() {
+ assert_eq!("x".repeat(4), "xxxx".to_string());
+ assert_eq!("hi".repeat(4), "hihihihi".to_string());
+ assert_eq!("ไท华".repeat(3), "ไท华ไท华ไท华".to_string());
+ assert_eq!("".repeat(4), "".to_string());
+ assert_eq!("hi".repeat(0), "".to_string());
+ }
+
+ #[test]
+ fn test_unsafe_slice() {
+ assert_eq!("ab", unsafe {raw::slice_bytes("abc", 0, 2)});
+ assert_eq!("bc", unsafe {raw::slice_bytes("abc", 1, 3)});
+ assert_eq!("", unsafe {raw::slice_bytes("abc", 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 {raw::slice_bytes(letters.as_slice(),
+ 0u,
+ 500000)}.to_owned());
+ }
+
+ #[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"), "".to_string());
+ assert_eq!("a".replace(a, "b"), "b".to_string());
+ assert_eq!("ab".replace(a, "b"), "bb".to_string());
+ let test = "test";
+ assert!(" test test ".replace(test, "toast") ==
+ " toast toast ".to_string());
+ assert_eq!(" test test ".replace(test, ""), " ".to_string());
+ }
+
+ #[test]
+ fn test_replace_2a() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let a = "ประเ";
+ let a2 = "دولة الكويتทศไทย中华";
+ assert_eq!(data.replace(a, repl).as_slice(), a2);
+ }
+
+ #[test]
+ fn test_replace_2b() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let b = "ะเ";
+ let b2 = "ปรدولة الكويتทศไทย中华";
+ assert_eq!(data.replace(b, repl).as_slice(), b2);
+ }
+
+ #[test]
+ fn test_replace_2c() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let c = "中华";
+ let c2 = "ประเทศไทยدولة الكويت";
+ assert_eq!(data.replace(c, repl).as_slice(), c2);
+ }
+
+ #[test]
+ fn test_replace_2d() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let d = "ไท华";
+ assert_eq!(data.replace(d, repl).as_slice(), 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!("\u65e5", "\u65e5\u672c".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() ==
+ letters.as_slice().slice(0u, 3u * 500000u).to_owned());
+ }
+
+ #[test]
+ fn test_slice_2() {
+ let ss = "中华Việt Nam";
+
+ assert_eq!("华", ss.slice(3u, 6u));
+ assert_eq!("Việt Nam", ss.slice(6u, 16u));
+
+ assert_eq!("ab", "abc".slice(0u, 2u));
+ assert_eq!("bc", "abc".slice(1u, 3u));
+ assert_eq!("", "abc".slice(1u, 1u));
+
+ assert_eq!("中", ss.slice(0u, 3u));
+ assert_eq!("华V", ss.slice(3u, 7u));
+ assert_eq!("", ss.slice(3u, 3u));
+ /*0: 中
+ 3: 华
+ 6: V
+ 7: i
+ 8: ệ
+ 11: t
+ 12:
+ 13: N
+ 14: a
+ 15: m */
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_slice_fail() {
+ "中华Việt Nam".slice(0u, 2u);
+ }
+
+ #[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_chars() {
+ let v: &[char] = &[];
+ assert_eq!(" *** foo *** ".trim_left_chars(v), " *** foo *** ");
+ assert_eq!(" *** foo *** ".trim_left_chars(&['*', ' ']), "foo *** ");
+ assert_eq!(" *** *** ".trim_left_chars(&['*', ' ']), "");
+ assert_eq!("foo *** ".trim_left_chars(&['*', ' ']), "foo *** ");
+
+ assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11");
+ assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12");
+ assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123");
+ }
+
+ #[test]
+ fn test_trim_right_chars() {
+ let v: &[char] = &[];
+ assert_eq!(" *** foo *** ".trim_right_chars(v), " *** foo *** ");
+ assert_eq!(" *** foo *** ".trim_right_chars(&['*', ' ']), " *** foo");
+ assert_eq!(" *** *** ".trim_right_chars(&['*', ' ']), "");
+ assert_eq!(" *** foo".trim_right_chars(&['*', ' ']), " *** foo");
+
+ assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar");
+ assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar");
+ assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar");
+ }
+
+ #[test]
+ fn test_trim_chars() {
+ let v: &[char] = &[];
+ assert_eq!(" *** foo *** ".trim_chars(v), " *** foo *** ");
+ assert_eq!(" *** foo *** ".trim_chars(&['*', ' ']), "foo");
+ assert_eq!(" *** *** ".trim_chars(&['*', ' ']), "");
+ assert_eq!("foo".trim_chars(&['*', ' ']), "foo");
+
+ assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar");
+ assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar");
+ assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "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!(" \u3000 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 \u3000 ".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 \u3000 ".trim(), "wut");
+ assert_eq!(" hey dude ".trim(), "hey dude");
+ }
+
+ #[test]
+ fn test_is_whitespace() {
+ assert!("".is_whitespace());
+ assert!(" ".is_whitespace());
+ assert!("\u2009".is_whitespace()); // Thin space
+ assert!(" \n\t ".is_whitespace());
+ assert!(!" _ ".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!(!is_utf8([0xc0, 0x80]));
+ assert!(!is_utf8([0xc0, 0xae]));
+ assert!(!is_utf8([0xe0, 0x80, 0x80]));
+ assert!(!is_utf8([0xe0, 0x80, 0xaf]));
+ assert!(!is_utf8([0xe0, 0x81, 0x81]));
+ assert!(!is_utf8([0xf0, 0x82, 0x82, 0xac]));
+ assert!(!is_utf8([0xf4, 0x90, 0x80, 0x80]));
+
+ // deny surrogates
+ assert!(!is_utf8([0xED, 0xA0, 0x80]));
+ assert!(!is_utf8([0xED, 0xBF, 0xBF]));
+
+ assert!(is_utf8([0xC2, 0x80]));
+ assert!(is_utf8([0xDF, 0xBF]));
+ assert!(is_utf8([0xE0, 0xA0, 0x80]));
+ assert!(is_utf8([0xED, 0x9F, 0xBF]));
+ assert!(is_utf8([0xEE, 0x80, 0x80]));
+ assert!(is_utf8([0xEF, 0xBF, 0xBF]));
+ assert!(is_utf8([0xF0, 0x90, 0x80, 0x80]));
+ assert!(is_utf8([0xF4, 0x8F, 0xBF, 0xBF]));
+ }
+
+ #[test]
+ fn test_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_raw_from_c_str() {
+ unsafe {
+ let a = box [65, 65, 65, 65, 65, 65, 65, 0];
+ let b = a.as_ptr();
+ let c = raw::from_c_str(b);
+ assert_eq!(c, "AAAAAAA".to_string());
+ }
+ }
+
+ #[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
+ ];
+ assert_eq!("".as_bytes(), &[]);
+ assert_eq!("abc".as_bytes(), &['a' as u8, 'b' as u8, 'c' as u8]);
+ assert_eq!("ศไทย中华Việt Nam".as_bytes(), v.as_slice());
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_as_bytes_fail() {
+ // Don't double free. (I'm not sure if this exercises the
+ // original problem code path anymore.)
+ let s = "".to_string();
+ let _bytes = s.as_bytes();
+ fail!();
+ }
+
+ #[test]
+ fn test_as_ptr() {
+ let buf = "hello".as_ptr();
+ unsafe {
+ assert_eq!(*buf.offset(0), 'h' as u8);
+ assert_eq!(*buf.offset(1), 'e' as u8);
+ assert_eq!(*buf.offset(2), 'l' as u8);
+ assert_eq!(*buf.offset(3), 'l' as u8);
+ assert_eq!(*buf.offset(4), 'o' as u8);
+ }
+ }
+
+ #[test]
+ fn test_subslice_offset() {
+ let a = "kernelsprite";
+ let b = a.slice(7, a.len());
+ let c = a.slice(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();
+ let lines = lines.as_slice();
+ 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_fail]
+ fn test_subslice_offset_2() {
+ let a = "alchemiter";
+ let b = "cruxtruder";
+ a.subslice_offset(b);
+ }
+
+ #[test]
+ fn vec_str_conversions() {
+ let s1: String = "All mimsy were the borogoves".to_string();
+
+ let v: Vec<u8> = Vec::from_slice(s1.as_bytes());
+ let s2: String = from_utf8(v.as_slice()).unwrap().to_string();
+ let mut i: uint = 0u;
+ let n1: uint = s1.len();
+ let n2: uint = v.len();
+ assert_eq!(n1, n2);
+ while i < n1 {
+ let a: u8 = s1.as_slice()[i];
+ let b: u8 = s2.as_slice()[i];
+ debug!("{}", a);
+ debug!("{}", b);
+ assert_eq!(a, b);
+ i += 1u;
+ }
+ }
+
+ #[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_utf16() {
+ let pairs =
+ [("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n".to_string(),
+ vec![0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
+ 0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16,
+ 0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16,
+ 0xd800_u16, 0xdf30_u16, 0x000a_u16]),
+
+ ("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n".to_string(),
+ vec![0xd801_u16, 0xdc12_u16, 0xd801_u16,
+ 0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16,
+ 0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16,
+ 0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16,
+ 0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16,
+ 0x000a_u16]),
+
+ ("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n".to_string(),
+ vec![0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
+ 0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16,
+ 0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16,
+ 0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16,
+ 0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16,
+ 0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16,
+ 0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]),
+
+ ("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n".to_string(),
+ vec![0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
+ 0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16,
+ 0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16,
+ 0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16,
+ 0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16,
+ 0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16,
+ 0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16,
+ 0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16,
+ 0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16,
+ 0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
+ 0x000a_u16 ]),
+ // Issue #12318, even-numbered non-BMP planes
+ ("\U00020000".to_string(),
+ vec![0xD840, 0xDC00])];
+
+ for p in pairs.iter() {
+ let (s, u) = (*p).clone();
+ assert!(is_utf16(u.as_slice()));
+ assert_eq!(s.to_utf16(), u);
+
+ assert_eq!(from_utf16(u.as_slice()).unwrap(), s);
+ assert_eq!(from_utf16_lossy(u.as_slice()), s);
+
+ assert_eq!(from_utf16(s.to_utf16().as_slice()).unwrap(), s);
+ assert_eq!(from_utf16(u.as_slice()).unwrap().to_utf16(), u);
+ }
+ }
+
+ #[test]
+ fn test_utf16_invalid() {
+ // completely positive cases tested above.
+ // lead + eof
+ assert_eq!(from_utf16([0xD800]), None);
+ // lead + lead
+ assert_eq!(from_utf16([0xD800, 0xD800]), None);
+
+ // isolated trail
+ assert_eq!(from_utf16([0x0061, 0xDC00]), None);
+
+ // general
+ assert_eq!(from_utf16([0xD800, 0xd801, 0xdc8b, 0xD800]), None);
+ }
+
+ #[test]
+ fn test_utf16_lossy() {
+ // completely positive cases tested above.
+ // lead + eof
+ assert_eq!(from_utf16_lossy([0xD800]), "\uFFFD".to_string());
+ // lead + lead
+ assert_eq!(from_utf16_lossy([0xD800, 0xD800]), "\uFFFD\uFFFD".to_string());
+
+ // isolated trail
+ assert_eq!(from_utf16_lossy([0x0061, 0xDC00]), "a\uFFFD".to_string());
+
+ // general
+ assert_eq!(from_utf16_lossy([0xD800, 0xd801, 0xdc8b, 0xD800]),
+ "\uFFFD𐒋\uFFFD".to_string());
+ }
+
+ #[test]
+ fn test_truncate_utf16_at_nul() {
+ let v = [];
+ assert_eq!(truncate_utf16_at_nul(v), &[]);
+
+ let v = [0, 2, 3];
+ assert_eq!(truncate_utf16_at_nul(v), &[]);
+
+ let v = [1, 0, 3];
+ assert_eq!(truncate_utf16_at_nul(v), &[1]);
+
+ let v = [1, 2, 0];
+ assert_eq!(truncate_utf16_at_nul(v), &[1, 2]);
+
+ let v = [1, 2, 3];
+ assert_eq!(truncate_utf16_at_nul(v), &[1, 2, 3]);
+ }
+
+ #[test]
+ fn test_char_at() {
+ let s = "ศไทย中华Việt Nam";
+ let v = box ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+ let mut pos = 0;
+ for ch in v.iter() {
+ assert!(s.char_at(pos) == *ch);
+ pos += from_char(*ch).len();
+ }
+ }
+
+ #[test]
+ fn test_char_at_reverse() {
+ let s = "ศไทย中华Việt Nam";
+ let v = box ['ศ','ไ','ท','ย','中','华','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 -= from_char(*ch).len();
+ }
+ }
+
+ #[test]
+ fn test_escape_unicode() {
+ assert_eq!("abc".escape_unicode(), "\\x61\\x62\\x63".to_string());
+ assert_eq!("a c".escape_unicode(), "\\x61\\x20\\x63".to_string());
+ assert_eq!("\r\n\t".escape_unicode(), "\\x0d\\x0a\\x09".to_string());
+ assert_eq!("'\"\\".escape_unicode(), "\\x27\\x22\\x5c".to_string());
+ assert_eq!("\x00\x01\xfe\xff".escape_unicode(), "\\x00\\x01\\xfe\\xff".to_string());
+ assert_eq!("\u0100\uffff".escape_unicode(), "\\u0100\\uffff".to_string());
+ assert_eq!("\U00010000\U0010ffff".escape_unicode(), "\\U00010000\\U0010ffff".to_string());
+ assert_eq!("ab\ufb00".escape_unicode(), "\\x61\\x62\\ufb00".to_string());
+ assert_eq!("\U0001d4ea\r".escape_unicode(), "\\U0001d4ea\\x0d".to_string());
+ }
+
+ #[test]
+ fn test_escape_default() {
+ assert_eq!("abc".escape_default(), "abc".to_string());
+ assert_eq!("a c".escape_default(), "a c".to_string());
+ assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t".to_string());
+ assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\".to_string());
+ assert_eq!("\u0100\uffff".escape_default(), "\\u0100\\uffff".to_string());
+ assert_eq!("\U00010000\U0010ffff".escape_default(), "\\U00010000\\U0010ffff".to_string());
+ assert_eq!("ab\ufb00".escape_default(), "ab\\ufb00".to_string());
+ assert_eq!("\U0001d4ea\r".escape_default(), "\\U0001d4ea\\r".to_string());
+ }
+
+ #[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() {
+ use iter::*;
+ let s = "ศไทย中华Việt Nam";
+ let v = box ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+
+ let mut pos = 0;
+ let mut it = s.chars();
+
+ for c in it {
+ assert_eq!(c, v[pos]);
+ pos += 1;
+ }
+ assert_eq!(pos, v.len());
+ }
+
+ #[test]
+ fn test_rev_iterator() {
+ use iter::*;
+ let s = "ศไทย中华Việt Nam";
+ let v = box ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
+
+ let mut pos = 0;
+ let mut it = s.chars().rev();
+
+ for c in it {
+ assert_eq!(c, v[pos]);
+ pos += 1;
+ }
+ assert_eq!(pos, v.len());
+ }
+
+ #[test]
+ fn test_iterator_clone() {
+ let s = "ศไทย中华Việt Nam";
+ let mut it = s.chars();
+ it.next();
+ assert!(it.zip(it.clone()).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() {
+ use iter::*;
+ 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 mut 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() {
+ use iter::*;
+ 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 mut 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_split_char_iterator() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let split: Vec<&str> = data.split(' ').collect();
+ assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
+ assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ // Unicode
+ let split: Vec<&str> = data.split('ä').collect();
+ assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
+ assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+ }
+
+ #[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, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+
+ let split: Vec<&str> = data.splitn(|c: char| c == ' ', 3).collect();
+ assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+
+ // Unicode
+ let split: Vec<&str> = data.splitn('ä', 3).collect();
+ assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+
+ let split: Vec<&str> = data.splitn(|c: char| c == 'ä', 3).collect();
+ assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+ }
+
+ #[test]
+ fn test_rsplitn_char_iterator() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let mut split: Vec<&str> = data.rsplitn(' ', 3).collect();
+ split.reverse();
+ assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let mut split: Vec<&str> = data.rsplitn(|c: char| c == ' ', 3).collect();
+ split.reverse();
+ assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ // Unicode
+ let mut split: Vec<&str> = data.rsplitn('ä', 3).collect();
+ split.reverse();
+ assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let mut split: Vec<&str> = data.rsplitn(|c: char| c == 'ä', 3).collect();
+ split.reverse();
+ assert_eq!(split, vec!["\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, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
+
+ let split: Vec<&str> = data.split_terminator('\n').collect();
+ assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
+ }
+
+ #[test]
+ fn test_rev_split_char_iterator_no_trailing() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let mut split: Vec<&str> = data.split('\n').rev().collect();
+ split.reverse();
+ assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
+
+ let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
+ split.reverse();
+ assert_eq!(split, vec!["", "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, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
+ }
+
+ #[test]
+ fn test_nfd_chars() {
+ assert_eq!("abc".nfd_chars().collect::<String>(), "abc".to_string());
+ assert_eq!("\u1e0b\u01c4".nfd_chars().collect::<String>(), "d\u0307\u01c4".to_string());
+ assert_eq!("\u2026".nfd_chars().collect::<String>(), "\u2026".to_string());
+ assert_eq!("\u2126".nfd_chars().collect::<String>(), "\u03a9".to_string());
+ assert_eq!("\u1e0b\u0323".nfd_chars().collect::<String>(), "d\u0323\u0307".to_string());
+ assert_eq!("\u1e0d\u0307".nfd_chars().collect::<String>(), "d\u0323\u0307".to_string());
+ assert_eq!("a\u0301".nfd_chars().collect::<String>(), "a\u0301".to_string());
+ assert_eq!("\u0301a".nfd_chars().collect::<String>(), "\u0301a".to_string());
+ assert_eq!("\ud4db".nfd_chars().collect::<String>(), "\u1111\u1171\u11b6".to_string());
+ assert_eq!("\uac1c".nfd_chars().collect::<String>(), "\u1100\u1162".to_string());
+ }
+
+ #[test]
+ fn test_nfkd_chars() {
+ assert_eq!("abc".nfkd_chars().collect::<String>(), "abc".to_string());
+ assert_eq!("\u1e0b\u01c4".nfkd_chars().collect::<String>(), "d\u0307DZ\u030c".to_string());
+ assert_eq!("\u2026".nfkd_chars().collect::<String>(), "...".to_string());
+ assert_eq!("\u2126".nfkd_chars().collect::<String>(), "\u03a9".to_string());
+ assert_eq!("\u1e0b\u0323".nfkd_chars().collect::<String>(), "d\u0323\u0307".to_string());
+ assert_eq!("\u1e0d\u0307".nfkd_chars().collect::<String>(), "d\u0323\u0307".to_string());
+ assert_eq!("a\u0301".nfkd_chars().collect::<String>(), "a\u0301".to_string());
+ assert_eq!("\u0301a".nfkd_chars().collect::<String>(), "\u0301a".to_string());
+ assert_eq!("\ud4db".nfkd_chars().collect::<String>(), "\u1111\u1171\u11b6".to_string());
+ assert_eq!("\uac1c".nfkd_chars().collect::<String>(), "\u1100\u1162".to_string());
+ }
+
+ #[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, vec!["", "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, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
+ }
+
+ #[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.as_slice(), u.as_slice());
+ }
+ 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 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<S: Container>(v: &[S]) -> uint {
+ v.iter().map(|x| x.len()).sum()
+ }
+
+ let s = "01234".to_string();
+ assert_eq!(5, sum_len(["012", "", "34"]));
+ assert_eq!(5, sum_len(["01".to_string(), "2".to_string(),
+ "34".to_string(), "".to_string()]));
+ assert_eq!(5, sum_len([s.as_slice()]));
+ }
+
+ #[test]
+ fn test_str_from_utf8() {
+ let xs = bytes!("hello");
+ assert_eq!(from_utf8(xs), Some("hello"));
+
+ let xs = bytes!("ศไทย中华Việt Nam");
+ assert_eq!(from_utf8(xs), Some("ศไทย中华Việt Nam"));
+
+ let xs = bytes!("hello", 0xff);
+ assert_eq!(from_utf8(xs), None);
+ }
+
+ #[test]
+ fn test_str_from_utf8_owned() {
+ let xs = Vec::from_slice(bytes!("hello"));
+ assert_eq!(from_utf8_owned(xs), Ok("hello".to_string()));
+
+ let xs = Vec::from_slice(bytes!("ศไทย中华Việt Nam"));
+ assert_eq!(from_utf8_owned(xs), Ok("ศไทย中华Việt Nam".to_string()));
+
+ let xs = Vec::from_slice(bytes!("hello", 0xff));
+ assert_eq!(from_utf8_owned(xs),
+ Err(Vec::from_slice(bytes!("hello", 0xff))));
+ }
+
+ #[test]
+ fn test_str_from_utf8_lossy() {
+ let xs = bytes!("hello");
+ assert_eq!(from_utf8_lossy(xs), Slice("hello"));
+
+ let xs = bytes!("ศไทย中华Việt Nam");
+ assert_eq!(from_utf8_lossy(xs), Slice("ศไทย中华Việt Nam"));
+
+ let xs = bytes!("Hello", 0xC2, " There", 0xFF, " Goodbye");
+ assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD There\uFFFD Goodbye".to_string()));
+
+ let xs = bytes!("Hello", 0xC0, 0x80, " There", 0xE6, 0x83, " Goodbye");
+ assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD\uFFFD There\uFFFD Goodbye".to_string()));
+
+ let xs = bytes!(0xF5, "foo", 0xF5, 0x80, "bar");
+ assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFD\uFFFDbar".to_string()));
+
+ let xs = bytes!(0xF1, "foo", 0xF1, 0x80, "bar", 0xF1, 0x80, 0x80, "baz");
+ assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFDbaz".to_string()));
+
+ let xs = bytes!(0xF4, "foo", 0xF4, 0x80, "bar", 0xF4, 0xBF, "baz");
+ assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz".to_string()));
+
+ let xs = bytes!(0xF0, 0x80, 0x80, 0x80, "foo", 0xF0, 0x90, 0x80, 0x80, "bar");
+ assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFD\uFFFD\
+ foo\U00010000bar".to_string()));
+
+ // surrogates
+ let xs = bytes!(0xED, 0xA0, 0x80, "foo", 0xED, 0xBF, 0xBF, "bar");
+ assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFDfoo\
+ \uFFFD\uFFFD\uFFFDbar".to_string()));
+ }
+
+ #[test]
+ fn test_from_str() {
+ let owned: Option<String> = from_str("string");
+ assert_eq!(owned, Some("string".to_string()));
+ }
+
+ #[test]
+ fn test_maybe_owned_traits() {
+ let s = Slice("abcde");
+ assert_eq!(s.len(), 5);
+ assert_eq!(s.as_slice(), "abcde");
+ assert_eq!(s.to_str(), "abcde".to_string());
+ assert_eq!(format!("{}", s), "abcde".to_string());
+ assert!(s.lt(&Owned("bcdef".to_string())));
+ assert_eq!(Slice(""), Default::default());
+
+ let o = Owned("abcde".to_string());
+ assert_eq!(o.len(), 5);
+ assert_eq!(o.as_slice(), "abcde");
+ assert_eq!(o.to_str(), "abcde".to_string());
+ assert_eq!(format!("{}", o), "abcde".to_string());
+ assert!(o.lt(&Slice("bcdef")));
+ assert_eq!(Owned("".to_string()), Default::default());
+
+ assert!(s.cmp(&o) == Equal);
+ assert!(s.equiv(&o));
+
+ assert!(o.cmp(&s) == Equal);
+ assert!(o.equiv(&s));
+ }
+
+ #[test]
+ fn test_maybe_owned_methods() {
+ let s = Slice("abcde");
+ assert!(s.is_slice());
+ assert!(!s.is_owned());
+
+ let o = Owned("abcde".to_string());
+ assert!(!o.is_slice());
+ assert!(o.is_owned());
+ }
+
+ #[test]
+ fn test_maybe_owned_clone() {
+ assert_eq!(Owned("abcde".to_string()), Slice("abcde").clone());
+ assert_eq!(Owned("abcde".to_string()), Owned("abcde".to_string()).clone());
+ assert_eq!(Slice("abcde"), Slice("abcde").clone());
+ assert_eq!(Slice("abcde"), Owned("abcde".to_string()).clone());
+ }
+
+ #[test]
+ fn test_maybe_owned_into_string() {
+ assert_eq!(Slice("abcde").into_string(), "abcde".to_string());
+ assert_eq!(Owned("abcde".to_string()).into_string(), "abcde".to_string());
+ }
+
+ #[test]
+ fn test_into_maybe_owned() {
+ assert_eq!("abcde".into_maybe_owned(), Slice("abcde"));
+ assert_eq!(("abcde".to_string()).into_maybe_owned(), Slice("abcde"));
+ assert_eq!("abcde".into_maybe_owned(), Owned("abcde".to_string()));
+ assert_eq!(("abcde".to_string()).into_maybe_owned(), Owned("abcde".to_string()));
+ }
+}
+
+#[cfg(test)]
+mod bench {
+ extern crate test;
+ use self::test::Bencher;
+ use super::*;
+ use prelude::*;
+
+ #[bench]
+ fn char_iterator(b: &mut Bencher) {
+ let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
+ let len = s.char_len();
+
+ b.iter(|| assert_eq!(s.chars().len(), len));
+ }
+
+ #[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";
+ let len = s.char_len();
+
+ b.iter(|| assert_eq!(s.chars().len(), len));
+ }
+
+ #[bench]
+ fn char_iterator_rev(b: &mut Bencher) {
+ let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
+ let len = s.char_len();
+
+ b.iter(|| assert_eq!(s.chars().rev().len(), len));
+ }
+
+ #[bench]
+ fn char_indicesator(b: &mut Bencher) {
+ let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
+ let len = s.char_len();
+
+ b.iter(|| assert_eq!(s.char_indices().len(), len));
+ }
+
+ #[bench]
+ fn char_indicesator_rev(b: &mut Bencher) {
+ let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
+ let len = s.char_len();
+
+ b.iter(|| assert_eq!(s.char_indices().rev().len(), len));
+ }
+
+ #[bench]
+ fn split_unicode_ascii(b: &mut Bencher) {
+ let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
+
+ b.iter(|| assert_eq!(s.split('V').len(), 3));
+ }
+
+ #[bench]
+ fn split_unicode_not_ascii(b: &mut Bencher) {
+ struct NotAscii(char);
+ impl CharEq for NotAscii {
+ fn matches(&mut self, c: char) -> bool {
+ let NotAscii(cc) = *self;
+ cc == c
+ }
+ fn only_ascii(&self) -> bool { false }
+ }
+ let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
+
+ b.iter(|| assert_eq!(s.split(NotAscii('V')).len(), 3));
+ }
+
+
+ #[bench]
+ fn split_ascii(b: &mut Bencher) {
+ let s = "Mary had a little lamb, Little lamb, little-lamb.";
+ let len = s.split(' ').len();
+
+ b.iter(|| assert_eq!(s.split(' ').len(), len));
+ }
+
+ #[bench]
+ fn split_not_ascii(b: &mut Bencher) {
+ struct NotAscii(char);
+ impl CharEq for NotAscii {
+ #[inline]
+ fn matches(&mut self, c: char) -> bool {
+ let NotAscii(cc) = *self;
+ cc == c
+ }
+ fn only_ascii(&self) -> bool { false }
+ }
+ let s = "Mary had a little lamb, Little lamb, little-lamb.";
+ let len = s.split(' ').len();
+
+ b.iter(|| assert_eq!(s.split(NotAscii(' ')).len(), len));
+ }
+
+ #[bench]
+ fn split_extern_fn(b: &mut Bencher) {
+ let s = "Mary had a little lamb, Little lamb, little-lamb.";
+ let len = s.split(' ').len();
+ fn pred(c: char) -> bool { c == ' ' }
+
+ b.iter(|| assert_eq!(s.split(pred).len(), len));
+ }
+
+ #[bench]
+ fn split_closure(b: &mut Bencher) {
+ let s = "Mary had a little lamb, Little lamb, little-lamb.";
+ let len = s.split(' ').len();
+
+ b.iter(|| assert_eq!(s.split(|c: char| c == ' ').len(), len));
+ }
+
+ #[bench]
+ fn split_slice(b: &mut Bencher) {
+ let s = "Mary had a little lamb, Little lamb, little-lamb.";
+ let len = s.split(' ').len();
+
+ b.iter(|| assert_eq!(s.split(&[' ']).len(), len));
+ }
+
+ #[bench]
+ fn is_utf8_100_ascii(b: &mut Bencher) {
+
+ let s = bytes!("Hello there, the quick brown fox jumped over the lazy dog! \
+ Lorem ipsum dolor sit amet, consectetur. ");
+
+ assert_eq!(100, s.len());
+ b.iter(|| {
+ is_utf8(s)
+ });
+ }
+
+ #[bench]
+ fn is_utf8_100_multibyte(b: &mut Bencher) {
+ let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰");
+ assert_eq!(100, s.len());
+ b.iter(|| {
+ is_utf8(s)
+ });
+ }
+
+ #[bench]
+ fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
+ let s = bytes!("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 _ = from_utf8_lossy(s);
+ });
+ }
+
+ #[bench]
+ fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
+ let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰");
+ assert_eq!(100, s.len());
+ b.iter(|| {
+ let _ = from_utf8_lossy(s);
+ });
+ }
+
+ #[bench]
+ fn from_utf8_lossy_invalid(b: &mut Bencher) {
+ let s = bytes!("Hello", 0xC0, 0x80, " There", 0xE6, 0x83, " Goodbye");
+ b.iter(|| {
+ let _ = from_utf8_lossy(s);
+ });
+ }
+
+ #[bench]
+ fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
+ let s = Vec::from_elem(100, 0xF5u8);
+ b.iter(|| {
+ let _ = from_utf8_lossy(s.as_slice());
+ });
+ }
+
+ #[bench]
+ fn bench_connect(b: &mut Bencher) {
+ let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
+ let sep = "→";
+ let v = [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));
+ })
+ }
+}
--- /dev/null
+// 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.
+
+//! An owned, growable string that enforces that its contents are valid UTF-8.
+
+use core::prelude::*;
+
+use core::default::Default;
+use core::fmt;
+use core::mem;
+use core::ptr;
+use core::raw::Slice;
+
+use hash;
+use str;
+use str::{CharRange, StrAllocating};
+use vec::Vec;
+
+/// A growable string stored as a UTF-8 encoded buffer.
+#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)]
+pub struct String {
+ vec: Vec<u8>,
+}
+
+impl String {
+ /// Creates a new string buffer initialized with the empty string.
+ #[inline]
+ pub fn new() -> String {
+ String {
+ vec: Vec::new(),
+ }
+ }
+
+ /// Creates a new string buffer with the given capacity.
+ #[inline]
+ pub fn with_capacity(capacity: uint) -> String {
+ String {
+ vec: Vec::with_capacity(capacity),
+ }
+ }
+
+ /// Creates a new string buffer from length, capacity, and a pointer.
+ #[inline]
+ pub unsafe fn from_raw_parts(length: uint, capacity: uint, ptr: *mut u8) -> String {
+ String {
+ vec: Vec::from_raw_parts(length, capacity, ptr),
+ }
+ }
+
+ /// Creates a new string buffer from the given string.
+ #[inline]
+ pub fn from_str(string: &str) -> String {
+ String {
+ vec: Vec::from_slice(string.as_bytes())
+ }
+ }
+
+ #[allow(missing_doc)]
+ #[deprecated = "obsoleted by the removal of ~str"]
+ #[inline]
+ pub fn from_owned_str(string: String) -> String {
+ string
+ }
+
+ /// Returns the vector as a string buffer, if possible, taking care not to
+ /// copy it.
+ ///
+ /// Returns `Err` with the original vector if the vector contains invalid
+ /// UTF-8.
+ #[inline]
+ pub fn from_utf8(vec: Vec<u8>) -> Result<String, Vec<u8>> {
+ if str::is_utf8(vec.as_slice()) {
+ Ok(String { vec: vec })
+ } else {
+ Err(vec)
+ }
+ }
+
+ /// Return the underlying byte buffer, encoded as UTF-8.
+ #[inline]
+ pub fn into_bytes(self) -> Vec<u8> {
+ self.vec
+ }
+
+ /// Pushes the given string onto this buffer; then, returns `self` so that it can be used
+ /// again.
+ #[inline]
+ pub fn append(mut self, second: &str) -> String {
+ self.push_str(second);
+ self
+ }
+
+ /// Creates a string buffer by repeating a character `length` times.
+ #[inline]
+ pub fn from_char(length: uint, ch: char) -> String {
+ if length == 0 {
+ return String::new()
+ }
+
+ let mut buf = String::new();
+ buf.push_char(ch);
+ let size = buf.len() * length;
+ buf.reserve(size);
+ for _ in range(1, length) {
+ buf.push_char(ch)
+ }
+ buf
+ }
+
+ /// Pushes the given string onto this string buffer.
+ #[inline]
+ pub fn push_str(&mut self, string: &str) {
+ self.vec.push_all(string.as_bytes())
+ }
+
+ /// Push `ch` onto the given string `count` times.
+ #[inline]
+ pub fn grow(&mut self, count: uint, ch: char) {
+ for _ in range(0, count) {
+ self.push_char(ch)
+ }
+ }
+
+ /// Returns the number of bytes that this string buffer can hold without reallocating.
+ #[inline]
+ pub fn byte_capacity(&self) -> uint {
+ self.vec.capacity()
+ }
+
+ /// Reserves capacity for at least `extra` additional bytes in this string buffer.
+ #[inline]
+ pub fn reserve_additional(&mut self, extra: uint) {
+ self.vec.reserve_additional(extra)
+ }
+
+ /// Reserves capacity for at least `capacity` bytes in this string buffer.
+ #[inline]
+ pub fn reserve(&mut self, capacity: uint) {
+ self.vec.reserve(capacity)
+ }
+
+ /// Reserves capacity for exactly `capacity` bytes in this string buffer.
+ #[inline]
+ pub fn reserve_exact(&mut self, capacity: uint) {
+ self.vec.reserve_exact(capacity)
+ }
+
+ /// Shrinks the capacity of this string buffer to match its length.
+ #[inline]
+ pub fn shrink_to_fit(&mut self) {
+ self.vec.shrink_to_fit()
+ }
+
+ /// Adds the given character to the end of the string.
+ #[inline]
+ pub fn push_char(&mut self, ch: char) {
+ let cur_len = self.len();
+ // This may use up to 4 bytes.
+ self.vec.reserve_additional(4);
+
+ unsafe {
+ // Attempt to not use an intermediate buffer by just pushing bytes
+ // directly onto this string.
+ let slice = Slice {
+ data: self.vec.as_ptr().offset(cur_len as int),
+ len: 4,
+ };
+ let used = ch.encode_utf8(mem::transmute(slice));
+ self.vec.set_len(cur_len + used);
+ }
+ }
+
+ /// Pushes the given bytes onto this string buffer. This is unsafe because it does not check
+ /// to ensure that the resulting string will be valid UTF-8.
+ #[inline]
+ pub unsafe fn push_bytes(&mut self, bytes: &[u8]) {
+ self.vec.push_all(bytes)
+ }
+
+ /// Works with the underlying buffer as a byte slice.
+ #[inline]
+ pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
+ self.vec.as_slice()
+ }
+
+ /// Works with the underlying buffer as a mutable byte slice. Unsafe
+ /// because this can be used to violate the UTF-8 property.
+ #[inline]
+ pub unsafe fn as_mut_bytes<'a>(&'a mut self) -> &'a mut [u8] {
+ self.vec.as_mut_slice()
+ }
+
+ /// Shorten a string to the specified length (which must be <= the current length)
+ #[inline]
+ pub fn truncate(&mut self, len: uint) {
+ assert!(self.as_slice().is_char_boundary(len));
+ self.vec.truncate(len)
+ }
+
+ /// Appends a byte to this string buffer. The caller must preserve the valid UTF-8 property.
+ #[inline]
+ pub unsafe fn push_byte(&mut self, byte: u8) {
+ self.push_bytes([byte])
+ }
+
+ /// Removes the last byte from the string buffer and returns it. Returns `None` if this string
+ /// buffer is empty.
+ ///
+ /// The caller must preserve the valid UTF-8 property.
+ #[inline]
+ pub unsafe fn pop_byte(&mut self) -> Option<u8> {
+ let len = self.len();
+ if len == 0 {
+ return None
+ }
+
+ let byte = self.as_slice()[len - 1];
+ self.vec.set_len(len - 1);
+ Some(byte)
+ }
+
+ /// Removes the last character from the string buffer and returns it. Returns `None` if this
+ /// string buffer is empty.
+ #[inline]
+ pub fn pop_char(&mut self) -> Option<char> {
+ let len = self.len();
+ if len == 0 {
+ return None
+ }
+
+ let CharRange {ch, next} = self.as_slice().char_range_at_reverse(len);
+ unsafe {
+ self.vec.set_len(next);
+ }
+ Some(ch)
+ }
+
+ /// Removes the first byte from the string buffer and returns it. Returns `None` if this string
+ /// buffer is empty.
+ ///
+ /// The caller must preserve the valid UTF-8 property.
+ pub unsafe fn shift_byte(&mut self) -> Option<u8> {
+ self.vec.shift()
+ }
+
+ /// Removes the first character from the string buffer and returns it. Returns `None` if this
+ /// string buffer is empty.
+ ///
+ /// # Warning
+ ///
+ /// This is a O(n) operation as it requires copying every element in the buffer.
+ pub fn shift_char (&mut self) -> Option<char> {
+ let len = self.len();
+ if len == 0 {
+ return None
+ }
+
+ let CharRange {ch, next} = self.as_slice().char_range_at(0);
+ let new_len = len - next;
+ unsafe {
+ ptr::copy_memory(self.vec.as_mut_ptr(), self.vec.as_ptr().offset(next as int), new_len);
+ self.vec.set_len(new_len);
+ }
+ Some(ch)
+ }
+
+ /// Views the string buffer as a mutable sequence of bytes.
+ ///
+ /// Callers must preserve the valid UTF-8 property.
+ pub unsafe fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec<u8> {
+ &mut self.vec
+ }
+}
+
+impl Container for String {
+ #[inline]
+ fn len(&self) -> uint {
+ self.vec.len()
+ }
+}
+
+impl Mutable for String {
+ #[inline]
+ fn clear(&mut self) {
+ self.vec.clear()
+ }
+}
+
+impl FromIterator<char> for String {
+ fn from_iter<I:Iterator<char>>(iterator: I) -> String {
+ let mut buf = String::new();
+ buf.extend(iterator);
+ buf
+ }
+}
+
+impl Extendable<char> for String {
+ fn extend<I:Iterator<char>>(&mut self, mut iterator: I) {
+ for ch in iterator {
+ self.push_char(ch)
+ }
+ }
+}
+
+impl Str for String {
+ #[inline]
+ fn as_slice<'a>(&'a self) -> &'a str {
+ unsafe {
+ mem::transmute(self.vec.as_slice())
+ }
+ }
+}
+
+impl StrAllocating for String {
+ #[inline]
+ fn into_string(self) -> String {
+ self
+ }
+}
+
+impl Default for String {
+ fn default() -> String {
+ String::new()
+ }
+}
+
+impl fmt::Show for String {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.as_slice().fmt(f)
+ }
+}
+
+impl<H: hash::Writer> hash::Hash<H> for String {
+ #[inline]
+ fn hash(&self, hasher: &mut H) {
+ self.as_slice().hash(hasher)
+ }
+}
+
+impl<'a, S: Str> Equiv<S> for String {
+ #[inline]
+ fn equiv(&self, other: &S) -> bool {
+ self.as_slice() == other.as_slice()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ extern crate test;
+ use container::{Container, Mutable};
+ use self::test::Bencher;
+ use str::{Str, StrSlice};
+ use super::String;
+
+ #[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);
+ });
+ }
+
+ #[test]
+ fn test_push_bytes() {
+ let mut s = String::from_str("ABC");
+ unsafe {
+ s.push_bytes([ 'D' as u8 ]);
+ }
+ assert_eq!(s.as_slice(), "ABCD");
+ }
+
+ #[test]
+ fn test_push_str() {
+ let mut s = String::new();
+ s.push_str("");
+ assert_eq!(s.as_slice().slice_from(0), "");
+ s.push_str("abc");
+ assert_eq!(s.as_slice().slice_from(0), "abc");
+ s.push_str("ประเทศไทย中华Việt Nam");
+ assert_eq!(s.as_slice().slice_from(0), "abcประเทศไทย中华Việt Nam");
+ }
+
+ #[test]
+ fn test_push_char() {
+ let mut data = String::from_str("ประเทศไทย中");
+ data.push_char('华');
+ data.push_char('b'); // 1 byte
+ data.push_char('¢'); // 2 byte
+ data.push_char('€'); // 3 byte
+ data.push_char('𤭢'); // 4 byte
+ assert_eq!(data.as_slice(), "ประเทศไทย中华b¢€𤭢");
+ }
+
+ #[test]
+ fn test_pop_char() {
+ let mut data = String::from_str("ประเทศไทย中华b¢€𤭢");
+ assert_eq!(data.pop_char().unwrap(), '𤭢'); // 4 bytes
+ assert_eq!(data.pop_char().unwrap(), '€'); // 3 bytes
+ assert_eq!(data.pop_char().unwrap(), '¢'); // 2 bytes
+ assert_eq!(data.pop_char().unwrap(), 'b'); // 1 bytes
+ assert_eq!(data.pop_char().unwrap(), '华');
+ assert_eq!(data.as_slice(), "ประเทศไทย中");
+ }
+
+ #[test]
+ fn test_shift_char() {
+ let mut data = String::from_str("𤭢€¢b华ประเทศไทย中");
+ assert_eq!(data.shift_char().unwrap(), '𤭢'); // 4 bytes
+ assert_eq!(data.shift_char().unwrap(), '€'); // 3 bytes
+ assert_eq!(data.shift_char().unwrap(), '¢'); // 2 bytes
+ assert_eq!(data.shift_char().unwrap(), 'b'); // 1 bytes
+ assert_eq!(data.shift_char().unwrap(), '华');
+ assert_eq!(data.as_slice(), "ประเทศไทย中");
+ }
+
+ #[test]
+ fn test_str_truncate() {
+ let mut s = String::from_str("12345");
+ s.truncate(5);
+ assert_eq!(s.as_slice(), "12345");
+ s.truncate(3);
+ assert_eq!(s.as_slice(), "123");
+ s.truncate(0);
+ assert_eq!(s.as_slice(), "");
+
+ let mut s = String::from_str("12345");
+ let p = s.as_slice().as_ptr();
+ s.truncate(3);
+ s.push_str("6");
+ let p_ = s.as_slice().as_ptr();
+ assert_eq!(p_, p);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_str_truncate_invalid_len() {
+ let mut s = String::from_str("12345");
+ s.truncate(6);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_str_truncate_split_codepoint() {
+ let mut s = String::from_str("\u00FC"); // ü
+ 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.as_slice(), "");
+ }
+}
//! trees. The only requirement for the types is that the key implements
//! `Ord`.
-use std::cmp::Ordering;
-use std::fmt::Show;
-use std::fmt;
-use std::iter::Peekable;
-use std::iter;
-use std::mem::{replace, swap};
-use std::ptr;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::fmt;
+use core::fmt::Show;
+use core::iter::Peekable;
+use core::iter;
+use core::mem::{replace, swap};
+use core::ptr;
+
+use vec::Vec;
// This is implemented as an AA tree, which is a simplified variation of
// a red-black tree where red (horizontal) nodes can only be added
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
-use std::mem::zeroed;
-use std::mem;
-use std::slice::{Items, MutItems};
-use std::slice;
-use std::uint;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::mem::zeroed;
+use core::mem;
+use core::uint;
+
+use slice::{Items, MutItems};
+use slice;
// FIXME: #5244: need to manually update the TrieNode constructor
static SHIFT: uint = 4;
*child = Internal(new);
return ret;
}
- _ => unreachable!()
+ _ => fail!("unreachable code"),
}
}
--- /dev/null
+// 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.
+
+// NOTE: The following code was generated by "src/etc/unicode.py", do not edit directly
+
+#![allow(missing_doc, non_uppercase_statics)]
+
+pub mod normalization {
+ use core::prelude::*;
+
+ fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
+ match r.bsearch(|&(lo, hi, _)| {
+ if lo <= c && c <= hi { Equal }
+ else if hi < c { Less }
+ else { Greater }
+ }) {
+ Some(idx) => {
+ let (_, _, result) = r[idx];
+ result
+ }
+ None => 0
+ }
+ }
+
+
+ static combining_class_table : &'static [(char, char, u8)] = &[
+ ('\u0300', '\u0314', 230), ('\u0315', '\u0315', 232),
+ ('\u0316', '\u0319', 220), ('\u031a', '\u031a', 232),
+ ('\u031b', '\u031b', 216), ('\u031c', '\u0320', 220),
+ ('\u0321', '\u0322', 202), ('\u0323', '\u0326', 220),
+ ('\u0327', '\u0328', 202), ('\u0329', '\u0333', 220),
+ ('\u0334', '\u0338', 1), ('\u0339', '\u033c', 220),
+ ('\u033d', '\u0344', 230), ('\u0345', '\u0345', 240),
+ ('\u0346', '\u0346', 230), ('\u0347', '\u0349', 220),
+ ('\u034a', '\u034c', 230), ('\u034d', '\u034e', 220),
+ ('\u0350', '\u0352', 230), ('\u0353', '\u0356', 220),
+ ('\u0357', '\u0357', 230), ('\u0358', '\u0358', 232),
+ ('\u0359', '\u035a', 220), ('\u035b', '\u035b', 230),
+ ('\u035c', '\u035c', 233), ('\u035d', '\u035e', 234),
+ ('\u035f', '\u035f', 233), ('\u0360', '\u0361', 234),
+ ('\u0362', '\u0362', 233), ('\u0363', '\u036f', 230),
+ ('\u0483', '\u0487', 230), ('\u0591', '\u0591', 220),
+ ('\u0592', '\u0595', 230), ('\u0596', '\u0596', 220),
+ ('\u0597', '\u0599', 230), ('\u059a', '\u059a', 222),
+ ('\u059b', '\u059b', 220), ('\u059c', '\u05a1', 230),
+ ('\u05a2', '\u05a7', 220), ('\u05a8', '\u05a9', 230),
+ ('\u05aa', '\u05aa', 220), ('\u05ab', '\u05ac', 230),
+ ('\u05ad', '\u05ad', 222), ('\u05ae', '\u05ae', 228),
+ ('\u05af', '\u05af', 230), ('\u05b0', '\u05b0', 10),
+ ('\u05b1', '\u05b1', 11), ('\u05b2', '\u05b2', 12),
+ ('\u05b3', '\u05b3', 13), ('\u05b4', '\u05b4', 14),
+ ('\u05b5', '\u05b5', 15), ('\u05b6', '\u05b6', 16),
+ ('\u05b7', '\u05b7', 17), ('\u05b8', '\u05b8', 18),
+ ('\u05b9', '\u05ba', 19), ('\u05bb', '\u05bb', 20),
+ ('\u05bc', '\u05bc', 21), ('\u05bd', '\u05bd', 22),
+ ('\u05bf', '\u05bf', 23), ('\u05c1', '\u05c1', 24),
+ ('\u05c2', '\u05c2', 25), ('\u05c4', '\u05c4', 230),
+ ('\u05c5', '\u05c5', 220), ('\u05c7', '\u05c7', 18),
+ ('\u0610', '\u0617', 230), ('\u0618', '\u0618', 30),
+ ('\u0619', '\u0619', 31), ('\u061a', '\u061a', 32),
+ ('\u064b', '\u064b', 27), ('\u064c', '\u064c', 28),
+ ('\u064d', '\u064d', 29), ('\u064e', '\u064e', 30),
+ ('\u064f', '\u064f', 31), ('\u0650', '\u0650', 32),
+ ('\u0651', '\u0651', 33), ('\u0652', '\u0652', 34),
+ ('\u0653', '\u0654', 230), ('\u0655', '\u0656', 220),
+ ('\u0657', '\u065b', 230), ('\u065c', '\u065c', 220),
+ ('\u065d', '\u065e', 230), ('\u065f', '\u065f', 220),
+ ('\u0670', '\u0670', 35), ('\u06d6', '\u06dc', 230),
+ ('\u06df', '\u06e2', 230), ('\u06e3', '\u06e3', 220),
+ ('\u06e4', '\u06e4', 230), ('\u06e7', '\u06e8', 230),
+ ('\u06ea', '\u06ea', 220), ('\u06eb', '\u06ec', 230),
+ ('\u06ed', '\u06ed', 220), ('\u0711', '\u0711', 36),
+ ('\u0730', '\u0730', 230), ('\u0731', '\u0731', 220),
+ ('\u0732', '\u0733', 230), ('\u0734', '\u0734', 220),
+ ('\u0735', '\u0736', 230), ('\u0737', '\u0739', 220),
+ ('\u073a', '\u073a', 230), ('\u073b', '\u073c', 220),
+ ('\u073d', '\u073d', 230), ('\u073e', '\u073e', 220),
+ ('\u073f', '\u0741', 230), ('\u0742', '\u0742', 220),
+ ('\u0743', '\u0743', 230), ('\u0744', '\u0744', 220),
+ ('\u0745', '\u0745', 230), ('\u0746', '\u0746', 220),
+ ('\u0747', '\u0747', 230), ('\u0748', '\u0748', 220),
+ ('\u0749', '\u074a', 230), ('\u07eb', '\u07f1', 230),
+ ('\u07f2', '\u07f2', 220), ('\u07f3', '\u07f3', 230),
+ ('\u0816', '\u0819', 230), ('\u081b', '\u0823', 230),
+ ('\u0825', '\u0827', 230), ('\u0829', '\u082d', 230),
+ ('\u0859', '\u085b', 220), ('\u08e4', '\u08e5', 230),
+ ('\u08e6', '\u08e6', 220), ('\u08e7', '\u08e8', 230),
+ ('\u08e9', '\u08e9', 220), ('\u08ea', '\u08ec', 230),
+ ('\u08ed', '\u08ef', 220), ('\u08f0', '\u08f0', 27),
+ ('\u08f1', '\u08f1', 28), ('\u08f2', '\u08f2', 29),
+ ('\u08f3', '\u08f5', 230), ('\u08f6', '\u08f6', 220),
+ ('\u08f7', '\u08f8', 230), ('\u08f9', '\u08fa', 220),
+ ('\u08fb', '\u08fe', 230), ('\u093c', '\u093c', 7),
+ ('\u094d', '\u094d', 9), ('\u0951', '\u0951', 230),
+ ('\u0952', '\u0952', 220), ('\u0953', '\u0954', 230),
+ ('\u09bc', '\u09bc', 7), ('\u09cd', '\u09cd', 9),
+ ('\u0a3c', '\u0a3c', 7), ('\u0a4d', '\u0a4d', 9),
+ ('\u0abc', '\u0abc', 7), ('\u0acd', '\u0acd', 9),
+ ('\u0b3c', '\u0b3c', 7), ('\u0b4d', '\u0b4d', 9),
+ ('\u0bcd', '\u0bcd', 9), ('\u0c4d', '\u0c4d', 9),
+ ('\u0c55', '\u0c55', 84), ('\u0c56', '\u0c56', 91),
+ ('\u0cbc', '\u0cbc', 7), ('\u0ccd', '\u0ccd', 9),
+ ('\u0d4d', '\u0d4d', 9), ('\u0dca', '\u0dca', 9),
+ ('\u0e38', '\u0e39', 103), ('\u0e3a', '\u0e3a', 9),
+ ('\u0e48', '\u0e4b', 107), ('\u0eb8', '\u0eb9', 118),
+ ('\u0ec8', '\u0ecb', 122), ('\u0f18', '\u0f19', 220),
+ ('\u0f35', '\u0f35', 220), ('\u0f37', '\u0f37', 220),
+ ('\u0f39', '\u0f39', 216), ('\u0f71', '\u0f71', 129),
+ ('\u0f72', '\u0f72', 130), ('\u0f74', '\u0f74', 132),
+ ('\u0f7a', '\u0f7d', 130), ('\u0f80', '\u0f80', 130),
+ ('\u0f82', '\u0f83', 230), ('\u0f84', '\u0f84', 9),
+ ('\u0f86', '\u0f87', 230), ('\u0fc6', '\u0fc6', 220),
+ ('\u1037', '\u1037', 7), ('\u1039', '\u103a', 9),
+ ('\u108d', '\u108d', 220), ('\u135d', '\u135f', 230),
+ ('\u1714', '\u1714', 9), ('\u1734', '\u1734', 9),
+ ('\u17d2', '\u17d2', 9), ('\u17dd', '\u17dd', 230),
+ ('\u18a9', '\u18a9', 228), ('\u1939', '\u1939', 222),
+ ('\u193a', '\u193a', 230), ('\u193b', '\u193b', 220),
+ ('\u1a17', '\u1a17', 230), ('\u1a18', '\u1a18', 220),
+ ('\u1a60', '\u1a60', 9), ('\u1a75', '\u1a7c', 230),
+ ('\u1a7f', '\u1a7f', 220), ('\u1b34', '\u1b34', 7),
+ ('\u1b44', '\u1b44', 9), ('\u1b6b', '\u1b6b', 230),
+ ('\u1b6c', '\u1b6c', 220), ('\u1b6d', '\u1b73', 230),
+ ('\u1baa', '\u1bab', 9), ('\u1be6', '\u1be6', 7),
+ ('\u1bf2', '\u1bf3', 9), ('\u1c37', '\u1c37', 7),
+ ('\u1cd0', '\u1cd2', 230), ('\u1cd4', '\u1cd4', 1),
+ ('\u1cd5', '\u1cd9', 220), ('\u1cda', '\u1cdb', 230),
+ ('\u1cdc', '\u1cdf', 220), ('\u1ce0', '\u1ce0', 230),
+ ('\u1ce2', '\u1ce8', 1), ('\u1ced', '\u1ced', 220),
+ ('\u1cf4', '\u1cf4', 230), ('\u1dc0', '\u1dc1', 230),
+ ('\u1dc2', '\u1dc2', 220), ('\u1dc3', '\u1dc9', 230),
+ ('\u1dca', '\u1dca', 220), ('\u1dcb', '\u1dcc', 230),
+ ('\u1dcd', '\u1dcd', 234), ('\u1dce', '\u1dce', 214),
+ ('\u1dcf', '\u1dcf', 220), ('\u1dd0', '\u1dd0', 202),
+ ('\u1dd1', '\u1de6', 230), ('\u1dfc', '\u1dfc', 233),
+ ('\u1dfd', '\u1dfd', 220), ('\u1dfe', '\u1dfe', 230),
+ ('\u1dff', '\u1dff', 220), ('\u20d0', '\u20d1', 230),
+ ('\u20d2', '\u20d3', 1), ('\u20d4', '\u20d7', 230),
+ ('\u20d8', '\u20da', 1), ('\u20db', '\u20dc', 230),
+ ('\u20e1', '\u20e1', 230), ('\u20e5', '\u20e6', 1),
+ ('\u20e7', '\u20e7', 230), ('\u20e8', '\u20e8', 220),
+ ('\u20e9', '\u20e9', 230), ('\u20ea', '\u20eb', 1),
+ ('\u20ec', '\u20ef', 220), ('\u20f0', '\u20f0', 230),
+ ('\u2cef', '\u2cf1', 230), ('\u2d7f', '\u2d7f', 9),
+ ('\u2de0', '\u2dff', 230), ('\u302a', '\u302a', 218),
+ ('\u302b', '\u302b', 228), ('\u302c', '\u302c', 232),
+ ('\u302d', '\u302d', 222), ('\u302e', '\u302f', 224),
+ ('\u3099', '\u309a', 8), ('\ua66f', '\ua66f', 230),
+ ('\ua674', '\ua67d', 230), ('\ua69f', '\ua69f', 230),
+ ('\ua6f0', '\ua6f1', 230), ('\ua806', '\ua806', 9),
+ ('\ua8c4', '\ua8c4', 9), ('\ua8e0', '\ua8f1', 230),
+ ('\ua92b', '\ua92d', 220), ('\ua953', '\ua953', 9),
+ ('\ua9b3', '\ua9b3', 7), ('\ua9c0', '\ua9c0', 9),
+ ('\uaab0', '\uaab0', 230), ('\uaab2', '\uaab3', 230),
+ ('\uaab4', '\uaab4', 220), ('\uaab7', '\uaab8', 230),
+ ('\uaabe', '\uaabf', 230), ('\uaac1', '\uaac1', 230),
+ ('\uaaf6', '\uaaf6', 9), ('\uabed', '\uabed', 9),
+ ('\ufb1e', '\ufb1e', 26), ('\ufe20', '\ufe26', 230),
+ ('\U000101fd', '\U000101fd', 220), ('\U00010a0d', '\U00010a0d', 220),
+ ('\U00010a0f', '\U00010a0f', 230), ('\U00010a38', '\U00010a38', 230),
+ ('\U00010a39', '\U00010a39', 1), ('\U00010a3a', '\U00010a3a', 220),
+ ('\U00010a3f', '\U00010a3f', 9), ('\U00011046', '\U00011046', 9),
+ ('\U000110b9', '\U000110b9', 9), ('\U000110ba', '\U000110ba', 7),
+ ('\U00011100', '\U00011102', 230), ('\U00011133', '\U00011134', 9),
+ ('\U000111c0', '\U000111c0', 9), ('\U000116b6', '\U000116b6', 9),
+ ('\U000116b7', '\U000116b7', 7), ('\U0001d165', '\U0001d166', 216),
+ ('\U0001d167', '\U0001d169', 1), ('\U0001d16d', '\U0001d16d', 226),
+ ('\U0001d16e', '\U0001d172', 216), ('\U0001d17b', '\U0001d182', 220),
+ ('\U0001d185', '\U0001d189', 230), ('\U0001d18a', '\U0001d18b', 220),
+ ('\U0001d1aa', '\U0001d1ad', 230), ('\U0001d242', '\U0001d244', 230)
+ ];
+
+ pub fn canonical_combining_class(c: char) -> u8 {
+ bsearch_range_value_table(c, combining_class_table)
+ }
+}
--- /dev/null
+// 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.
+
+//! An owned, growable vector.
+
+use core::prelude::*;
+
+use alloc::heap::{allocate, reallocate, deallocate};
+use RawVec = core::raw::Vec;
+use core::raw::Slice;
+use core::cmp::max;
+use core::default::Default;
+use core::fmt;
+use core::mem;
+use core::num::{CheckedMul, CheckedAdd};
+use core::num;
+use core::ptr;
+use core::uint;
+
+use slice::{MutableTotalOrdVector, OwnedVector, MutableVectorAllocating};
+use slice::{Items, MutItems};
+
+/// An owned, growable vector.
+///
+/// # Examples
+///
+/// ```rust
+/// # use std::vec::Vec;
+/// let mut vec = Vec::new();
+/// vec.push(1);
+/// vec.push(2);
+///
+/// assert_eq!(vec.len(), 2);
+/// assert_eq!(vec.get(0), &1);
+///
+/// assert_eq!(vec.pop(), Some(2));
+/// assert_eq!(vec.len(), 1);
+/// ```
+///
+/// The `vec!` macro is provided to make initialization more convenient:
+///
+/// ```rust
+/// let mut vec = vec!(1, 2, 3);
+/// vec.push(4);
+/// assert_eq!(vec, vec!(1, 2, 3, 4));
+/// ```
+#[unsafe_no_drop_flag]
+pub struct Vec<T> {
+ len: uint,
+ cap: uint,
+ ptr: *mut T
+}
+
+impl<T> Vec<T> {
+ /// Constructs a new, empty `Vec`.
+ ///
+ /// The vector will not allocate until elements are pushed onto it.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let mut vec: Vec<int> = Vec::new();
+ /// ```
+ #[inline]
+ pub fn new() -> Vec<T> {
+ Vec { len: 0, cap: 0, ptr: 0 as *mut T }
+ }
+
+ /// Constructs a new, empty `Vec` with the specified capacity.
+ ///
+ /// The vector will be able to hold exactly `capacity` elements without
+ /// reallocating. If `capacity` is 0, the vector will not allocate.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let vec: Vec<int> = Vec::with_capacity(10);
+ /// ```
+ pub fn with_capacity(capacity: uint) -> Vec<T> {
+ if mem::size_of::<T>() == 0 {
+ Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T }
+ } else if capacity == 0 {
+ Vec::new()
+ } else {
+ let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
+ "capacity overflow");
+ let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
+ Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
+ }
+ }
+
+ /// Creates and initializes a `Vec`.
+ ///
+ /// Creates a `Vec` of size `length` and initializes the elements to the
+ /// value returned by the closure `op`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let vec = Vec::from_fn(3, |idx| idx * 2);
+ /// assert_eq!(vec, vec!(0, 2, 4));
+ /// ```
+ pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> {
+ unsafe {
+ let mut xs = Vec::with_capacity(length);
+ while xs.len < length {
+ mem::overwrite(xs.as_mut_slice().unsafe_mut_ref(xs.len),
+ op(xs.len));
+ xs.len += 1;
+ }
+ xs
+ }
+ }
+
+ /// Create a `Vec<T>` directly from the raw constituents.
+ ///
+ /// This is highly unsafe:
+ ///
+ /// - if `ptr` is null, then `length` and `capacity` should be 0
+ /// - `ptr` must point to an allocation of size `capacity`
+ /// - there must be `length` valid instances of type `T` at the
+ /// beginning of that allocation
+ /// - `ptr` must be allocated by the default `Vec` allocator
+ pub unsafe fn from_raw_parts(length: uint, capacity: uint,
+ ptr: *mut T) -> Vec<T> {
+ Vec { len: length, cap: capacity, ptr: ptr }
+ }
+
+ /// Consumes the `Vec`, partitioning it based on a predicate.
+ ///
+ /// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A`
+ /// satisfy `f` and all elements of `B` do not. The order of elements is
+ /// preserved.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3, 4);
+ /// let (even, odd) = vec.partition(|&n| n % 2 == 0);
+ /// assert_eq!(even, vec!(2, 4));
+ /// assert_eq!(odd, vec!(1, 3));
+ /// ```
+ #[inline]
+ pub fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
+ let mut lefts = Vec::new();
+ let mut rights = Vec::new();
+
+ for elt in self.move_iter() {
+ if f(&elt) {
+ lefts.push(elt);
+ } else {
+ rights.push(elt);
+ }
+ }
+
+ (lefts, rights)
+ }
+}
+
+impl<T: Clone> Vec<T> {
+ /// Iterates over the `second` vector, copying each element and appending it to
+ /// the `first`. Afterwards, the `first` is then returned for use again.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2);
+ /// let vec = vec.append([3, 4]);
+ /// assert_eq!(vec, vec!(1, 2, 3, 4));
+ /// ```
+ #[inline]
+ pub fn append(mut self, second: &[T]) -> Vec<T> {
+ self.push_all(second);
+ self
+ }
+
+ /// Constructs a `Vec` by cloning elements of a slice.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let slice = [1, 2, 3];
+ /// let vec = Vec::from_slice(slice);
+ /// ```
+ pub fn from_slice(values: &[T]) -> Vec<T> {
+ values.iter().map(|x| x.clone()).collect()
+ }
+
+ /// Constructs a `Vec` with copies of a value.
+ ///
+ /// Creates a `Vec` with `length` copies of `value`.
+ ///
+ /// # Example
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let vec = Vec::from_elem(3, "hi");
+ /// println!("{}", vec); // prints [hi, hi, hi]
+ /// ```
+ pub fn from_elem(length: uint, value: T) -> Vec<T> {
+ unsafe {
+ let mut xs = Vec::with_capacity(length);
+ while xs.len < length {
+ mem::overwrite(xs.as_mut_slice().unsafe_mut_ref(xs.len),
+ value.clone());
+ xs.len += 1;
+ }
+ xs
+ }
+ }
+
+ /// Appends all elements in a slice to the `Vec`.
+ ///
+ /// Iterates over the slice `other`, clones each element, and then appends
+ /// it to this `Vec`. The `other` vector is traversed in-order.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1);
+ /// vec.push_all([2, 3, 4]);
+ /// assert_eq!(vec, vec!(1, 2, 3, 4));
+ /// ```
+ #[inline]
+ pub fn push_all(&mut self, other: &[T]) {
+ self.extend(other.iter().map(|e| e.clone()));
+ }
+
+ /// Grows the `Vec` in-place.
+ ///
+ /// Adds `n` copies of `value` to the `Vec`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!("hello");
+ /// vec.grow(2, &("world"));
+ /// assert_eq!(vec, vec!("hello", "world", "world"));
+ /// ```
+ pub fn grow(&mut self, n: uint, value: &T) {
+ let new_len = self.len() + n;
+ self.reserve(new_len);
+ let mut i: uint = 0u;
+
+ while i < n {
+ self.push((*value).clone());
+ i += 1u;
+ }
+ }
+
+ /// Sets the value of a vector element at a given index, growing the vector
+ /// as needed.
+ ///
+ /// Sets the element at position `index` to `value`. If `index` is past the
+ /// end of the vector, expands the vector by replicating `initval` to fill
+ /// the intervening space.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!("a", "b", "c");
+ /// vec.grow_set(1, &("fill"), "d");
+ /// vec.grow_set(4, &("fill"), "e");
+ /// assert_eq!(vec, vec!("a", "d", "c", "fill", "e"));
+ /// ```
+ pub fn grow_set(&mut self, index: uint, initval: &T, value: T) {
+ let l = self.len();
+ if index >= l {
+ self.grow(index - l + 1u, initval);
+ }
+ *self.get_mut(index) = value;
+ }
+
+ /// Partitions a vector based on a predicate.
+ ///
+ /// Clones the elements of the vector, partitioning them into two `Vec`s
+ /// `(A,B)`, where all elements of `A` satisfy `f` and all elements of `B`
+ /// do not. The order of elements is preserved.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3, 4);
+ /// let (even, odd) = vec.partitioned(|&n| n % 2 == 0);
+ /// assert_eq!(even, vec!(2, 4));
+ /// assert_eq!(odd, vec!(1, 3));
+ /// ```
+ pub fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
+ let mut lefts = Vec::new();
+ let mut rights = Vec::new();
+
+ for elt in self.iter() {
+ if f(elt) {
+ lefts.push(elt.clone());
+ } else {
+ rights.push(elt.clone());
+ }
+ }
+
+ (lefts, rights)
+ }
+}
+
+impl<T:Clone> Clone for Vec<T> {
+ fn clone(&self) -> Vec<T> {
+ let len = self.len;
+ let mut vector = Vec::with_capacity(len);
+ // Unsafe code so this can be optimised to a memcpy (or something
+ // similarly fast) when T is Copy. LLVM is easily confused, so any
+ // extra operations during the loop can prevent this optimisation
+ {
+ let this_slice = self.as_slice();
+ while vector.len < len {
+ unsafe {
+ mem::overwrite(
+ vector.as_mut_slice().unsafe_mut_ref(vector.len),
+ this_slice.unsafe_ref(vector.len).clone());
+ }
+ vector.len += 1;
+ }
+ }
+ vector
+ }
+
+ fn clone_from(&mut self, other: &Vec<T>) {
+ // drop anything in self that will not be overwritten
+ if self.len() > other.len() {
+ self.truncate(other.len())
+ }
+
+ // reuse the contained values' allocations/resources.
+ for (place, thing) in self.mut_iter().zip(other.iter()) {
+ place.clone_from(thing)
+ }
+
+ // self.len <= other.len due to the truncate above, so the
+ // slice here is always in-bounds.
+ let len = self.len();
+ self.extend(other.slice_from(len).iter().map(|x| x.clone()));
+ }
+}
+
+impl<T> FromIterator<T> for Vec<T> {
+ fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
+ let (lower, _) = iterator.size_hint();
+ let mut vector = Vec::with_capacity(lower);
+ for element in iterator {
+ vector.push(element)
+ }
+ vector
+ }
+}
+
+impl<T> Extendable<T> for Vec<T> {
+ fn extend<I: Iterator<T>>(&mut self, mut iterator: I) {
+ let (lower, _) = iterator.size_hint();
+ self.reserve_additional(lower);
+ for element in iterator {
+ self.push(element)
+ }
+ }
+}
+
+impl<T: PartialEq> PartialEq for Vec<T> {
+ #[inline]
+ fn eq(&self, other: &Vec<T>) -> bool {
+ self.as_slice() == other.as_slice()
+ }
+}
+
+impl<T: PartialOrd> PartialOrd for Vec<T> {
+ #[inline]
+ fn lt(&self, other: &Vec<T>) -> bool {
+ self.as_slice() < other.as_slice()
+ }
+}
+
+impl<T: Eq> Eq for Vec<T> {}
+
+impl<T: Ord> Ord for Vec<T> {
+ #[inline]
+ fn cmp(&self, other: &Vec<T>) -> Ordering {
+ self.as_slice().cmp(&other.as_slice())
+ }
+}
+
+impl<T> Container for Vec<T> {
+ #[inline]
+ fn len(&self) -> uint {
+ self.len
+ }
+}
+
+// FIXME: #13996: need a way to mark the return value as `noalias`
+#[inline(never)]
+unsafe fn alloc_or_realloc<T>(ptr: *mut T, size: uint, old_size: uint) -> *mut T {
+ if old_size == 0 {
+ allocate(size, mem::min_align_of::<T>()) as *mut T
+ } else {
+ reallocate(ptr as *mut u8, size,
+ mem::min_align_of::<T>(), old_size) as *mut T
+ }
+}
+
+#[inline]
+unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
+ if mem::size_of::<T>() != 0 {
+ deallocate(ptr as *mut u8,
+ len * mem::size_of::<T>(),
+ mem::min_align_of::<T>())
+ }
+}
+
+impl<T> Vec<T> {
+ /// Returns the number of elements the vector can hold without
+ /// reallocating.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let vec: Vec<int> = Vec::with_capacity(10);
+ /// assert_eq!(vec.capacity(), 10);
+ /// ```
+ #[inline]
+ pub fn capacity(&self) -> uint {
+ self.cap
+ }
+
+ /// Reserves capacity for at least `n` additional elements in the given
+ /// vector.
+ ///
+ /// # Failure
+ ///
+ /// Fails if the new capacity overflows `uint`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let mut vec: Vec<int> = vec!(1);
+ /// vec.reserve_additional(10);
+ /// assert!(vec.capacity() >= 11);
+ /// ```
+ pub fn reserve_additional(&mut self, extra: uint) {
+ if self.cap - self.len < extra {
+ match self.len.checked_add(&extra) {
+ None => fail!("Vec::reserve_additional: `uint` overflow"),
+ Some(new_cap) => self.reserve(new_cap)
+ }
+ }
+ }
+
+ /// Reserves capacity for at least `n` elements in the given vector.
+ ///
+ /// This function will over-allocate in order to amortize the allocation
+ /// costs in scenarios where the caller may need to repeatedly reserve
+ /// additional space.
+ ///
+ /// If the capacity for `self` is already equal to or greater than the
+ /// requested capacity, then no action is taken.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// vec.reserve(10);
+ /// assert!(vec.capacity() >= 10);
+ /// ```
+ pub fn reserve(&mut self, capacity: uint) {
+ if capacity >= self.len {
+ self.reserve_exact(num::next_power_of_two(capacity))
+ }
+ }
+
+ /// Reserves capacity for exactly `capacity` elements in the given vector.
+ ///
+ /// If the capacity for `self` is already equal to or greater than the
+ /// requested capacity, then no action is taken.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::vec::Vec;
+ /// let mut vec: Vec<int> = Vec::with_capacity(10);
+ /// vec.reserve_exact(11);
+ /// assert_eq!(vec.capacity(), 11);
+ /// ```
+ pub fn reserve_exact(&mut self, capacity: uint) {
+ if mem::size_of::<T>() == 0 { return }
+
+ if capacity > self.cap {
+ let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
+ "capacity overflow");
+ unsafe {
+ self.ptr = alloc_or_realloc(self.ptr, size,
+ self.cap * mem::size_of::<T>());
+ }
+ self.cap = capacity;
+ }
+ }
+
+ /// Shrink the capacity of the vector as much as possible
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// vec.shrink_to_fit();
+ /// ```
+ pub fn shrink_to_fit(&mut self) {
+ if mem::size_of::<T>() == 0 { return }
+
+ if self.len == 0 {
+ if self.cap != 0 {
+ unsafe {
+ dealloc(self.ptr, self.cap)
+ }
+ self.cap = 0;
+ }
+ } else {
+ unsafe {
+ // Overflow check is unnecessary as the vector is already at
+ // least this large.
+ self.ptr = reallocate(self.ptr as *mut u8,
+ self.len * mem::size_of::<T>(),
+ mem::min_align_of::<T>(),
+ self.cap * mem::size_of::<T>()) as *mut T;
+ }
+ self.cap = self.len;
+ }
+ }
+
+ /// Remove the last element from a vector and return it, or `None` if it is
+ /// empty.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// assert_eq!(vec.pop(), Some(3));
+ /// assert_eq!(vec, vec!(1, 2));
+ /// ```
+ #[inline]
+ pub fn pop(&mut self) -> Option<T> {
+ if self.len == 0 {
+ None
+ } else {
+ unsafe {
+ self.len -= 1;
+ Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
+ }
+ }
+ }
+
+ /// Append an element to a vector.
+ ///
+ /// # Failure
+ ///
+ /// Fails if the number of elements in the vector overflows a `uint`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2);
+ /// vec.push(3);
+ /// assert_eq!(vec, vec!(1, 2, 3));
+ /// ```
+ #[inline]
+ pub fn push(&mut self, value: T) {
+ if mem::size_of::<T>() == 0 {
+ // zero-size types consume no memory, so we can't rely on the address space running out
+ self.len = ::expect(self.len.checked_add(&1), "length overflow");
+ unsafe { mem::forget(value); }
+ return
+ }
+ if self.len == self.cap {
+ let old_size = self.cap * mem::size_of::<T>();
+ let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
+ if old_size > size { fail!("capacity overflow") }
+ unsafe {
+ self.ptr = alloc_or_realloc(self.ptr, size,
+ self.cap * mem::size_of::<T>());
+ }
+ self.cap = max(self.cap, 2) * 2;
+ }
+
+ unsafe {
+ let end = (self.ptr as *T).offset(self.len as int) as *mut T;
+ mem::overwrite(&mut *end, value);
+ self.len += 1;
+ }
+ }
+
+ /// Appends one element to the vector provided. The vector itself is then
+ /// returned for use again.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2);
+ /// let vec = vec.append_one(3);
+ /// assert_eq!(vec, vec!(1, 2, 3));
+ /// ```
+ #[inline]
+ pub fn append_one(mut self, x: T) -> Vec<T> {
+ self.push(x);
+ self
+ }
+
+ /// Shorten a vector, dropping excess elements.
+ ///
+ /// If `len` is greater than the vector's current length, this has no
+ /// effect.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3, 4);
+ /// vec.truncate(2);
+ /// assert_eq!(vec, vec!(1, 2));
+ /// ```
+ pub fn truncate(&mut self, len: uint) {
+ unsafe {
+ // drop any extra elements
+ while len < self.len {
+ // decrement len before the read(), so a failure on Drop doesn't
+ // re-drop the just-failed value.
+ self.len -= 1;
+ ptr::read(self.as_slice().unsafe_ref(self.len));
+ }
+ }
+ }
+
+ /// Work with `self` as a mutable slice.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// fn foo(slice: &mut [int]) {}
+ ///
+ /// let mut vec = vec!(1, 2);
+ /// foo(vec.as_mut_slice());
+ /// ```
+ #[inline]
+ pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
+ unsafe {
+ mem::transmute(Slice { data: self.as_mut_ptr() as *T, len: self.len })
+ }
+ }
+
+ /// Creates a consuming iterator, that is, one that moves each
+ /// value out of the vector (from start to end). The vector cannot
+ /// be used after calling this.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let v = vec!("a".to_string(), "b".to_string());
+ /// for s in v.move_iter() {
+ /// // s has type String, not &String
+ /// println!("{}", s);
+ /// }
+ /// ```
+ #[inline]
+ pub fn move_iter(self) -> MoveItems<T> {
+ unsafe {
+ let iter = mem::transmute(self.as_slice().iter());
+ let ptr = self.ptr;
+ let cap = self.cap;
+ mem::forget(self);
+ MoveItems { allocation: ptr, cap: cap, iter: iter }
+ }
+ }
+
+
+ /// Sets the length of a vector.
+ ///
+ /// This will explicitly set the size of the vector, without actually
+ /// modifying its buffers, so it is up to the caller to ensure that the
+ /// vector is actually the specified size.
+ #[inline]
+ pub unsafe fn set_len(&mut self, len: uint) {
+ self.len = len;
+ }
+
+ /// Returns a reference to the value at index `index`.
+ ///
+ /// # Failure
+ ///
+ /// Fails if `index` is out of bounds
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3);
+ /// assert!(vec.get(1) == &2);
+ /// ```
+ #[inline]
+ pub fn get<'a>(&'a self, index: uint) -> &'a T {
+ &self.as_slice()[index]
+ }
+
+ /// Returns a mutable reference to the value at index `index`.
+ ///
+ /// # Failure
+ ///
+ /// Fails if `index` is out of bounds
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// *vec.get_mut(1) = 4;
+ /// assert_eq!(vec, vec!(1, 4, 3));
+ /// ```
+ #[inline]
+ pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
+ &mut self.as_mut_slice()[index]
+ }
+
+ /// Returns an iterator over references to the elements of the vector in
+ /// order.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3);
+ /// for num in vec.iter() {
+ /// println!("{}", *num);
+ /// }
+ /// ```
+ #[inline]
+ pub fn iter<'a>(&'a self) -> Items<'a,T> {
+ self.as_slice().iter()
+ }
+
+
+ /// Returns an iterator over mutable references to the elements of the
+ /// vector in order.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// for num in vec.mut_iter() {
+ /// *num = 0;
+ /// }
+ /// ```
+ #[inline]
+ pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a,T> {
+ self.as_mut_slice().mut_iter()
+ }
+
+ /// Sort the vector, 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`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut v = vec!(5i, 4, 1, 3, 2);
+ /// v.sort_by(|a, b| a.cmp(b));
+ /// assert_eq!(v, vec!(1, 2, 3, 4, 5));
+ ///
+ /// // reverse sorting
+ /// v.sort_by(|a, b| b.cmp(a));
+ /// assert_eq!(v, vec!(5, 4, 3, 2, 1));
+ /// ```
+ #[inline]
+ pub fn sort_by(&mut self, compare: |&T, &T| -> Ordering) {
+ self.as_mut_slice().sort_by(compare)
+ }
+
+ /// Returns a slice of `self` between `start` and `end`.
+ ///
+ /// # Failure
+ ///
+ /// Fails when `start` or `end` point outside the bounds of `self`, or when
+ /// `start` > `end`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3, 4);
+ /// assert!(vec.slice(0, 2) == [1, 2]);
+ /// ```
+ #[inline]
+ pub fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] {
+ self.as_slice().slice(start, end)
+ }
+
+ /// Returns a slice containing all but the first element of the vector.
+ ///
+ /// # Failure
+ ///
+ /// Fails when the vector is empty.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3);
+ /// assert!(vec.tail() == [2, 3]);
+ /// ```
+ #[inline]
+ pub fn tail<'a>(&'a self) -> &'a [T] {
+ self.as_slice().tail()
+ }
+
+ /// Returns all but the first `n' elements of a vector.
+ ///
+ /// # Failure
+ ///
+ /// Fails when there are fewer than `n` elements in the vector.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3, 4);
+ /// assert!(vec.tailn(2) == [3, 4]);
+ /// ```
+ #[inline]
+ pub fn tailn<'a>(&'a self, n: uint) -> &'a [T] {
+ self.as_slice().tailn(n)
+ }
+
+ /// Returns a reference to the last element of a vector, or `None` if it is
+ /// empty.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3);
+ /// assert!(vec.last() == Some(&3));
+ /// ```
+ #[inline]
+ pub fn last<'a>(&'a self) -> Option<&'a T> {
+ self.as_slice().last()
+ }
+
+ /// Returns a mutable reference to the last element of a vector, or `None`
+ /// if it is empty.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// *vec.mut_last().unwrap() = 4;
+ /// assert_eq!(vec, vec!(1, 2, 4));
+ /// ```
+ #[inline]
+ pub fn mut_last<'a>(&'a mut self) -> Option<&'a mut T> {
+ self.as_mut_slice().mut_last()
+ }
+
+ /// Remove an element from anywhere in the vector and return it, replacing
+ /// it with the last element. This does not preserve ordering, but is O(1).
+ ///
+ /// Returns `None` if `index` is out of bounds.
+ ///
+ /// # Example
+ /// ```rust
+ /// let mut v = vec!("foo".to_string(), "bar".to_string(),
+ /// "baz".to_string(), "qux".to_string());
+ ///
+ /// assert_eq!(v.swap_remove(1), Some("bar".to_string()));
+ /// assert_eq!(v, vec!("foo".to_string(), "qux".to_string(), "baz".to_string()));
+ ///
+ /// assert_eq!(v.swap_remove(0), Some("foo".to_string()));
+ /// assert_eq!(v, vec!("baz".to_string(), "qux".to_string()));
+ ///
+ /// assert_eq!(v.swap_remove(2), None);
+ /// ```
+ #[inline]
+ pub fn swap_remove(&mut self, index: uint) -> Option<T> {
+ let length = self.len();
+ if index < length - 1 {
+ self.as_mut_slice().swap(index, length - 1);
+ } else if index >= length {
+ return None
+ }
+ self.pop()
+ }
+
+ /// Prepend an element to the vector.
+ ///
+ /// # Warning
+ ///
+ /// This is an O(n) operation as it requires copying every element in the
+ /// vector.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// vec.unshift(4);
+ /// assert_eq!(vec, vec!(4, 1, 2, 3));
+ /// ```
+ #[inline]
+ pub fn unshift(&mut self, element: T) {
+ self.insert(0, element)
+ }
+
+ /// Removes the first element from a vector and returns it, or `None` if
+ /// the vector is empty.
+ ///
+ /// # Warning
+ ///
+ /// This is an O(n) operation as it requires copying every element in the
+ /// vector.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// assert!(vec.shift() == Some(1));
+ /// assert_eq!(vec, vec!(2, 3));
+ /// ```
+ #[inline]
+ pub fn shift(&mut self) -> Option<T> {
+ self.remove(0)
+ }
+
+ /// Insert an element at position `index` within the vector, shifting all
+ /// elements after position i one position to the right.
+ ///
+ /// # Failure
+ ///
+ /// Fails if `index` is out of bounds of the vector.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3);
+ /// vec.insert(1, 4);
+ /// assert_eq!(vec, vec!(1, 4, 2, 3));
+ /// ```
+ pub fn insert(&mut self, index: uint, element: T) {
+ let len = self.len();
+ assert!(index <= len);
+ // space for the new element
+ self.reserve(len + 1);
+
+ unsafe { // infallible
+ // The spot to put the new value
+ {
+ let p = self.as_mut_ptr().offset(index as int);
+ // Shift everything over to make space. (Duplicating the
+ // `index`th element into two consecutive places.)
+ ptr::copy_memory(p.offset(1), &*p, len - index);
+ // Write it in, overwriting the first copy of the `index`th
+ // element.
+ mem::overwrite(&mut *p, element);
+ }
+ self.set_len(len + 1);
+ }
+ }
+
+ /// Remove and return the element at position `index` within the vector,
+ /// shifting all elements after position `index` one position to the left.
+ /// Returns `None` if `i` is out of bounds.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut v = vec!(1, 2, 3);
+ /// assert_eq!(v.remove(1), Some(2));
+ /// assert_eq!(v, vec!(1, 3));
+ ///
+ /// assert_eq!(v.remove(4), None);
+ /// // v is unchanged:
+ /// assert_eq!(v, vec!(1, 3));
+ /// ```
+ pub fn remove(&mut self, index: uint) -> Option<T> {
+ let len = self.len();
+ if index < len {
+ unsafe { // infallible
+ let ret;
+ {
+ // the place we are taking from.
+ let ptr = self.as_mut_ptr().offset(index as int);
+ // copy it out, unsafely having a copy of the value on
+ // the stack and in the vector at the same time.
+ ret = Some(ptr::read(ptr as *T));
+
+ // Shift everything down to fill in that spot.
+ ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
+ }
+ self.set_len(len - 1);
+ ret
+ }
+ } else {
+ None
+ }
+ }
+
+ /// Takes ownership of the vector `other`, moving all elements into
+ /// the current vector. This does not copy any elements, and it is
+ /// illegal to use the `other` vector after calling this method
+ /// (because it is moved here).
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(box 1);
+ /// vec.push_all_move(vec!(box 2, box 3, box 4));
+ /// assert_eq!(vec, vec!(box 1, box 2, box 3, box 4));
+ /// ```
+ pub fn push_all_move(&mut self, other: Vec<T>) {
+ self.extend(other.move_iter());
+ }
+
+ /// Returns a mutable slice of `self` between `start` and `end`.
+ ///
+ /// # Failure
+ ///
+ /// Fails when `start` or `end` point outside the bounds of `self`, or when
+ /// `start` > `end`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3, 4);
+ /// assert!(vec.mut_slice(0, 2) == [1, 2]);
+ /// ```
+ #[inline]
+ pub fn mut_slice<'a>(&'a mut self, start: uint, end: uint)
+ -> &'a mut [T] {
+ self.as_mut_slice().mut_slice(start, end)
+ }
+
+ /// Returns a mutable slice of self from `start` to the end of the vec.
+ ///
+ /// # Failure
+ ///
+ /// Fails when `start` points outside the bounds of self.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3, 4);
+ /// assert!(vec.mut_slice_from(2) == [3, 4]);
+ /// ```
+ #[inline]
+ pub fn mut_slice_from<'a>(&'a mut self, start: uint) -> &'a mut [T] {
+ self.as_mut_slice().mut_slice_from(start)
+ }
+
+ /// Returns a mutable slice of self from the start of the vec to `end`.
+ ///
+ /// # Failure
+ ///
+ /// Fails when `end` points outside the bounds of self.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3, 4);
+ /// assert!(vec.mut_slice_to(2) == [1, 2]);
+ /// ```
+ #[inline]
+ pub fn mut_slice_to<'a>(&'a mut self, end: uint) -> &'a mut [T] {
+ self.as_mut_slice().mut_slice_to(end)
+ }
+
+ /// Returns a pair of mutable slices that divides the vec 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).
+ ///
+ /// # Failure
+ ///
+ /// Fails if `mid > len`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 3, 4, 5, 6);
+ ///
+ /// // scoped to restrict the lifetime of the borrows
+ /// {
+ /// let (left, right) = vec.mut_split_at(0);
+ /// assert!(left == &mut []);
+ /// assert!(right == &mut [1, 2, 3, 4, 5, 6]);
+ /// }
+ ///
+ /// {
+ /// let (left, right) = vec.mut_split_at(2);
+ /// assert!(left == &mut [1, 2]);
+ /// assert!(right == &mut [3, 4, 5, 6]);
+ /// }
+ ///
+ /// {
+ /// let (left, right) = vec.mut_split_at(6);
+ /// assert!(left == &mut [1, 2, 3, 4, 5, 6]);
+ /// assert!(right == &mut []);
+ /// }
+ /// ```
+ #[inline]
+ pub fn mut_split_at<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]) {
+ self.as_mut_slice().mut_split_at(mid)
+ }
+
+ /// Reverse the order of elements in a vector, in place.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut v = vec!(1, 2, 3);
+ /// v.reverse();
+ /// assert_eq!(v, vec!(3, 2, 1));
+ /// ```
+ #[inline]
+ pub fn reverse(&mut self) {
+ self.as_mut_slice().reverse()
+ }
+
+ /// Returns a slice of `self` from `start` to the end of the vec.
+ ///
+ /// # Failure
+ ///
+ /// Fails when `start` points outside the bounds of self.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3);
+ /// assert!(vec.slice_from(1) == [2, 3]);
+ /// ```
+ #[inline]
+ pub fn slice_from<'a>(&'a self, start: uint) -> &'a [T] {
+ self.as_slice().slice_from(start)
+ }
+
+ /// Returns a slice of self from the start of the vec to `end`.
+ ///
+ /// # Failure
+ ///
+ /// Fails when `end` points outside the bounds of self.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3);
+ /// assert!(vec.slice_to(2) == [1, 2]);
+ /// ```
+ #[inline]
+ pub fn slice_to<'a>(&'a self, end: uint) -> &'a [T] {
+ self.as_slice().slice_to(end)
+ }
+
+ /// Returns a slice containing all but the last element of the vector.
+ ///
+ /// # Failure
+ ///
+ /// Fails if the vector is empty
+ #[inline]
+ pub fn init<'a>(&'a self) -> &'a [T] {
+ self.slice(0, self.len() - 1)
+ }
+
+
+ /// Returns an unsafe pointer to the vector's buffer.
+ ///
+ /// The caller must ensure that the vector outlives the pointer this
+ /// function returns, or else it will end up pointing to garbage.
+ ///
+ /// Modifying the vector may cause its buffer to be reallocated, which
+ /// would also make any pointers to it invalid.
+ #[inline]
+ pub fn as_ptr(&self) -> *T {
+ // If we have a 0-sized vector, then the base pointer should not be NULL
+ // because an iterator over the slice will attempt to yield the base
+ // pointer as the first element in the vector, but this will end up
+ // being Some(NULL) which is optimized to None.
+ if mem::size_of::<T>() == 0 {
+ 1 as *T
+ } else {
+ self.ptr as *T
+ }
+ }
+
+ /// Returns a mutable unsafe pointer to the vector's buffer.
+ ///
+ /// The caller must ensure that the vector outlives the pointer this
+ /// function returns, or else it will end up pointing to garbage.
+ ///
+ /// Modifying the vector may cause its buffer to be reallocated, which
+ /// would also make any pointers to it invalid.
+ #[inline]
+ pub fn as_mut_ptr(&mut self) -> *mut T {
+ // see above for the 0-size check
+ if mem::size_of::<T>() == 0 {
+ 1 as *mut T
+ } else {
+ self.ptr
+ }
+ }
+
+ /// Retains only the elements specified by the predicate.
+ ///
+ /// In other words, remove all elements `e` such that `f(&e)` returns false.
+ /// This method operates in place and preserves the order the retained elements.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1i, 2, 3, 4);
+ /// vec.retain(|x| x%2 == 0);
+ /// assert_eq!(vec, vec!(2, 4));
+ /// ```
+ pub fn retain(&mut self, f: |&T| -> bool) {
+ let len = self.len();
+ let mut del = 0u;
+ {
+ let v = self.as_mut_slice();
+
+ for i in range(0u, len) {
+ if !f(&v[i]) {
+ del += 1;
+ } else if del > 0 {
+ v.swap(i-del, i);
+ }
+ }
+ }
+ if del > 0 {
+ self.truncate(len - del);
+ }
+ }
+
+ /// Expands a vector in place, initializing the new elements to the result of a function.
+ ///
+ /// The vector is grown by `n` elements. The i-th new element are initialized to the value
+ /// returned by `f(i)` where `i` is in the range [0, n).
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(0u, 1);
+ /// vec.grow_fn(3, |i| i);
+ /// assert_eq!(vec, vec!(0, 1, 0, 1, 2));
+ /// ```
+ pub fn grow_fn(&mut self, n: uint, f: |uint| -> T) {
+ self.reserve_additional(n);
+ for i in range(0u, n) {
+ self.push(f(i));
+ }
+ }
+}
+
+impl<T:Ord> Vec<T> {
+ /// Sorts the vector in place.
+ ///
+ /// This sort is `O(n log n)` worst-case and stable, but allocates
+ /// approximately `2 * n`, where `n` is the length of `self`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(3i, 1, 2);
+ /// vec.sort();
+ /// assert_eq!(vec, vec!(1, 2, 3));
+ /// ```
+ pub fn sort(&mut self) {
+ self.as_mut_slice().sort()
+ }
+}
+
+impl<T> Mutable for Vec<T> {
+ #[inline]
+ fn clear(&mut self) {
+ self.truncate(0)
+ }
+}
+
+impl<T:PartialEq> Vec<T> {
+ /// Return true if a vector contains an element with the given value
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let vec = vec!(1, 2, 3);
+ /// assert!(vec.contains(&1));
+ /// ```
+ pub fn contains(&self, x: &T) -> bool {
+ self.as_slice().contains(x)
+ }
+
+ /// Remove consecutive repeated elements in the vector.
+ ///
+ /// If the vector is sorted, this removes all duplicates.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut vec = vec!(1, 2, 2, 3, 2);
+ /// vec.dedup();
+ /// assert_eq!(vec, vec!(1, 2, 3, 2));
+ /// ```
+ pub fn dedup(&mut self) {
+ unsafe {
+ // Although we have a mutable reference to `self`, we cannot make
+ // *arbitrary* changes. The `PartialEq` comparisons could fail, so we
+ // must ensure that the vector is in a valid state at all time.
+ //
+ // The way that we handle this is by using swaps; we iterate
+ // over all the elements, swapping as we go so that at the end
+ // the elements we wish to keep are in the front, and those we
+ // wish to reject are at the back. We can then truncate the
+ // vector. This operation is still O(n).
+ //
+ // Example: We start in this state, where `r` represents "next
+ // read" and `w` represents "next_write`.
+ //
+ // r
+ // +---+---+---+---+---+---+
+ // | 0 | 1 | 1 | 2 | 3 | 3 |
+ // +---+---+---+---+---+---+
+ // w
+ //
+ // Comparing self[r] against self[w-1], this is not a duplicate, so
+ // we swap self[r] and self[w] (no effect as r==w) and then increment both
+ // r and w, leaving us with:
+ //
+ // r
+ // +---+---+---+---+---+---+
+ // | 0 | 1 | 1 | 2 | 3 | 3 |
+ // +---+---+---+---+---+---+
+ // w
+ //
+ // Comparing self[r] against self[w-1], this value is a duplicate,
+ // so we increment `r` but leave everything else unchanged:
+ //
+ // r
+ // +---+---+---+---+---+---+
+ // | 0 | 1 | 1 | 2 | 3 | 3 |
+ // +---+---+---+---+---+---+
+ // w
+ //
+ // Comparing self[r] against self[w-1], this is not a duplicate,
+ // so swap self[r] and self[w] and advance r and w:
+ //
+ // r
+ // +---+---+---+---+---+---+
+ // | 0 | 1 | 2 | 1 | 3 | 3 |
+ // +---+---+---+---+---+---+
+ // w
+ //
+ // Not a duplicate, repeat:
+ //
+ // r
+ // +---+---+---+---+---+---+
+ // | 0 | 1 | 2 | 3 | 1 | 3 |
+ // +---+---+---+---+---+---+
+ // w
+ //
+ // Duplicate, advance r. End of vec. Truncate to w.
+
+ let ln = self.len();
+ if ln < 1 { return; }
+
+ // Avoid bounds checks by using unsafe pointers.
+ let p = self.as_mut_slice().as_mut_ptr();
+ let mut r = 1;
+ let mut w = 1;
+
+ while r < ln {
+ let p_r = p.offset(r as int);
+ let p_wm1 = p.offset((w - 1) as int);
+ if *p_r != *p_wm1 {
+ if r != w {
+ let p_w = p_wm1.offset(1);
+ mem::swap(&mut *p_r, &mut *p_w);
+ }
+ w += 1;
+ }
+ r += 1;
+ }
+
+ self.truncate(w);
+ }
+ }
+}
+
+impl<T> Vector<T> for Vec<T> {
+ /// Work with `self` as a slice.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// fn foo(slice: &[int]) {}
+ ///
+ /// let vec = vec!(1, 2);
+ /// foo(vec.as_slice());
+ /// ```
+ #[inline]
+ fn as_slice<'a>(&'a self) -> &'a [T] {
+ unsafe { mem::transmute(Slice { data: self.as_ptr(), len: self.len }) }
+ }
+}
+
+impl<T: Clone, V: Vector<T>> Add<V, Vec<T>> for Vec<T> {
+ #[inline]
+ fn add(&self, rhs: &V) -> Vec<T> {
+ let mut res = Vec::with_capacity(self.len() + rhs.as_slice().len());
+ res.push_all(self.as_slice());
+ res.push_all(rhs.as_slice());
+ res
+ }
+}
+
+#[unsafe_destructor]
+impl<T> Drop for Vec<T> {
+ fn drop(&mut self) {
+ // This is (and should always remain) a no-op if the fields are
+ // zeroed (when moving out, because of #[unsafe_no_drop_flag]).
+ if self.cap != 0 {
+ unsafe {
+ for x in self.as_mut_slice().iter() {
+ ptr::read(x);
+ }
+ dealloc(self.ptr, self.cap)
+ }
+ }
+ }
+}
+
+impl<T> Default for Vec<T> {
+ fn default() -> Vec<T> {
+ Vec::new()
+ }
+}
+
+impl<T:fmt::Show> fmt::Show for Vec<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.as_slice().fmt(f)
+ }
+}
+
+/// An iterator that moves out of a vector.
+pub struct MoveItems<T> {
+ allocation: *mut T, // the block of memory allocated for the vector
+ cap: uint, // the capacity of the vector
+ iter: Items<'static, T>
+}
+
+impl<T> Iterator<T> for MoveItems<T> {
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ unsafe {
+ self.iter.next().map(|x| ptr::read(x))
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<T> DoubleEndedIterator<T> for MoveItems<T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<T> {
+ unsafe {
+ self.iter.next_back().map(|x| ptr::read(x))
+ }
+ }
+}
+
+#[unsafe_destructor]
+impl<T> Drop for MoveItems<T> {
+ fn drop(&mut self) {
+ // destroy the remaining elements
+ if self.cap != 0 {
+ for _x in *self {}
+ unsafe {
+ dealloc(self.allocation, self.cap);
+ }
+ }
+ }
+}
+
+/**
+ * Convert an iterator of pairs into a pair of vectors.
+ *
+ * Returns a tuple containing two vectors where the i-th element of the first
+ * vector contains the first element of the i-th tuple of the input iterator,
+ * and the i-th element of the second vector contains the second element
+ * of the i-th tuple of the input iterator.
+ */
+pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
+ let (lo, _) = iter.size_hint();
+ let mut ts = Vec::with_capacity(lo);
+ let mut us = Vec::with_capacity(lo);
+ for (t, u) in iter {
+ ts.push(t);
+ us.push(u);
+ }
+ (ts, us)
+}
+
+/// Mechanism to convert from a `Vec<T>` to a `[T]`.
+///
+/// In a post-DST world this will be used to convert to any `Ptr<[T]>`.
+///
+/// This could be implemented on more types than just pointers to vectors, but
+/// the recommended approach for those types is to implement `FromIterator`.
+// FIXME(#12938): Update doc comment when DST lands
+pub trait FromVec<T> {
+ /// Convert a `Vec<T>` into the receiver type.
+ fn from_vec(v: Vec<T>) -> Self;
+}
+
+impl<T> FromVec<T> for ~[T] {
+ fn from_vec(mut v: Vec<T>) -> ~[T] {
+ let len = v.len();
+ let data_size = len.checked_mul(&mem::size_of::<T>());
+ let data_size = ::expect(data_size, "overflow in from_vec()");
+ let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
+ let size = ::expect(size, "overflow in from_vec()");
+
+ // In a post-DST world, we can attempt to reuse the Vec allocation by calling
+ // shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
+ // diffrent than what we're doing manually here.
+
+ let vp = v.as_mut_ptr();
+
+ unsafe {
+ let ret = allocate(size, 8) as *mut RawVec<()>;
+
+ let a_size = mem::size_of::<T>();
+ let a_size = if a_size == 0 {1} else {a_size};
+ (*ret).fill = len * a_size;
+ (*ret).alloc = len * a_size;
+
+ ptr::copy_nonoverlapping_memory(&mut (*ret).data as *mut _ as *mut u8,
+ vp as *u8, data_size);
+
+ // we've transferred ownership of the contents from v, but we can't drop it
+ // as it still needs to free its own allocation.
+ v.set_len(0);
+
+ mem::transmute(ret)
+ }
+ }
+}
+
+/// Unsafe operations
+pub mod raw {
+ use super::Vec;
+ use core::ptr;
+
+ /// Constructs a vector from an unsafe pointer to a buffer.
+ ///
+ /// The elements of the buffer are copied into the vector without cloning,
+ /// as if `ptr::read()` were called on them.
+ #[inline]
+ pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> Vec<T> {
+ let mut dst = Vec::with_capacity(elts);
+ dst.set_len(elts);
+ ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
+ dst
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+ use prelude::*;
+ use mem::size_of;
+ use kinds::marker;
+ use super::{unzip, raw, FromVec};
+
+ #[test]
+ fn test_small_vec_struct() {
+ assert!(size_of::<Vec<u8>>() == size_of::<uint>() * 3);
+ }
+
+ #[test]
+ fn test_double_drop() {
+ struct TwoVec<T> {
+ x: Vec<T>,
+ y: Vec<T>
+ }
+
+ struct DropCounter<'a> {
+ count: &'a mut int
+ }
+
+ #[unsafe_destructor]
+ impl<'a> Drop for DropCounter<'a> {
+ fn drop(&mut self) {
+ *self.count += 1;
+ }
+ }
+
+ let mut count_x @ mut count_y = 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_additional() {
+ let mut v = Vec::new();
+ assert_eq!(v.capacity(), 0);
+
+ v.reserve_additional(2);
+ assert!(v.capacity() >= 2);
+
+ for i in range(0, 16) {
+ v.push(i);
+ }
+
+ assert!(v.capacity() >= 16);
+ v.reserve_additional(16);
+ assert!(v.capacity() >= 32);
+
+ v.push(16);
+
+ v.reserve_additional(16);
+ assert!(v.capacity() >= 33)
+ }
+
+ #[test]
+ fn test_extend() {
+ let mut v = Vec::new();
+ let mut w = Vec::new();
+
+ v.extend(range(0, 3));
+ for i in range(0, 3) { w.push(i) }
+
+ assert_eq!(v, w);
+
+ v.extend(range(3, 10));
+ for i in range(3, 10) { w.push(i) }
+
+ assert_eq!(v, w);
+ }
+
+ #[test]
+ fn test_mut_slice_from() {
+ let mut values = Vec::from_slice([1u8,2,3,4,5]);
+ {
+ let slice = values.mut_slice_from(2);
+ assert!(slice == [3, 4, 5]);
+ for p in slice.mut_iter() {
+ *p += 2;
+ }
+ }
+
+ assert!(values.as_slice() == [1, 2, 5, 6, 7]);
+ }
+
+ #[test]
+ fn test_mut_slice_to() {
+ let mut values = Vec::from_slice([1u8,2,3,4,5]);
+ {
+ let slice = values.mut_slice_to(2);
+ assert!(slice == [1, 2]);
+ for p in slice.mut_iter() {
+ *p += 1;
+ }
+ }
+
+ assert!(values.as_slice() == [2, 3, 3, 4, 5]);
+ }
+
+ #[test]
+ fn test_mut_split_at() {
+ let mut values = Vec::from_slice([1u8,2,3,4,5]);
+ {
+ let (left, right) = values.mut_split_at(2);
+ assert!(left.slice(0, left.len()) == [1, 2]);
+ for p in left.mut_iter() {
+ *p += 1;
+ }
+
+ assert!(right.slice(0, right.len()) == [3, 4, 5]);
+ for p in right.mut_iter() {
+ *p += 2;
+ }
+ }
+
+ assert!(values == Vec::from_slice([2u8, 3, 5, 6, 7]));
+ }
+
+ #[test]
+ fn test_clone() {
+ let v: Vec<int> = 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 1, box 2, box 3);
+ let two = 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_grow_fn() {
+ let mut v = Vec::from_slice([0u, 1]);
+ v.grow_fn(3, |i| i);
+ assert!(v == Vec::from_slice([0u, 1, 0, 1, 2]));
+ }
+
+ #[test]
+ fn test_retain() {
+ let mut vec = Vec::from_slice([1u, 2, 3, 4]);
+ vec.retain(|x| x%2 == 0);
+ assert!(vec == Vec::from_slice([2u, 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().len(), 0);
+ v.push(());
+ assert_eq!(v.iter().len(), 1);
+ v.push(());
+ assert_eq!(v.iter().len(), 2);
+
+ for &() in v.iter() {}
+
+ assert_eq!(v.mut_iter().len(), 2);
+ v.push(());
+ assert_eq!(v.mut_iter().len(), 3);
+ v.push(());
+ assert_eq!(v.mut_iter().len(), 4);
+
+ for &() in v.mut_iter() {}
+ unsafe { v.set_len(0); }
+ assert_eq!(v.mut_iter().len(), 0);
+ }
+
+ #[test]
+ fn test_partition() {
+ assert_eq!(vec![].partition(|x: &int| *x < 3), (vec![], vec![]));
+ assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+ }
+
+ #[test]
+ fn test_partitioned() {
+ assert_eq!(vec![].partitioned(|x: &int| *x < 3), (vec![], vec![]))
+ assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+ }
+
+ #[test]
+ fn test_zip_unzip() {
+ let z1 = vec![(1, 4), (2, 5), (3, 6)];
+
+ let (left, right) = unzip(z1.iter().map(|&x| x));
+
+ let (left, right) = (left.as_slice(), right.as_slice());
+ 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 = raw::from_buf(ptr, 3u);
+ assert_eq!(b, vec![1, 2, 3]);
+
+ // Test on-heap copy-from-buf.
+ let c = box [1, 2, 3, 4, 5];
+ let ptr = c.as_ptr();
+ let d = raw::from_buf(ptr, 5u);
+ assert_eq!(d, vec![1, 2, 3, 4, 5]);
+ }
+ }
+
+ #[test]
+ fn test_from_vec() {
+ let a = vec![1u, 2, 3];
+ let b: ~[uint] = FromVec::from_vec(a);
+ assert_eq!(b.as_slice(), &[1u, 2, 3]);
+
+ let a = vec![];
+ let b: ~[u8] = FromVec::from_vec(a);
+ assert_eq!(b.as_slice(), &[]);
+
+ let a = vec!["one".to_string(), "two".to_string()];
+ let b: ~[String] = FromVec::from_vec(a);
+ assert_eq!(b.as_slice(), &["one".to_string(), "two".to_string()]);
+
+ struct Foo {
+ x: uint,
+ nocopy: marker::NoCopy
+ }
+
+ let a = vec![Foo{x: 42, nocopy: marker::NoCopy}, Foo{x: 84, nocopy: marker::NoCopy}];
+ let b: ~[Foo] = FromVec::from_vec(a);
+ assert_eq!(b.len(), 2);
+ assert_eq!(b[0].x, 42);
+ assert_eq!(b[1].x, 84);
+ }
+
+ #[test]
+ fn test_vec_truncate_drop() {
+ static mut drops: uint = 0;
+ struct Elem(int);
+ 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_fail]
+ fn test_vec_truncate_fail() {
+ struct BadElem(int);
+ impl Drop for BadElem {
+ fn drop(&mut self) {
+ let BadElem(ref mut x) = *self;
+ if *x == 0xbadbeef {
+ fail!("BadElem failure: 0xbadbeef")
+ }
+ }
+ }
+
+ let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
+ v.truncate(0);
+ }
+}
//! types to reintroduce mutability:
//!
//! ```
-//! extern crate collections;
-//!
-//! use collections::HashMap;
+//! use std::collections::HashMap;
//! use std::cell::RefCell;
//! use std::rc::Rc;
//!
//! to take `&self`.
//!
//! ```
-//! extern crate collections;
-//!
//! use std::cell::RefCell;
//!
//! struct Graph {
pub use self::num::Radix;
pub use self::num::RadixFmt;
-macro_rules! write(
- ($dst:expr, $($arg:tt)*) => ({
- format_args!(|args| { $dst.write_fmt(args) }, $($arg)*)
- })
-)
-
mod num;
mod float;
pub mod rt;
);
)
+/// Runtime assertion, only without `--cfg ndebug`
+#[macro_export]
+macro_rules! debug_assert(
+ ($(a:tt)*) => ({
+ if cfg!(not(ndebug)) {
+ assert!($($a)*);
+ }
+ })
+)
+
/// Runtime assertion for equality, for details see std::macros
+#[macro_export]
macro_rules! assert_eq(
($cond1:expr, $cond2:expr) => ({
let c1 = $cond1;
})
)
+/// Runtime assertion for equality, only without `--cfg ndebug`
+#[macro_export]
+macro_rules! debug_assert_eq(
+ ($($a:tt)*) => ({
+ if cfg!(not(ndebug)) {
+ assert_eq!($($a)*);
+ }
+ })
+)
+
/// Runtime assertion, disableable at compile time
#[macro_export]
macro_rules! debug_assert(
#[cfg(test)]
macro_rules! format( ($($arg:tt)*) => (format_args!(::fmt::format, $($arg)*)) )
+
+/// Write some formatted data into a stream.
+///
+/// Identical to the macro in `std::macros`
+#[macro_export]
+macro_rules! write(
+ ($dst:expr, $($arg:tt)*) => ({
+ format_args_method!($dst, write_fmt, $($arg)*)
+ })
+)
--- /dev/null
+// 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.
+
+//! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types)
+
+use clone::Clone;
+use cmp::{max, Eq, Equiv, PartialEq};
+use container::{Container, Mutable, Set, MutableSet, Map, MutableMap};
+use default::Default;
+use fmt::Show;
+use fmt;
+use hash::{Hash, Hasher, sip};
+use iter::{Iterator, FilterMap, Chain, Repeat, Zip, Extendable};
+use iter::{range, range_inclusive, FromIterator};
+use iter;
+use mem::replace;
+use num;
+use option::{Some, None, Option};
+use rand::Rng;
+use rand;
+use result::{Ok, Err};
+
+mod table {
+ use clone::Clone;
+ use cmp;
+ use hash::{Hash, Hasher};
+ use iter::range_step_inclusive;
+ use iter::{Iterator, range};
+ use kinds::marker;
+ use mem::{min_align_of, size_of};
+ use mem::{overwrite, transmute};
+ use num::{CheckedMul, is_power_of_two};
+ use ops::Drop;
+ use option::{Some, None, Option, Expect};
+ use ptr::RawPtr;
+ use ptr::set_memory;
+ use ptr;
+ use rt::heap::{allocate, deallocate};
+
+ static EMPTY_BUCKET: u64 = 0u64;
+
+ /// The raw hashtable, providing safe-ish access to the unzipped and highly
+ /// optimized arrays of hashes, keys, and values.
+ ///
+ /// This design uses less memory and is a lot faster than the naive
+ /// `Vec<Option<u64, K, V>>`, because we don't pay for the overhead of an
+ /// option on every element, and we get a generally more cache-aware design.
+ ///
+ /// Key invariants of this structure:
+ ///
+ /// - if hashes[i] == EMPTY_BUCKET, then keys[i] and vals[i] have
+ /// 'undefined' contents. Don't read from them. This invariant is
+ /// enforced outside this module with the `EmptyIndex`, `FullIndex`,
+ /// and `SafeHash` types.
+ ///
+ /// - An `EmptyIndex` is only constructed for a bucket at an index with
+ /// a hash of EMPTY_BUCKET.
+ ///
+ /// - A `FullIndex` is only constructed for a bucket at an index with a
+ /// non-EMPTY_BUCKET hash.
+ ///
+ /// - A `SafeHash` is only constructed for non-`EMPTY_BUCKET` hash. We get
+ /// around hashes of zero by changing them to 0x8000_0000_0000_0000,
+ /// which will likely map to the same bucket, while not being confused
+ /// with "empty".
+ ///
+ /// - All three "arrays represented by pointers" are the same length:
+ /// `capacity`. This is set at creation and never changes. The arrays
+ /// are unzipped to save space (we don't have to pay for the padding
+ /// between odd sized elements, such as in a map from u64 to u8), and
+ /// be more cache aware (scanning through 8 hashes brings in 2 cache
+ /// lines, since they're all right beside each other).
+ ///
+ /// You can kind of think of this module/data structure as a safe wrapper
+ /// around just the "table" part of the hashtable. It enforces some
+ /// invariants at the type level and employs some performance trickery,
+ /// but in general is just a tricked out `Vec<Option<u64, K, V>>`.
+ ///
+ /// FIXME(cgaebel):
+ ///
+ /// Feb 11, 2014: This hashtable was just implemented, and, hard as I tried,
+ /// isn't yet totally safe. There's a "known exploit" that you can create
+ /// multiple FullIndexes for a bucket, `take` one, and then still `take`
+ /// the other causing undefined behavior. Currently, there's no story
+ /// for how to protect against this statically. Therefore, there are asserts
+ /// on `take`, `get`, `get_mut`, and `put` which check the bucket state.
+ /// With time, and when we're confident this works correctly, they should
+ /// be removed. Also, the bounds check in `peek` is especially painful,
+ /// as that's called in the innermost loops of the hashtable and has the
+ /// potential to be a major performance drain. Remove this too.
+ ///
+ /// Or, better than remove, only enable these checks for debug builds.
+ /// There's currently no "debug-only" asserts in rust, so if you're reading
+ /// this and going "what? of course there are debug-only asserts!", then
+ /// please make this use them!
+ #[unsafe_no_drop_flag]
+ pub struct RawTable<K, V> {
+ capacity: uint,
+ size: uint,
+ hashes: *mut u64,
+ keys: *mut K,
+ vals: *mut V,
+ }
+
+ /// Represents an index into a `RawTable` with no key or value in it.
+ pub struct EmptyIndex {
+ idx: int,
+ nocopy: marker::NoCopy,
+ }
+
+ /// Represents an index into a `RawTable` with a key, value, and hash
+ /// in it.
+ pub struct FullIndex {
+ idx: int,
+ hash: SafeHash,
+ nocopy: marker::NoCopy,
+ }
+
+ impl FullIndex {
+ /// Since we get the hash for free whenever we check the bucket state,
+ /// this function is provided for fast access, letting us avoid
+ /// redundant trips back to the hashtable.
+ #[inline(always)]
+ pub fn hash(&self) -> SafeHash { self.hash }
+
+ /// Same comment as with `hash`.
+ #[inline(always)]
+ pub fn raw_index(&self) -> uint { self.idx as uint }
+ }
+
+ /// Represents the state of a bucket: it can either have a key/value
+ /// pair (be full) or not (be empty). You cannot `take` empty buckets,
+ /// and you cannot `put` into full buckets.
+ pub enum BucketState {
+ Empty(EmptyIndex),
+ Full(FullIndex),
+ }
+
+ /// A hash that is not zero, since we use a hash of zero to represent empty
+ /// buckets.
+ #[deriving(PartialEq)]
+ pub struct SafeHash {
+ hash: u64,
+ }
+
+ impl SafeHash {
+ /// Peek at the hash value, which is guaranteed to be non-zero.
+ #[inline(always)]
+ pub fn inspect(&self) -> u64 { self.hash }
+ }
+
+ /// We need to remove hashes of 0. That's reserved for empty buckets.
+ /// This function wraps up `hash_keyed` to be the only way outside this
+ /// module to generate a SafeHash.
+ pub fn make_hash<T: Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
+ match hasher.hash(t) {
+ // This constant is exceedingly likely to hash to the same
+ // bucket, but it won't be counted as empty!
+ EMPTY_BUCKET => SafeHash { hash: 0x8000_0000_0000_0000 },
+ h => SafeHash { hash: h },
+ }
+ }
+
+ fn round_up_to_next(unrounded: uint, target_alignment: uint) -> uint {
+ assert!(is_power_of_two(target_alignment));
+ (unrounded + target_alignment - 1) & !(target_alignment - 1)
+ }
+
+ #[test]
+ fn test_rounding() {
+ assert_eq!(round_up_to_next(0, 4), 0);
+ assert_eq!(round_up_to_next(1, 4), 4);
+ assert_eq!(round_up_to_next(2, 4), 4);
+ assert_eq!(round_up_to_next(3, 4), 4);
+ assert_eq!(round_up_to_next(4, 4), 4);
+ assert_eq!(round_up_to_next(5, 4), 8);
+ }
+
+ // Returns a tuple of (minimum required malloc alignment, hash_offset,
+ // key_offset, val_offset, array_size), from the start of a mallocated array.
+ fn calculate_offsets(
+ hash_size: uint, hash_align: uint,
+ keys_size: uint, keys_align: uint,
+ vals_size: uint, vals_align: uint) -> (uint, uint, uint, uint, uint) {
+
+ let hash_offset = 0;
+ let end_of_hashes = hash_offset + hash_size;
+
+ let keys_offset = round_up_to_next(end_of_hashes, keys_align);
+ let end_of_keys = keys_offset + keys_size;
+
+ let vals_offset = round_up_to_next(end_of_keys, vals_align);
+ let end_of_vals = vals_offset + vals_size;
+
+ let min_align = cmp::max(hash_align, cmp::max(keys_align, vals_align));
+
+ (min_align, hash_offset, keys_offset, vals_offset, end_of_vals)
+ }
+
+ #[test]
+ fn test_offset_calculation() {
+ assert_eq!(calculate_offsets(128, 8, 15, 1, 4, 4 ), (8, 0, 128, 144, 148));
+ assert_eq!(calculate_offsets(3, 1, 2, 1, 1, 1 ), (1, 0, 3, 5, 6));
+ assert_eq!(calculate_offsets(6, 2, 12, 4, 24, 8), (8, 0, 8, 24, 48));
+ }
+
+ impl<K, V> RawTable<K, V> {
+
+ /// Does not initialize the buckets. The caller should ensure they,
+ /// at the very least, set every hash to EMPTY_BUCKET.
+ unsafe fn new_uninitialized(capacity: uint) -> RawTable<K, V> {
+ let hashes_size = capacity.checked_mul(&size_of::<u64>())
+ .expect("capacity overflow");
+ let keys_size = capacity.checked_mul(&size_of::< K >())
+ .expect("capacity overflow");
+ let vals_size = capacity.checked_mul(&size_of::< V >())
+ .expect("capacity overflow");
+
+ // Allocating hashmaps is a little tricky. We need to allocate three
+ // arrays, but since we know their sizes and alignments up front,
+ // we just allocate a single array, and then have the subarrays
+ // point into it.
+ //
+ // This is great in theory, but in practice getting the alignment
+ // right is a little subtle. Therefore, calculating offsets has been
+ // factored out into a different function.
+ let (malloc_alignment, hash_offset, keys_offset, vals_offset, size) =
+ calculate_offsets(
+ hashes_size, min_align_of::<u64>(),
+ keys_size, min_align_of::< K >(),
+ vals_size, min_align_of::< V >());
+
+ let buffer = allocate(size, malloc_alignment);
+
+ let hashes = buffer.offset(hash_offset as int) as *mut u64;
+ let keys = buffer.offset(keys_offset as int) as *mut K;
+ let vals = buffer.offset(vals_offset as int) as *mut V;
+
+ RawTable {
+ capacity: capacity,
+ size: 0,
+ hashes: hashes,
+ keys: keys,
+ vals: vals,
+ }
+ }
+
+ /// Creates a new raw table from a given capacity. All buckets are
+ /// initially empty.
+ pub fn new(capacity: uint) -> RawTable<K, V> {
+ unsafe {
+ let ret = RawTable::new_uninitialized(capacity);
+ set_memory(ret.hashes, 0u8, capacity);
+ ret
+ }
+ }
+
+ /// Reads a bucket at a given index, returning an enum indicating whether
+ /// there's anything there or not. You need to match on this enum to get
+ /// the appropriate types to pass on to most of the other functions in
+ /// this module.
+ pub fn peek(&self, index: uint) -> BucketState {
+ debug_assert!(index < self.capacity);
+
+ let idx = index as int;
+ let hash = unsafe { *self.hashes.offset(idx) };
+
+ let nocopy = marker::NoCopy;
+
+ match hash {
+ EMPTY_BUCKET =>
+ Empty(EmptyIndex {
+ idx: idx,
+ nocopy: nocopy
+ }),
+ full_hash =>
+ Full(FullIndex {
+ idx: idx,
+ hash: SafeHash { hash: full_hash },
+ nocopy: nocopy,
+ })
+ }
+ }
+
+ /// Gets references to the key and value at a given index.
+ pub fn read<'a>(&'a self, index: &FullIndex) -> (&'a K, &'a V) {
+ let idx = index.idx;
+
+ unsafe {
+ debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
+ (&'a *self.keys.offset(idx),
+ &'a *self.vals.offset(idx))
+ }
+ }
+
+ /// Gets references to the key and value at a given index, with the
+ /// value's reference being mutable.
+ pub fn read_mut<'a>(&'a mut self, index: &FullIndex) -> (&'a K, &'a mut V) {
+ let idx = index.idx;
+
+ unsafe {
+ debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
+ (&'a *self.keys.offset(idx),
+ &'a mut *self.vals.offset(idx))
+ }
+ }
+
+ /// Read everything, mutably.
+ pub fn read_all_mut<'a>(&'a mut self, index: &FullIndex)
+ -> (&'a mut SafeHash, &'a mut K, &'a mut V) {
+ let idx = index.idx;
+
+ unsafe {
+ debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
+ (transmute(self.hashes.offset(idx)),
+ &'a mut *self.keys.offset(idx),
+ &'a mut *self.vals.offset(idx))
+ }
+ }
+
+ /// Puts a key and value pair, along with the key's hash, into a given
+ /// index in the hashtable. Note how the `EmptyIndex` is 'moved' into this
+ /// function, because that slot will no longer be empty when we return!
+ /// A FullIndex is returned for later use, pointing to the newly-filled
+ /// slot in the hashtable.
+ ///
+ /// Use `make_hash` to construct a `SafeHash` to pass to this function.
+ pub fn put(&mut self, index: EmptyIndex, hash: SafeHash, k: K, v: V) -> FullIndex {
+ let idx = index.idx;
+
+ unsafe {
+ debug_assert_eq!(*self.hashes.offset(idx), EMPTY_BUCKET);
+ *self.hashes.offset(idx) = hash.inspect();
+ overwrite(&mut *self.keys.offset(idx), k);
+ overwrite(&mut *self.vals.offset(idx), v);
+ }
+
+ self.size += 1;
+
+ FullIndex { idx: idx, hash: hash, nocopy: marker::NoCopy }
+ }
+
+ /// Removes a key and value from the hashtable.
+ ///
+ /// This works similarly to `put`, building an `EmptyIndex` out of the
+ /// taken FullIndex.
+ pub fn take(&mut self, index: FullIndex) -> (EmptyIndex, K, V) {
+ let idx = index.idx;
+
+ unsafe {
+ debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
+
+ *self.hashes.offset(idx) = EMPTY_BUCKET;
+
+ // Drop the mutable constraint.
+ let keys = self.keys as *K;
+ let vals = self.vals as *V;
+
+ let k = ptr::read(keys.offset(idx));
+ let v = ptr::read(vals.offset(idx));
+
+ self.size -= 1;
+
+ (EmptyIndex { idx: idx, nocopy: marker::NoCopy }, k, v)
+ }
+ }
+
+ /// The hashtable's capacity, similar to a vector's.
+ pub fn capacity(&self) -> uint {
+ self.capacity
+ }
+
+ /// The number of elements ever `put` in the hashtable, minus the number
+ /// of elements ever `take`n.
+ pub fn size(&self) -> uint {
+ self.size
+ }
+
+ pub fn iter<'a>(&'a self) -> Entries<'a, K, V> {
+ Entries { table: self, idx: 0, elems_seen: 0 }
+ }
+
+ pub fn mut_iter<'a>(&'a mut self) -> MutEntries<'a, K, V> {
+ MutEntries { table: self, idx: 0, elems_seen: 0 }
+ }
+
+ pub fn move_iter(self) -> MoveEntries<K, V> {
+ MoveEntries { table: self, idx: 0, elems_seen: 0 }
+ }
+ }
+
+ // `read_all_mut` casts a `*u64` to a `*SafeHash`. Since we statically
+ // ensure that a `FullIndex` points to an index with a non-zero hash,
+ // and a `SafeHash` is just a `u64` with a different name, this is
+ // safe.
+ //
+ // This test ensures that a `SafeHash` really IS the same size as a
+ // `u64`. If you need to change the size of `SafeHash` (and
+ // consequently made this test fail), `read_all_mut` needs to be
+ // modified to no longer assume this.
+ #[test]
+ fn can_alias_safehash_as_u64() {
+ assert_eq!(size_of::<SafeHash>(), size_of::<u64>())
+ }
+
+ pub struct Entries<'a, K, V> {
+ table: &'a RawTable<K, V>,
+ idx: uint,
+ elems_seen: uint,
+ }
+
+ pub struct MutEntries<'a, K, V> {
+ table: &'a mut RawTable<K, V>,
+ idx: uint,
+ elems_seen: uint,
+ }
+
+ pub struct MoveEntries<K, V> {
+ table: RawTable<K, V>,
+ idx: uint,
+ elems_seen: uint,
+ }
+
+ impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
+ fn next(&mut self) -> Option<(&'a K, &'a V)> {
+ while self.idx < self.table.capacity() {
+ let i = self.idx;
+ self.idx += 1;
+
+ match self.table.peek(i) {
+ Empty(_) => {},
+ Full(idx) => {
+ self.elems_seen += 1;
+ return Some(self.table.read(&idx));
+ }
+ }
+ }
+
+ None
+ }
+
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ let size = self.table.size() - self.elems_seen;
+ (size, Some(size))
+ }
+ }
+
+ impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
+ fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
+ while self.idx < self.table.capacity() {
+ let i = self.idx;
+ self.idx += 1;
+
+ match self.table.peek(i) {
+ Empty(_) => {},
+ // the transmute here fixes:
+ // error: lifetime of `self` is too short to guarantee its contents
+ // can be safely reborrowed
+ Full(idx) => unsafe {
+ self.elems_seen += 1;
+ return Some(transmute(self.table.read_mut(&idx)));
+ }
+ }
+ }
+
+ None
+ }
+
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ let size = self.table.size() - self.elems_seen;
+ (size, Some(size))
+ }
+ }
+
+ impl<K, V> Iterator<(SafeHash, K, V)> for MoveEntries<K, V> {
+ fn next(&mut self) -> Option<(SafeHash, K, V)> {
+ while self.idx < self.table.capacity() {
+ let i = self.idx;
+ self.idx += 1;
+
+ match self.table.peek(i) {
+ Empty(_) => {},
+ Full(idx) => {
+ let h = idx.hash();
+ let (_, k, v) = self.table.take(idx);
+ return Some((h, k, v));
+ }
+ }
+ }
+
+ None
+ }
+
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ let size = self.table.size();
+ (size, Some(size))
+ }
+ }
+
+ impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
+ fn clone(&self) -> RawTable<K, V> {
+ unsafe {
+ let mut new_ht = RawTable::new_uninitialized(self.capacity());
+
+ for i in range(0, self.capacity()) {
+ match self.peek(i) {
+ Empty(_) => {
+ *new_ht.hashes.offset(i as int) = EMPTY_BUCKET;
+ },
+ Full(idx) => {
+ let hash = idx.hash().inspect();
+ let (k, v) = self.read(&idx);
+ *new_ht.hashes.offset(i as int) = hash;
+ overwrite(&mut *new_ht.keys.offset(i as int), (*k).clone());
+ overwrite(&mut *new_ht.vals.offset(i as int), (*v).clone());
+ }
+ }
+ }
+
+ new_ht.size = self.size();
+
+ new_ht
+ }
+ }
+ }
+
+ #[unsafe_destructor]
+ impl<K, V> Drop for RawTable<K, V> {
+ fn drop(&mut self) {
+ // This is in reverse because we're likely to have partially taken
+ // some elements out with `.move_iter()` from the front.
+ for i in range_step_inclusive(self.capacity as int - 1, 0, -1) {
+ // Check if the size is 0, so we don't do a useless scan when
+ // dropping empty tables such as on resize.
+ if self.size == 0 { break }
+
+ match self.peek(i as uint) {
+ Empty(_) => {},
+ Full(idx) => { self.take(idx); }
+ }
+ }
+
+ assert_eq!(self.size, 0);
+
+ if self.hashes.is_not_null() {
+ let hashes_size = self.capacity * size_of::<u64>();
+ let keys_size = self.capacity * size_of::<K>();
+ let vals_size = self.capacity * size_of::<V>();
+ let (align, _, _, _, size) = calculate_offsets(hashes_size, min_align_of::<u64>(),
+ keys_size, min_align_of::<K>(),
+ vals_size, min_align_of::<V>());
+
+ unsafe {
+ deallocate(self.hashes as *mut u8, size, align);
+ // Remember how everything was allocated out of one buffer
+ // during initialization? We only need one call to free here.
+ }
+
+ self.hashes = RawPtr::null();
+ }
+ }
+ }
+}
+
+static INITIAL_LOG2_CAP: uint = 5;
+static INITIAL_CAPACITY: uint = 1 << INITIAL_LOG2_CAP; // 2^5
+
+/// The default behavior of HashMap implements a load factor of 90.9%.
+/// This behavior is characterized by the following conditions:
+///
+/// - if `size * 1.1 < cap < size * 4` then shouldn't resize
+/// - if `cap < minimum_capacity * 2` then shouldn't shrink
+#[deriving(Clone)]
+struct DefaultResizePolicy {
+ /// Doubled minimal capacity. The capacity must never drop below
+ /// the minimum capacity. (The check happens before the capacity
+ /// is potentially halved.)
+ minimum_capacity2: uint
+}
+
+impl DefaultResizePolicy {
+ fn new(new_capacity: uint) -> DefaultResizePolicy {
+ DefaultResizePolicy {
+ minimum_capacity2: new_capacity << 1
+ }
+ }
+
+ #[inline]
+ fn capacity_range(&self, new_size: uint) -> (uint, uint) {
+ ((new_size * 11) / 10, max(new_size << 3, self.minimum_capacity2))
+ }
+
+ #[inline]
+ fn reserve(&mut self, new_capacity: uint) {
+ self.minimum_capacity2 = new_capacity << 1;
+ }
+}
+
+// The main performance trick in this hashmap is called Robin Hood Hashing.
+// It gains its excellent performance from one key invariant:
+//
+// If an insertion collides with an existing element, and that elements
+// "probe distance" (how far away the element is from its ideal location)
+// is higher than how far we've already probed, swap the elements.
+//
+// This massively lowers variance in probe distance, and allows us to get very
+// high load factors with good performance. The 90% load factor I use is rather
+// conservative.
+//
+// > Why a load factor of approximately 90%?
+//
+// In general, all the distances to initial buckets will converge on the mean.
+// At a load factor of α, the odds of finding the target bucket after k
+// probes is approximately 1-α^k. If we set this equal to 50% (since we converge
+// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round
+// this down to make the math easier on the CPU and avoid its FPU.
+// Since on average we start the probing in the middle of a cache line, this
+// strategy pulls in two cache lines of hashes on every lookup. I think that's
+// pretty good, but if you want to trade off some space, it could go down to one
+// cache line on average with an α of 0.84.
+//
+// > Wait, what? Where did you get 1-α^k from?
+//
+// On the first probe, your odds of a collision with an existing element is α.
+// The odds of doing this twice in a row is approximately α^2. For three times,
+// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT
+// colliding after k tries is 1-α^k.
+//
+// Future Improvements (FIXME!)
+// ============================
+//
+// Allow the load factor to be changed dynamically and/or at initialization.
+//
+// Also, would it be possible for us to reuse storage when growing the
+// underlying table? This is exactly the use case for 'realloc', and may
+// be worth exploring.
+//
+// Future Optimizations (FIXME!)
+// =============================
+//
+// The paper cited below mentions an implementation which keeps track of the
+// distance-to-initial-bucket histogram. I'm suspicious of this approach because
+// it requires maintaining an internal map. If this map were replaced with a
+// hashmap, it would be faster, but now our data structure is self-referential
+// and blows up. Also, this allows very good first guesses, but array accesses
+// are no longer linear and in one direction, as we have now. There is also
+// memory and cache pressure that this map would entail that would be very
+// difficult to properly see in a microbenchmark.
+//
+// Another possible design choice that I made without any real reason is
+// parameterizing the raw table over keys and values. Technically, all we need
+// is the size and alignment of keys and values, and the code should be just as
+// efficient (well, we might need one for power-of-two size and one for not...).
+// This has the potential to reduce code bloat in rust executables, without
+// really losing anything except 4 words (key size, key alignment, val size,
+// val alignment) which can be passed in to every call of a `RawTable` function.
+// This would definitely be an avenue worth exploring if people start complaining
+// about the size of rust executables.
+//
+// There's also an "optimization" that has been omitted regarding how the
+// hashtable allocates. The vector type has set the expectation that a hashtable
+// which never has an element inserted should not allocate. I'm suspicious of
+// implementing this for hashtables, because supporting it has no performance
+// benefit over using an `Option<HashMap<K, V>>`, and is significantly more
+// complicated.
+
+/// A hash map implementation which uses linear probing with Robin
+/// Hood bucket stealing.
+///
+/// The hashes are all keyed by the task-local random number generator
+/// on creation by default, this means the ordering of the keys is
+/// randomized, but makes the tables more resistant to
+/// denial-of-service attacks (Hash DoS). This behaviour can be
+/// overridden with one of the constructors.
+///
+/// It is required that the keys implement the `PartialEq` and `Hash` traits, although
+/// this can frequently be achieved by using `#[deriving(PartialEq, Hash)]`.
+///
+/// Relevant papers/articles:
+///
+/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf)
+/// 2. Emmanuel Goossaert. ["Robin Hood
+/// hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/)
+/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift
+/// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/)
+///
+/// # Example
+///
+/// ```rust
+/// use collections::HashMap;
+///
+/// // type inference lets us omit an explicit type signature (which
+/// // would be `HashMap<&str, &str>` in this example).
+/// let mut book_reviews = HashMap::new();
+///
+/// // review some books.
+/// book_reviews.insert("Adventures of Huckleberry Finn", "My favorite book.");
+/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
+/// book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
+/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
+///
+/// // check for a specific one.
+/// if !book_reviews.contains_key(&("Les Misérables")) {
+/// println!("We've got {} reviews, but Les Misérables ain't one.",
+/// book_reviews.len());
+/// }
+///
+/// // oops, this review has a lot of spelling mistakes, let's delete it.
+/// book_reviews.remove(&("The Adventures of Sherlock Holmes"));
+///
+/// // look up the values associated with some keys.
+/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
+/// for book in to_find.iter() {
+/// match book_reviews.find(book) {
+/// Some(review) => println!("{}: {}", *book, *review),
+/// None => println!("{} is unreviewed.", *book)
+/// }
+/// }
+///
+/// // iterate over everything.
+/// for (book, review) in book_reviews.iter() {
+/// println!("{}: \"{}\"", *book, *review);
+/// }
+/// ```
+#[deriving(Clone)]
+pub struct HashMap<K, V, H = sip::SipHasher> {
+ // All hashes are keyed on these values, to prevent hash collision attacks.
+ hasher: H,
+
+ table: table::RawTable<K, V>,
+
+ // We keep this at the end since it might as well have tail padding.
+ resize_policy: DefaultResizePolicy,
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
+ // Probe the `idx`th bucket for a given hash, returning the index of the
+ // target bucket.
+ //
+ // This exploits the power-of-two size of the hashtable. As long as this
+ // is always true, we can use a bitmask of cap-1 to do modular arithmetic.
+ //
+ // Prefer using this with increasing values of `idx` rather than repeatedly
+ // calling `probe_next`. This reduces data-dependencies between loops, which
+ // can help the optimizer, and certainly won't hurt it. `probe_next` is
+ // simply for convenience, and is no more efficient than `probe`.
+ fn probe(&self, hash: &table::SafeHash, idx: uint) -> uint {
+ let hash_mask = self.table.capacity() - 1;
+
+ // So I heard a rumor that unsigned overflow is safe in rust..
+ ((hash.inspect() as uint) + idx) & hash_mask
+ }
+
+ // Generate the next probe in a sequence. Prefer using 'probe' by itself,
+ // but this can sometimes be useful.
+ fn probe_next(&self, probe: uint) -> uint {
+ let hash_mask = self.table.capacity() - 1;
+ (probe + 1) & hash_mask
+ }
+
+ fn make_hash<X: Hash<S>>(&self, x: &X) -> table::SafeHash {
+ table::make_hash(&self.hasher, x)
+ }
+
+ /// Get the distance of the bucket at the given index that it lies
+ /// from its 'ideal' location.
+ ///
+ /// In the cited blog posts above, this is called the "distance to
+ /// initial bucket", or DIB.
+ fn bucket_distance(&self, index_of_elem: &table::FullIndex) -> uint {
+ // where the hash of the element that happens to reside at
+ // `index_of_elem` tried to place itself first.
+ let first_probe_index = self.probe(&index_of_elem.hash(), 0);
+
+ let raw_index = index_of_elem.raw_index();
+
+ if first_probe_index <= raw_index {
+ // probe just went forward
+ raw_index - first_probe_index
+ } else {
+ // probe wrapped around the hashtable
+ raw_index + (self.table.capacity() - first_probe_index)
+ }
+ }
+
+ /// Search for a pre-hashed key.
+ fn search_hashed_generic(&self, hash: &table::SafeHash, is_match: |&K| -> bool)
+ -> Option<table::FullIndex> {
+ for num_probes in range(0u, self.table.size()) {
+ let probe = self.probe(hash, num_probes);
+
+ let idx = match self.table.peek(probe) {
+ table::Empty(_) => return None, // hit an empty bucket
+ table::Full(idx) => idx
+ };
+
+ // We can finish the search early if we hit any bucket
+ // with a lower distance to initial bucket than we've probed.
+ if self.bucket_distance(&idx) < num_probes { return None }
+
+ // If the hash doesn't match, it can't be this one..
+ if *hash != idx.hash() { continue }
+
+ let (k, _) = self.table.read(&idx);
+
+ // If the key doesn't match, it can't be this one..
+ if !is_match(k) { continue }
+
+ return Some(idx);
+ }
+
+ return None
+ }
+
+ fn search_hashed(&self, hash: &table::SafeHash, k: &K) -> Option<table::FullIndex> {
+ self.search_hashed_generic(hash, |k_| *k == *k_)
+ }
+
+ fn search_equiv<Q: Hash<S> + Equiv<K>>(&self, q: &Q) -> Option<table::FullIndex> {
+ self.search_hashed_generic(&self.make_hash(q), |k| q.equiv(k))
+ }
+
+ /// Search for a key, yielding the index if it's found in the hashtable.
+ /// If you already have the hash for the key lying around, use
+ /// search_hashed.
+ fn search(&self, k: &K) -> Option<table::FullIndex> {
+ self.search_hashed(&self.make_hash(k), k)
+ }
+
+ fn pop_internal(&mut self, starting_index: table::FullIndex) -> Option<V> {
+ let starting_probe = starting_index.raw_index();
+
+ let ending_probe = {
+ let mut probe = self.probe_next(starting_probe);
+ for _ in range(0u, self.table.size()) {
+ match self.table.peek(probe) {
+ table::Empty(_) => {}, // empty bucket. this is the end of our shifting.
+ table::Full(idx) => {
+ // Bucket that isn't us, which has a non-zero probe distance.
+ // This isn't the ending index, so keep searching.
+ if self.bucket_distance(&idx) != 0 {
+ probe = self.probe_next(probe);
+ continue;
+ }
+
+ // if we do have a bucket_distance of zero, we're at the end
+ // of what we need to shift.
+ }
+ }
+ break;
+ }
+
+ probe
+ };
+
+ let (_, _, retval) = self.table.take(starting_index);
+
+ let mut probe = starting_probe;
+ let mut next_probe = self.probe_next(probe);
+
+ // backwards-shift all the elements after our newly-deleted one.
+ while next_probe != ending_probe {
+ match self.table.peek(next_probe) {
+ table::Empty(_) => {
+ // nothing to shift in. just empty it out.
+ match self.table.peek(probe) {
+ table::Empty(_) => {},
+ table::Full(idx) => { self.table.take(idx); }
+ }
+ },
+ table::Full(next_idx) => {
+ // something to shift. move it over!
+ let next_hash = next_idx.hash();
+ let (_, next_key, next_val) = self.table.take(next_idx);
+ match self.table.peek(probe) {
+ table::Empty(idx) => {
+ self.table.put(idx, next_hash, next_key, next_val);
+ },
+ table::Full(idx) => {
+ let (emptyidx, _, _) = self.table.take(idx);
+ self.table.put(emptyidx, next_hash, next_key, next_val);
+ }
+ }
+ }
+ }
+
+ probe = next_probe;
+ next_probe = self.probe_next(next_probe);
+ }
+
+ // Done the backwards shift, but there's still an element left!
+ // Empty it out.
+ match self.table.peek(probe) {
+ table::Empty(_) => {},
+ table::Full(idx) => { self.table.take(idx); }
+ }
+
+ // Now we're done all our shifting. Return the value we grabbed
+ // earlier.
+ return Some(retval);
+ }
+
+ /// Like `pop`, but can operate on any type that is equivalent to a key.
+ #[experimental]
+ pub fn pop_equiv<Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
+ if self.table.size() == 0 {
+ return None
+ }
+
+ let potential_new_size = self.table.size() - 1;
+ self.make_some_room(potential_new_size);
+
+ let starting_index = match self.search_equiv(k) {
+ Some(idx) => idx,
+ None => return None,
+ };
+
+ self.pop_internal(starting_index)
+ }
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Container for HashMap<K, V, H> {
+ /// Return the number of elements in the map
+ fn len(&self) -> uint { self.table.size() }
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Mutable for HashMap<K, V, H> {
+ /// Clear the map, removing all key-value pairs. Keeps the allocated memory
+ /// for reuse.
+ fn clear(&mut self) {
+ // Prevent reallocations from happening from now on. Makes it possible
+ // for the map to be reused but has a downside: reserves permanently.
+ self.resize_policy.reserve(self.table.size());
+
+ for i in range(0, self.table.capacity()) {
+ match self.table.peek(i) {
+ table::Empty(_) => {},
+ table::Full(idx) => { self.table.take(idx); }
+ }
+ }
+ }
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Map<K, V> for HashMap<K, V, H> {
+ fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
+ self.search(k).map(|idx| {
+ let (_, v) = self.table.read(&idx);
+ v
+ })
+ }
+
+ fn contains_key(&self, k: &K) -> bool {
+ self.search(k).is_some()
+ }
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V, H> {
+ fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
+ match self.search(k) {
+ None => None,
+ Some(idx) => {
+ let (_, v) = self.table.read_mut(&idx);
+ Some(v)
+ }
+ }
+ }
+
+ fn swap(&mut self, k: K, v: V) -> Option<V> {
+ let hash = self.make_hash(&k);
+ let potential_new_size = self.table.size() + 1;
+ self.make_some_room(potential_new_size);
+
+ for dib in range_inclusive(0u, self.table.size()) {
+ let probe = self.probe(&hash, dib);
+
+ let idx = match self.table.peek(probe) {
+ table::Empty(idx) => {
+ // Found a hole!
+ self.table.put(idx, hash, k, v);
+ return None;
+ },
+ table::Full(idx) => idx
+ };
+
+ if idx.hash() == hash {
+ let (bucket_k, bucket_v) = self.table.read_mut(&idx);
+ if k == *bucket_k {
+ // Found an existing value.
+ return Some(replace(bucket_v, v));
+ }
+ }
+
+ let probe_dib = self.bucket_distance(&idx);
+
+ if probe_dib < dib {
+ // Found a luckier bucket. This implies that the key does not
+ // already exist in the hashtable. Just do a robin hood
+ // insertion, then.
+ self.robin_hood(idx, probe_dib, hash, k, v);
+ return None;
+ }
+ }
+
+ // We really shouldn't be here.
+ fail!("Internal HashMap error: Out of space.");
+ }
+
+ fn pop(&mut self, k: &K) -> Option<V> {
+ if self.table.size() == 0 {
+ return None
+ }
+
+ let potential_new_size = self.table.size() - 1;
+ self.make_some_room(potential_new_size);
+
+ let starting_index = match self.search(k) {
+ Some(idx) => idx,
+ None => return None,
+ };
+
+ self.pop_internal(starting_index)
+ }
+
+}
+
+impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
+ /// Create an empty HashMap.
+ pub fn new() -> HashMap<K, V, sip::SipHasher> {
+ HashMap::with_capacity(INITIAL_CAPACITY)
+ }
+
+ /// Creates an empty hash map with the given initial capacity.
+ pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> {
+ let mut r = rand::task_rng();
+ let r0 = r.gen();
+ let r1 = r.gen();
+ let hasher = sip::SipHasher::new_with_keys(r0, r1);
+ HashMap::with_capacity_and_hasher(capacity, hasher)
+ }
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
+ /// Creates an empty hashmap which will use the given hasher to hash keys.
+ ///
+ /// The creates map has the default initial capacity.
+ pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
+ HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
+ }
+
+ /// Create an empty HashMap with space for at least `capacity`
+ /// elements, using `hasher` to hash the keys.
+ ///
+ /// Warning: `hasher` is normally randomly generated, and
+ /// is designed to allow HashMaps to be resistant to attacks that
+ /// cause many collisions and very poor performance. Setting it
+ /// manually using this function can expose a DoS attack vector.
+ pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
+ let cap = num::next_power_of_two(max(INITIAL_CAPACITY, capacity));
+ HashMap {
+ hasher: hasher,
+ resize_policy: DefaultResizePolicy::new(cap),
+ table: table::RawTable::new(cap),
+ }
+ }
+
+ /// The hashtable will never try to shrink below this size. You can use
+ /// this function to reduce reallocations if your hashtable frequently
+ /// grows and shrinks by large amounts.
+ ///
+ /// This function has no effect on the operational semantics of the
+ /// hashtable, only on performance.
+ pub fn reserve(&mut self, new_minimum_capacity: uint) {
+ let cap = num::next_power_of_two(
+ max(INITIAL_CAPACITY, new_minimum_capacity));
+
+ self.resize_policy.reserve(cap);
+
+ if self.table.capacity() < cap {
+ self.resize(cap);
+ }
+ }
+
+ /// Resizes the internal vectors to a new capacity. It's your responsibility to:
+ /// 1) Make sure the new capacity is enough for all the elements, accounting
+ /// for the load factor.
+ /// 2) Ensure new_capacity is a power of two.
+ fn resize(&mut self, new_capacity: uint) {
+ assert!(self.table.size() <= new_capacity);
+ assert!(num::is_power_of_two(new_capacity));
+
+ let old_table = replace(&mut self.table, table::RawTable::new(new_capacity));
+ let old_size = old_table.size();
+
+ for (h, k, v) in old_table.move_iter() {
+ self.insert_hashed_nocheck(h, k, v);
+ }
+
+ assert_eq!(self.table.size(), old_size);
+ }
+
+ /// Performs any necessary resize operations, such that there's space for
+ /// new_size elements.
+ fn make_some_room(&mut self, new_size: uint) {
+ let (grow_at, shrink_at) = self.resize_policy.capacity_range(new_size);
+ let cap = self.table.capacity();
+
+ // An invalid value shouldn't make us run out of space.
+ debug_assert!(grow_at >= new_size);
+
+ if cap <= grow_at {
+ let new_capacity = cap << 1;
+ self.resize(new_capacity);
+ } else if shrink_at <= cap {
+ let new_capacity = cap >> 1;
+ self.resize(new_capacity);
+ }
+ }
+
+ /// Perform robin hood bucket stealing at the given 'index'. You must
+ /// also pass that probe's "distance to initial bucket" so we don't have
+ /// to recalculate it, as well as the total number of probes already done
+ /// so we have some sort of upper bound on the number of probes to do.
+ ///
+ /// 'hash', 'k', and 'v' are the elements to robin hood into the hashtable.
+ fn robin_hood(&mut self, mut index: table::FullIndex, mut dib_param: uint,
+ mut hash: table::SafeHash, mut k: K, mut v: V) {
+ 'outer: loop {
+ let (old_hash, old_key, old_val) = {
+ let (old_hash_ref, old_key_ref, old_val_ref) =
+ self.table.read_all_mut(&index);
+
+ let old_hash = replace(old_hash_ref, hash);
+ let old_key = replace(old_key_ref, k);
+ let old_val = replace(old_val_ref, v);
+
+ (old_hash, old_key, old_val)
+ };
+
+ let mut probe = self.probe_next(index.raw_index());
+
+ for dib in range(dib_param + 1, self.table.size()) {
+ let full_index = match self.table.peek(probe) {
+ table::Empty(idx) => {
+ // Finally. A hole!
+ self.table.put(idx, old_hash, old_key, old_val);
+ return;
+ },
+ table::Full(idx) => idx
+ };
+
+ let probe_dib = self.bucket_distance(&full_index);
+
+ // Robin hood! Steal the spot.
+ if probe_dib < dib {
+ index = full_index;
+ dib_param = probe_dib;
+ hash = old_hash;
+ k = old_key;
+ v = old_val;
+ continue 'outer;
+ }
+
+ probe = self.probe_next(probe);
+ }
+
+ fail!("HashMap fatal error: 100% load factor?");
+ }
+ }
+
+ /// Insert a pre-hashed key-value pair, without first checking
+ /// that there's enough room in the buckets. Returns a reference to the
+ /// newly insert value.
+ ///
+ /// If the key already exists, the hashtable will be returned untouched
+ /// and a reference to the existing element will be returned.
+ fn insert_hashed_nocheck<'a>(
+ &'a mut self, hash: table::SafeHash, k: K, v: V) -> &'a mut V {
+
+ for dib in range_inclusive(0u, self.table.size()) {
+ let probe = self.probe(&hash, dib);
+
+ let idx = match self.table.peek(probe) {
+ table::Empty(idx) => {
+ // Found a hole!
+ let fullidx = self.table.put(idx, hash, k, v);
+ let (_, val) = self.table.read_mut(&fullidx);
+ return val;
+ },
+ table::Full(idx) => idx
+ };
+
+ if idx.hash() == hash {
+ let (bucket_k, bucket_v) = self.table.read_mut(&idx);
+ // FIXME #12147 the conditional return confuses
+ // borrowck if we return bucket_v directly
+ let bv: *mut V = bucket_v;
+ if k == *bucket_k {
+ // Key already exists. Get its reference.
+ return unsafe {&mut *bv};
+ }
+ }
+
+ let probe_dib = self.bucket_distance(&idx);
+
+ if probe_dib < dib {
+ // Found a luckier bucket than me. Better steal his spot.
+ self.robin_hood(idx, probe_dib, hash, k, v);
+
+ // Now that it's stolen, just read the value's pointer
+ // right out of the table!
+ match self.table.peek(probe) {
+ table::Empty(_) => fail!("Just stole a spot, but now that spot's empty."),
+ table::Full(idx) => {
+ let (_, v) = self.table.read_mut(&idx);
+ return v;
+ }
+ }
+ }
+ }
+
+ // We really shouldn't be here.
+ fail!("Internal HashMap error: Out of space.");
+ }
+
+ /// Inserts an element which has already been hashed, returning a reference
+ /// to that element inside the hashtable. This is more efficient that using
+ /// `insert`, since the key will not be rehashed.
+ fn insert_hashed<'a>(&'a mut self, hash: table::SafeHash, k: K, v: V) -> &'a mut V {
+ let potential_new_size = self.table.size() + 1;
+ self.make_some_room(potential_new_size);
+ self.insert_hashed_nocheck(hash, k, v)
+ }
+
+ /// Return the value corresponding to the key in the map, or insert
+ /// and return the value if it doesn't exist.
+ pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V {
+ self.find_with_or_insert_with(k, v, |_k, _v, _a| (), |_k, a| a)
+ }
+
+ /// Return the value corresponding to the key in the map, or create,
+ /// insert, and return a new value if it doesn't exist.
+ pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: |&K| -> V)
+ -> &'a mut V {
+ self.find_with_or_insert_with(k, (), |_k, _v, _a| (), |k, _a| f(k))
+ }
+
+ /// Insert a key-value pair into the map if the key is not already present.
+ /// Otherwise, modify the existing value for the key.
+ /// Returns the new or modified value for the key.
+ pub fn insert_or_update_with<'a>(
+ &'a mut self,
+ k: K,
+ v: V,
+ f: |&K, &mut V|)
+ -> &'a mut V {
+ self.find_with_or_insert_with(k, v, |k, v, _a| f(k, v), |_k, a| a)
+ }
+
+ /// Modify and return the value corresponding to the key in the map, or
+ /// insert and return a new value if it doesn't exist.
+ ///
+ /// This method allows for all insertion behaviours of a hashmap;
+ /// see methods like `insert`, `find_or_insert` and
+ /// `insert_or_update_with` for less general and more friendly
+ /// variations of this.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use collections::HashMap;
+ ///
+ /// // map some strings to vectors of strings
+ /// let mut map = HashMap::new();
+ /// map.insert("a key", vec!["value"]);
+ /// map.insert("z key", vec!["value"]);
+ ///
+ /// let new = vec!["a key", "b key", "z key"];
+ ///
+ /// for k in new.move_iter() {
+ /// map.find_with_or_insert_with(
+ /// k, "new value",
+ /// // if the key does exist either prepend or append this
+ /// // new value based on the first letter of the key.
+ /// |key, already, new| {
+ /// if key.as_slice().starts_with("z") {
+ /// already.unshift(new);
+ /// } else {
+ /// already.push(new);
+ /// }
+ /// },
+ /// // if the key doesn't exist in the map yet, add it in
+ /// // the obvious way.
+ /// |_k, v| vec![v]);
+ /// }
+ ///
+ /// assert_eq!(map.len(), 3);
+ /// assert_eq!(map.get(&"a key"), &vec!["value", "new value"]);
+ /// assert_eq!(map.get(&"b key"), &vec!["new value"]);
+ /// assert_eq!(map.get(&"z key"), &vec!["new value", "value"]);
+ /// ```
+ pub fn find_with_or_insert_with<'a, A>(&'a mut self,
+ k: K,
+ a: A,
+ found: |&K, &mut V, A|,
+ not_found: |&K, A| -> V)
+ -> &'a mut V {
+ let hash = self.make_hash(&k);
+ match self.search_hashed(&hash, &k) {
+ None => {
+ let v = not_found(&k, a);
+ self.insert_hashed(hash, k, v)
+ },
+ Some(idx) => {
+ let (_, v_ref) = self.table.read_mut(&idx);
+ found(&k, v_ref, a);
+ v_ref
+ }
+ }
+ }
+
+ /// Retrieves a value for the given key, failing if the key is not present.
+ pub fn get<'a>(&'a self, k: &K) -> &'a V {
+ match self.find(k) {
+ Some(v) => v,
+ None => fail!("no entry found for key")
+ }
+ }
+
+ /// Retrieves a (mutable) value for the given key, failing if the key is not present.
+ pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
+ match self.find_mut(k) {
+ Some(v) => v,
+ None => fail!("no entry found for key")
+ }
+ }
+
+ /// Return true if the map contains a value for the specified key,
+ /// using equivalence.
+ pub fn contains_key_equiv<Q: Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
+ self.search_equiv(key).is_some()
+ }
+
+ /// Return the value corresponding to the key in the map, using
+ /// equivalence.
+ pub fn find_equiv<'a, Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
+ match self.search_equiv(k) {
+ None => None,
+ Some(idx) => {
+ let (_, v_ref) = self.table.read(&idx);
+ Some(v_ref)
+ }
+ }
+ }
+
+ /// An iterator visiting all keys in arbitrary order.
+ /// Iterator element type is &'a K.
+ pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
+ self.iter().map(|(k, _v)| k)
+ }
+
+ /// An iterator visiting all values in arbitrary order.
+ /// Iterator element type is &'a V.
+ pub fn values<'a>(&'a self) -> Values<'a, K, V> {
+ self.iter().map(|(_k, v)| v)
+ }
+
+ /// An iterator visiting all key-value pairs in arbitrary order.
+ /// Iterator element type is (&'a K, &'a V).
+ pub fn iter<'a>(&'a self) -> Entries<'a, K, V> {
+ self.table.iter()
+ }
+
+ /// An iterator visiting all key-value pairs in arbitrary order,
+ /// with mutable references to the values.
+ /// Iterator element type is (&'a K, &'a mut V).
+ pub fn mut_iter<'a>(&'a mut self) -> MutEntries<'a, K, V> {
+ self.table.mut_iter()
+ }
+
+ /// Creates a consuming iterator, that is, one that moves each key-value
+ /// pair out of the map in arbitrary order. The map cannot be used after
+ /// calling this.
+ pub fn move_iter(self) -> MoveEntries<K, V> {
+ self.table.move_iter().map(|(_, k, v)| (k, v))
+ }
+}
+
+impl<K: Eq + Hash<S>, V: Clone, S, H: Hasher<S>> HashMap<K, V, H> {
+ /// Like `find`, but returns a copy of the value.
+ pub fn find_copy(&self, k: &K) -> Option<V> {
+ self.find(k).map(|v| (*v).clone())
+ }
+
+ /// Like `get`, but returns a copy of the value.
+ pub fn get_copy(&self, k: &K) -> V {
+ (*self.get(k)).clone()
+ }
+}
+
+impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, H> {
+ fn eq(&self, other: &HashMap<K, V, H>) -> bool {
+ if self.len() != other.len() { return false; }
+
+ self.iter()
+ .all(|(key, value)| {
+ match other.find(key) {
+ None => false,
+ Some(v) => *value == *v
+ }
+ })
+ }
+}
+
+impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, r"\{"));
+
+ for (i, (k, v)) in self.iter().enumerate() {
+ if i != 0 { try!(write!(f, ", ")); }
+ try!(write!(f, "{}: {}", *k, *v));
+ }
+
+ write!(f, r"\}")
+ }
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
+ fn default() -> HashMap<K, V, H> {
+ HashMap::with_hasher(Default::default())
+ }
+}
+
+/// HashMap iterator
+pub type Entries<'a, K, V> = table::Entries<'a, K, V>;
+
+/// HashMap mutable values iterator
+pub type MutEntries<'a, K, V> = table::MutEntries<'a, K, V>;
+
+/// HashMap move iterator
+pub type MoveEntries<K, V> =
+ iter::Map<'static, (table::SafeHash, K, V), (K, V), table::MoveEntries<K, V>>;
+
+/// HashMap keys iterator
+pub type Keys<'a, K, V> =
+ iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>;
+
+/// HashMap values iterator
+pub type Values<'a, K, V> =
+ iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>;
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
+ fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
+ let (lower, _) = iter.size_hint();
+ let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
+ map.extend(iter);
+ map
+ }
+}
+
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Extendable<(K, V)> for HashMap<K, V, H> {
+ fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
+ for (k, v) in iter {
+ self.insert(k, v);
+ }
+ }
+}
+
+/// HashSet iterator
+pub type SetItems<'a, K> =
+ iter::Map<'static, (&'a K, &'a ()), &'a K, Entries<'a, K, ()>>;
+
+/// HashSet move iterator
+pub type SetMoveItems<K> =
+ iter::Map<'static, (K, ()), K, MoveEntries<K, ()>>;
+
+/// An implementation of a hash set using the underlying representation of a
+/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
+/// requires that the elements implement the `PartialEq` and `Hash` traits.
+#[deriving(Clone)]
+pub struct HashSet<T, H = sip::SipHasher> {
+ map: HashMap<T, (), H>
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
+ fn eq(&self, other: &HashSet<T, H>) -> bool {
+ if self.len() != other.len() { return false; }
+
+ self.iter().all(|key| other.contains(key))
+ }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Container for HashSet<T, H> {
+ fn len(&self) -> uint { self.map.len() }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> {
+ fn clear(&mut self) { self.map.clear() }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
+ fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
+
+ fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
+ self.iter().all(|v| !other.contains(v))
+ }
+
+ fn is_subset(&self, other: &HashSet<T, H>) -> bool {
+ self.iter().all(|v| other.contains(v))
+ }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
+ fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
+
+ fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
+}
+
+impl<T: Hash + Eq> HashSet<T, sip::SipHasher> {
+ /// Create an empty HashSet
+ pub fn new() -> HashSet<T, sip::SipHasher> {
+ HashSet::with_capacity(INITIAL_CAPACITY)
+ }
+
+ /// Create an empty HashSet with space for at least `n` elements in
+ /// the hash table.
+ pub fn with_capacity(capacity: uint) -> HashSet<T, sip::SipHasher> {
+ HashSet { map: HashMap::with_capacity(capacity) }
+ }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
+ /// Creates a new empty hash set which will use the given hasher to hash
+ /// keys.
+ ///
+ /// The hash set is also created with the default initial capacity.
+ pub fn with_hasher(hasher: H) -> HashSet<T, H> {
+ HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
+ }
+
+ /// Create an empty HashSet with space for at least `capacity`
+ /// elements in the hash table, using `hasher` to hash the keys.
+ ///
+ /// Warning: `hasher` is normally randomly generated, and
+ /// is designed to allow `HashSet`s to be resistant to attacks that
+ /// cause many collisions and very poor performance. Setting it
+ /// manually using this function can expose a DoS attack vector.
+ pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
+ HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
+ }
+
+ /// Reserve space for at least `n` elements in the hash table.
+ pub fn reserve(&mut self, n: uint) {
+ self.map.reserve(n)
+ }
+
+ /// Returns true if the hash set contains a value equivalent to the
+ /// given query value.
+ pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
+ self.map.contains_key_equiv(value)
+ }
+
+ /// An iterator visiting all elements in arbitrary order.
+ /// Iterator element type is &'a T.
+ pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
+ self.map.keys()
+ }
+
+ /// Creates a consuming iterator, that is, one that moves each value out
+ /// of the set in arbitrary order. The set cannot be used after calling
+ /// this.
+ pub fn move_iter(self) -> SetMoveItems<T> {
+ self.map.move_iter().map(|(k, _)| k)
+ }
+
+ /// Visit the values representing the difference
+ pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
+ Repeat::new(other).zip(self.iter())
+ .filter_map(|(other, elt)| {
+ if !other.contains(elt) { Some(elt) } else { None }
+ })
+ }
+
+ /// Visit the values representing the symmetric difference
+ pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
+ -> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
+ self.difference(other).chain(other.difference(self))
+ }
+
+ /// Visit the values representing the intersection
+ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
+ -> SetAlgebraItems<'a, T, H> {
+ Repeat::new(other).zip(self.iter())
+ .filter_map(|(other, elt)| {
+ if other.contains(elt) { Some(elt) } else { None }
+ })
+ }
+
+ /// Visit the values representing the union
+ pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
+ -> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
+ self.iter().chain(other.difference(self))
+ }
+}
+
+impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, r"\{"));
+
+ for (i, x) in self.iter().enumerate() {
+ if i != 0 { try!(write!(f, ", ")); }
+ try!(write!(f, "{}", *x));
+ }
+
+ write!(f, r"\}")
+ }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
+ fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> {
+ let (lower, _) = iter.size_hint();
+ let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
+ set.extend(iter);
+ set
+ }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H> {
+ fn extend<I: Iterator<T>>(&mut self, mut iter: I) {
+ for k in iter {
+ self.insert(k);
+ }
+ }
+}
+
+impl<T: TotalEq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
+ fn default() -> HashSet<T, H> {
+ HashSet::with_hasher(Default::default())
+ }
+}
+
+// `Repeat` is used to feed the filter closure an explicit capture
+// of a reference to the other set
+/// Set operations iterator
+pub type SetAlgebraItems<'a, T, H> =
+ FilterMap<'static, (&'a HashSet<T, H>, &'a T), &'a T,
+ Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>>;
+
+#[cfg(test)]
+mod test_map {
+ use super::HashMap;
+ use std::cmp::Equiv;
+ use std::hash::Hash;
+ use std::iter::{Iterator,range_inclusive,range_step_inclusive};
+ use std::cell::RefCell;
+
+ struct KindaIntLike(int);
+
+ impl Equiv<int> for KindaIntLike {
+ fn equiv(&self, other: &int) -> bool {
+ let KindaIntLike(this) = *self;
+ this == *other
+ }
+ }
+ impl<S: Writer> Hash<S> for KindaIntLike {
+ fn hash(&self, state: &mut S) {
+ let KindaIntLike(this) = *self;
+ this.hash(state)
+ }
+ }
+
+ #[test]
+ fn test_create_capacity_zero() {
+ let mut m = HashMap::with_capacity(0);
+
+ assert!(m.insert(1, 1));
+
+ assert!(m.contains_key(&1));
+ assert!(!m.contains_key(&0));
+ }
+
+ #[test]
+ fn test_insert() {
+ let mut m = HashMap::new();
+ assert_eq!(m.len(), 0);
+ assert!(m.insert(1, 2));
+ assert_eq!(m.len(), 1);
+ assert!(m.insert(2, 4));
+ assert_eq!(m.len(), 2);
+ assert_eq!(*m.find(&1).unwrap(), 2);
+ assert_eq!(*m.find(&2).unwrap(), 4);
+ }
+
+ local_data_key!(drop_vector: RefCell<Vec<int>>)
+
+ #[deriving(Hash, PartialEq, Eq)]
+ struct Dropable {
+ k: uint
+ }
+
+
+ impl Dropable {
+ fn new(k: uint) -> Dropable {
+ let v = drop_vector.get().unwrap();
+ v.borrow_mut().as_mut_slice()[k] += 1;
+
+ Dropable { k: k }
+ }
+ }
+
+ impl Drop for Dropable {
+ fn drop(&mut self) {
+ let v = drop_vector.get().unwrap();
+ v.borrow_mut().as_mut_slice()[self.k] -= 1;
+ }
+ }
+
+ #[test]
+ fn test_drops() {
+ drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0))));
+
+ {
+ let mut m = HashMap::new();
+
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 200) {
+ assert_eq!(v.borrow().as_slice()[i], 0);
+ }
+ drop(v);
+
+ for i in range(0u, 100) {
+ let d1 = Dropable::new(i);
+ let d2 = Dropable::new(i+100);
+ m.insert(d1, d2);
+ }
+
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 200) {
+ assert_eq!(v.borrow().as_slice()[i], 1);
+ }
+ drop(v);
+
+ for i in range(0u, 50) {
+ let k = Dropable::new(i);
+ let v = m.pop(&k);
+
+ assert!(v.is_some());
+
+ let v = drop_vector.get().unwrap();
+ assert_eq!(v.borrow().as_slice()[i], 1);
+ assert_eq!(v.borrow().as_slice()[i+100], 1);
+ }
+
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 50) {
+ assert_eq!(v.borrow().as_slice()[i], 0);
+ assert_eq!(v.borrow().as_slice()[i+100], 0);
+ }
+
+ for i in range(50u, 100) {
+ assert_eq!(v.borrow().as_slice()[i], 1);
+ assert_eq!(v.borrow().as_slice()[i+100], 1);
+ }
+ }
+
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 200) {
+ assert_eq!(v.borrow().as_slice()[i], 0);
+ }
+ }
+
+ #[test]
+ fn test_empty_pop() {
+ let mut m: HashMap<int, bool> = HashMap::new();
+ assert_eq!(m.pop(&0), None);
+ }
+
+ #[test]
+ fn test_lots_of_insertions() {
+ let mut m = HashMap::new();
+
+ // Try this a few times to make sure we never screw up the hashmap's
+ // internal state.
+ for _ in range(0, 10) {
+ assert!(m.is_empty());
+
+ for i in range_inclusive(1, 1000) {
+ assert!(m.insert(i, i));
+
+ for j in range_inclusive(1, i) {
+ let r = m.find(&j);
+ assert_eq!(r, Some(&j));
+ }
+
+ for j in range_inclusive(i+1, 1000) {
+ let r = m.find(&j);
+ assert_eq!(r, None);
+ }
+ }
+
+ for i in range_inclusive(1001, 2000) {
+ assert!(!m.contains_key(&i));
+ }
+
+ // remove forwards
+ for i in range_inclusive(1, 1000) {
+ assert!(m.remove(&i));
+
+ for j in range_inclusive(1, i) {
+ assert!(!m.contains_key(&j));
+ }
+
+ for j in range_inclusive(i+1, 1000) {
+ assert!(m.contains_key(&j));
+ }
+ }
+
+ for i in range_inclusive(1, 1000) {
+ assert!(!m.contains_key(&i));
+ }
+
+ for i in range_inclusive(1, 1000) {
+ assert!(m.insert(i, i));
+ }
+
+ // remove backwards
+ for i in range_step_inclusive(1000, 1, -1) {
+ assert!(m.remove(&i));
+
+ for j in range_inclusive(i, 1000) {
+ assert!(!m.contains_key(&j));
+ }
+
+ for j in range_inclusive(1, i-1) {
+ assert!(m.contains_key(&j));
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_find_mut() {
+ let mut m = HashMap::new();
+ assert!(m.insert(1, 12));
+ assert!(m.insert(2, 8));
+ assert!(m.insert(5, 14));
+ let new = 100;
+ match m.find_mut(&5) {
+ None => fail!(), Some(x) => *x = new
+ }
+ assert_eq!(m.find(&5), Some(&new));
+ }
+
+ #[test]
+ fn test_insert_overwrite() {
+ let mut m = HashMap::new();
+ assert!(m.insert(1, 2));
+ assert_eq!(*m.find(&1).unwrap(), 2);
+ assert!(!m.insert(1, 3));
+ assert_eq!(*m.find(&1).unwrap(), 3);
+ }
+
+ #[test]
+ fn test_insert_conflicts() {
+ let mut m = HashMap::with_capacity(4);
+ assert!(m.insert(1, 2));
+ assert!(m.insert(5, 3));
+ assert!(m.insert(9, 4));
+ assert_eq!(*m.find(&9).unwrap(), 4);
+ assert_eq!(*m.find(&5).unwrap(), 3);
+ assert_eq!(*m.find(&1).unwrap(), 2);
+ }
+
+ #[test]
+ fn test_conflict_remove() {
+ let mut m = HashMap::with_capacity(4);
+ assert!(m.insert(1, 2));
+ assert_eq!(*m.find(&1).unwrap(), 2);
+ assert!(m.insert(5, 3));
+ assert_eq!(*m.find(&1).unwrap(), 2);
+ assert_eq!(*m.find(&5).unwrap(), 3);
+ assert!(m.insert(9, 4));
+ assert_eq!(*m.find(&1).unwrap(), 2);
+ assert_eq!(*m.find(&5).unwrap(), 3);
+ assert_eq!(*m.find(&9).unwrap(), 4);
+ assert!(m.remove(&1));
+ assert_eq!(*m.find(&9).unwrap(), 4);
+ assert_eq!(*m.find(&5).unwrap(), 3);
+ }
+
+ #[test]
+ fn test_is_empty() {
+ let mut m = HashMap::with_capacity(4);
+ assert!(m.insert(1, 2));
+ assert!(!m.is_empty());
+ assert!(m.remove(&1));
+ assert!(m.is_empty());
+ }
+
+ #[test]
+ fn test_pop() {
+ let mut m = HashMap::new();
+ m.insert(1, 2);
+ assert_eq!(m.pop(&1), Some(2));
+ assert_eq!(m.pop(&1), None);
+ }
+
+ #[test]
+ #[allow(experimental)]
+ fn test_pop_equiv() {
+ let mut m = HashMap::new();
+ m.insert(1, 2);
+ assert_eq!(m.pop_equiv(&KindaIntLike(1)), Some(2));
+ assert_eq!(m.pop_equiv(&KindaIntLike(1)), None);
+ }
+
+ #[test]
+ fn test_swap() {
+ let mut m = HashMap::new();
+ assert_eq!(m.swap(1, 2), None);
+ assert_eq!(m.swap(1, 3), Some(2));
+ assert_eq!(m.swap(1, 4), Some(3));
+ }
+
+ #[test]
+ fn test_move_iter() {
+ let hm = {
+ let mut hm = HashMap::new();
+
+ hm.insert('a', 1);
+ hm.insert('b', 2);
+
+ hm
+ };
+
+ let v = hm.move_iter().collect::<Vec<(char, int)>>();
+ assert!([('a', 1), ('b', 2)] == v.as_slice() || [('b', 2), ('a', 1)] == v.as_slice());
+ }
+
+ #[test]
+ fn test_iterate() {
+ let mut m = HashMap::with_capacity(4);
+ for i in range(0u, 32) {
+ assert!(m.insert(i, i*2));
+ }
+ assert_eq!(m.len(), 32);
+
+ let mut observed: u32 = 0;
+
+ for (k, v) in m.iter() {
+ assert_eq!(*v, *k * 2);
+ observed |= 1 << *k;
+ }
+ assert_eq!(observed, 0xFFFF_FFFF);
+ }
+
+ #[test]
+ fn test_keys() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map = vec.move_iter().collect::<HashMap<int, char>>();
+ let keys = map.keys().map(|&k| k).collect::<Vec<int>>();
+ assert_eq!(keys.len(), 3);
+ assert!(keys.contains(&1));
+ assert!(keys.contains(&2));
+ assert!(keys.contains(&3));
+ }
+
+ #[test]
+ fn test_values() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map = vec.move_iter().collect::<HashMap<int, char>>();
+ let values = map.values().map(|&v| v).collect::<Vec<char>>();
+ assert_eq!(values.len(), 3);
+ assert!(values.contains(&'a'));
+ assert!(values.contains(&'b'));
+ assert!(values.contains(&'c'));
+ }
+
+ #[test]
+ fn test_find() {
+ let mut m = HashMap::new();
+ assert!(m.find(&1).is_none());
+ m.insert(1, 2);
+ match m.find(&1) {
+ None => fail!(),
+ Some(v) => assert_eq!(*v, 2)
+ }
+ }
+
+ #[test]
+ fn test_eq() {
+ let mut m1 = HashMap::new();
+ m1.insert(1, 2);
+ m1.insert(2, 3);
+ m1.insert(3, 4);
+
+ let mut m2 = HashMap::new();
+ m2.insert(1, 2);
+ m2.insert(2, 3);
+
+ assert!(m1 != m2);
+
+ m2.insert(3, 4);
+
+ assert_eq!(m1, m2);
+ }
+
+ #[test]
+ fn test_show() {
+ let mut map: HashMap<int, int> = HashMap::new();
+ let empty: HashMap<int, int> = HashMap::new();
+
+ map.insert(1, 2);
+ map.insert(3, 4);
+
+ let map_str = format!("{}", map);
+
+ assert!(map_str == "{1: 2, 3: 4}".to_string() || map_str == "{3: 4, 1: 2}".to_string());
+ assert_eq!(format!("{}", empty), "{}".to_string());
+ }
+
+ #[test]
+ fn test_expand() {
+ let mut m = HashMap::new();
+
+ assert_eq!(m.len(), 0);
+ assert!(m.is_empty());
+
+ let mut i = 0u;
+ let old_cap = m.table.capacity();
+ while old_cap == m.table.capacity() {
+ m.insert(i, i);
+ i += 1;
+ }
+
+ assert_eq!(m.len(), i);
+ assert!(!m.is_empty());
+ }
+
+ #[test]
+ fn test_resize_policy() {
+ let mut m = HashMap::new();
+
+ assert_eq!(m.len(), 0);
+ assert!(m.is_empty());
+
+ let initial_cap = m.table.capacity();
+ m.reserve(initial_cap * 2);
+ let cap = m.table.capacity();
+
+ assert_eq!(cap, initial_cap * 2);
+
+ let mut i = 0u;
+ for _ in range(0, cap * 3 / 4) {
+ m.insert(i, i);
+ i += 1;
+ }
+
+ assert_eq!(m.len(), i);
+ assert_eq!(m.table.capacity(), cap);
+
+ for _ in range(0, cap / 4) {
+ m.insert(i, i);
+ i += 1;
+ }
+
+ let new_cap = m.table.capacity();
+ assert_eq!(new_cap, cap * 2);
+
+ for _ in range(0, cap / 2) {
+ i -= 1;
+ m.remove(&i);
+ assert_eq!(m.table.capacity(), new_cap);
+ }
+
+ for _ in range(0, cap / 2 - 1) {
+ i -= 1;
+ m.remove(&i);
+ }
+
+ assert_eq!(m.table.capacity(), cap);
+ assert_eq!(m.len(), i);
+ assert!(!m.is_empty());
+ }
+
+ #[test]
+ fn test_find_equiv() {
+ let mut m = HashMap::new();
+
+ let (foo, bar, baz) = (1,2,3);
+ m.insert("foo".to_string(), foo);
+ m.insert("bar".to_string(), bar);
+ m.insert("baz".to_string(), baz);
+
+
+ assert_eq!(m.find_equiv(&("foo")), Some(&foo));
+ assert_eq!(m.find_equiv(&("bar")), Some(&bar));
+ assert_eq!(m.find_equiv(&("baz")), Some(&baz));
+
+ assert_eq!(m.find_equiv(&("qux")), None);
+ }
+
+ #[test]
+ fn test_from_iter() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+ for &(k, v) in xs.iter() {
+ assert_eq!(map.find(&k), Some(&v));
+ }
+ }
+
+ #[test]
+ fn test_size_hint() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+ let mut iter = map.iter();
+
+ for _ in iter.by_ref().take(3) {}
+
+ assert_eq!(iter.size_hint(), (3, Some(3)));
+ }
+
+ #[test]
+ fn test_mut_size_hint() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+ let mut iter = map.mut_iter();
+
+ for _ in iter.by_ref().take(3) {}
+
+ assert_eq!(iter.size_hint(), (3, Some(3)));
+ }
+}
+
+#[cfg(test)]
+mod test_set {
+ use super::HashSet;
+ use std::container::Container;
+ use std::slice::ImmutableEqVector;
+
+ #[test]
+ fn test_disjoint() {
+ let mut xs = HashSet::new();
+ let mut ys = HashSet::new();
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(xs.insert(5));
+ assert!(ys.insert(11));
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(xs.insert(7));
+ assert!(xs.insert(19));
+ assert!(xs.insert(4));
+ assert!(ys.insert(2));
+ assert!(ys.insert(-11));
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(ys.insert(7));
+ assert!(!xs.is_disjoint(&ys));
+ assert!(!ys.is_disjoint(&xs));
+ }
+
+ #[test]
+ fn test_subset_and_superset() {
+ let mut a = HashSet::new();
+ assert!(a.insert(0));
+ assert!(a.insert(5));
+ assert!(a.insert(11));
+ assert!(a.insert(7));
+
+ let mut b = HashSet::new();
+ assert!(b.insert(0));
+ assert!(b.insert(7));
+ assert!(b.insert(19));
+ assert!(b.insert(250));
+ assert!(b.insert(11));
+ assert!(b.insert(200));
+
+ assert!(!a.is_subset(&b));
+ assert!(!a.is_superset(&b));
+ assert!(!b.is_subset(&a));
+ assert!(!b.is_superset(&a));
+
+ assert!(b.insert(5));
+
+ assert!(a.is_subset(&b));
+ assert!(!a.is_superset(&b));
+ assert!(!b.is_subset(&a));
+ assert!(b.is_superset(&a));
+ }
+
+ #[test]
+ fn test_iterate() {
+ let mut a = HashSet::new();
+ for i in range(0u, 32) {
+ assert!(a.insert(i));
+ }
+ let mut observed: u32 = 0;
+ for k in a.iter() {
+ observed |= 1 << *k;
+ }
+ assert_eq!(observed, 0xFFFF_FFFF);
+ }
+
+ #[test]
+ fn test_intersection() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::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!(a.insert(-5));
+
+ assert!(b.insert(2));
+ assert!(b.insert(11));
+ assert!(b.insert(77));
+ assert!(b.insert(-9));
+ assert!(b.insert(-42));
+ assert!(b.insert(5));
+ assert!(b.insert(3));
+
+ let mut i = 0;
+ let expected = [3, 5, 11, 77];
+ for x in a.intersection(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_difference() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::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));
+
+ let mut i = 0;
+ let expected = [1, 5, 11];
+ for x in a.difference(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_symmetric_difference() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+
+ assert!(b.insert(-2));
+ assert!(b.insert(3));
+ assert!(b.insert(9));
+ assert!(b.insert(14));
+ assert!(b.insert(22));
+
+ let mut i = 0;
+ let expected = [-2, 1, 5, 11, 14, 22];
+ for x in a.symmetric_difference(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_union() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+ assert!(a.insert(16));
+ assert!(a.insert(19));
+ assert!(a.insert(24));
+
+ assert!(b.insert(-2));
+ assert!(b.insert(1));
+ assert!(b.insert(5));
+ assert!(b.insert(9));
+ assert!(b.insert(13));
+ assert!(b.insert(19));
+
+ let mut i = 0;
+ let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
+ for x in a.union(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_from_iter() {
+ let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+ let set: HashSet<int> = xs.iter().map(|&x| x).collect();
+
+ for x in xs.iter() {
+ assert!(set.contains(x));
+ }
+ }
+
+ #[test]
+ fn test_move_iter() {
+ let hs = {
+ let mut hs = HashSet::new();
+
+ hs.insert('a');
+ hs.insert('b');
+
+ hs
+ };
+
+ let v = hs.move_iter().collect::<Vec<char>>();
+ assert!(['a', 'b'] == v.as_slice() || ['b', 'a'] == v.as_slice());
+ }
+
+ #[test]
+ fn test_eq() {
+ // These constants once happened to expose a bug in insert().
+ // I'm keeping them around to prevent a regression.
+ let mut s1 = HashSet::new();
+
+ s1.insert(1);
+ s1.insert(2);
+ s1.insert(3);
+
+ let mut s2 = HashSet::new();
+
+ s2.insert(1);
+ s2.insert(2);
+
+ assert!(s1 != s2);
+
+ s2.insert(3);
+
+ assert_eq!(s1, s2);
+ }
+
+ #[test]
+ fn test_show() {
+ let mut set: HashSet<int> = HashSet::new();
+ let empty: HashSet<int> = HashSet::new();
+
+ set.insert(1);
+ set.insert(2);
+
+ let set_str = format!("{}", set);
+
+ assert!(set_str == "{1, 2}".to_string() || set_str == "{2, 1}".to_string());
+ assert_eq!(format!("{}", empty), "{}".to_string());
+ }
+}
+
+#[cfg(test)]
+mod bench {
+ extern crate test;
+ use self::test::Bencher;
+ use std::iter::{range_inclusive};
+
+ #[bench]
+ fn new_drop(b : &mut Bencher) {
+ use super::HashMap;
+
+ b.iter(|| {
+ let m : HashMap<int, int> = HashMap::new();
+ assert_eq!(m.len(), 0);
+ })
+ }
+
+ #[bench]
+ fn new_insert_drop(b : &mut Bencher) {
+ use super::HashMap;
+
+ b.iter(|| {
+ let mut m = HashMap::new();
+ m.insert(0, 0);
+ assert_eq!(m.len(), 1);
+ })
+ }
+
+ #[bench]
+ fn insert(b: &mut Bencher) {
+ use super::HashMap;
+
+ let mut m = HashMap::new();
+
+ for i in range_inclusive(1, 1000) {
+ m.insert(i, i);
+ }
+
+ let mut k = 1001;
+
+ b.iter(|| {
+ m.insert(k, k);
+ k += 1;
+ });
+ }
+
+ #[bench]
+ fn find_existing(b: &mut Bencher) {
+ use super::HashMap;
+
+ let mut m = HashMap::new();
+
+ for i in range_inclusive(1, 1000) {
+ m.insert(i, i);
+ }
+
+ b.iter(|| {
+ for i in range_inclusive(1, 1000) {
+ m.contains_key(&i);
+ }
+ });
+ }
+
+ #[bench]
+ fn find_nonexisting(b: &mut Bencher) {
+ use super::HashMap;
+
+ let mut m = HashMap::new();
+
+ for i in range_inclusive(1, 1000) {
+ m.insert(i, i);
+ }
+
+ b.iter(|| {
+ for i in range_inclusive(1001, 2000) {
+ m.contains_key(&i);
+ }
+ });
+ }
+
+ #[bench]
+ fn hashmap_as_queue(b: &mut Bencher) {
+ use super::HashMap;
+
+ let mut m = HashMap::new();
+
+ for i in range_inclusive(1, 1000) {
+ m.insert(i, i);
+ }
+
+ let mut k = 1;
+
+ b.iter(|| {
+ m.pop(&k);
+ m.insert(k + 1000, k + 1000);
+ k += 1;
+ });
+ }
+
+ #[bench]
+ fn find_pop_insert(b: &mut Bencher) {
+ use super::HashMap;
+
+ let mut m = HashMap::new();
+
+ for i in range_inclusive(1, 1000) {
+ m.insert(i, i);
+ }
+
+ let mut k = 1;
+
+ b.iter(|| {
+ m.find(&(k + 400));
+ m.find(&(k + 2000));
+ m.pop(&k);
+ m.insert(k + 1000, k + 1000);
+ k += 1;
+ })
+ }
+}
--- /dev/null
+// Copyright 2013 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.
+
+
+//! A cache that holds a limited number of key-value pairs. When the
+//! capacity of the cache is exceeded, the least-recently-used
+//! (where "used" means a look-up or putting the pair into the cache)
+//! pair is automatically removed.
+//!
+//! # Example
+//!
+//! ```rust
+//! use collections::LruCache;
+//!
+//! let mut cache: LruCache<int, int> = LruCache::new(2);
+//! cache.put(1, 10);
+//! cache.put(2, 20);
+//! cache.put(3, 30);
+//! assert!(cache.get(&1).is_none());
+//! assert_eq!(*cache.get(&2).unwrap(), 20);
+//! assert_eq!(*cache.get(&3).unwrap(), 30);
+//!
+//! cache.put(2, 22);
+//! assert_eq!(*cache.get(&2).unwrap(), 22);
+//!
+//! cache.put(6, 60);
+//! assert!(cache.get(&3).is_none());
+//!
+//! cache.change_capacity(1);
+//! assert!(cache.get(&2).is_none());
+//! ```
+
+use cmp::{Eq, TotalEq};
+use collections::HashMap;
+use container::{Container, Mutable, MutableMap};
+use fmt;
+use hash::Hash;
+use iter::{range, Iterator};
+use mem;
+use ops::Drop;
+use option::{Some, None, Option};
+use owned::Box;
+use ptr;
+use result::{Ok, Err};
+
+struct KeyRef<K> { k: *K }
+
+struct LruEntry<K, V> {
+ next: *mut LruEntry<K, V>,
+ prev: *mut LruEntry<K, V>,
+ key: K,
+ value: V,
+}
+
+/// An LRU Cache.
+pub struct LruCache<K, V> {
+ map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>>,
+ max_size: uint,
+ head: *mut LruEntry<K, V>,
+}
+
+impl<S, K: Hash<S>> Hash<S> for KeyRef<K> {
+ fn hash(&self, state: &mut S) {
+ unsafe { (*self.k).hash(state) }
+ }
+}
+
+impl<K: PartialEq> PartialEq for KeyRef<K> {
+ fn eq(&self, other: &KeyRef<K>) -> bool {
+ unsafe{ (*self.k).eq(&*other.k) }
+ }
+}
+
+impl<K: Eq> Eq for KeyRef<K> {}
+
+impl<K, V> LruEntry<K, V> {
+ fn new(k: K, v: V) -> LruEntry<K, V> {
+ LruEntry {
+ key: k,
+ value: v,
+ next: ptr::mut_null(),
+ prev: ptr::mut_null(),
+ }
+ }
+}
+
+impl<K: Hash + Eq, V> LruCache<K, V> {
+ /// Create an LRU Cache that holds at most `capacity` items.
+ pub fn new(capacity: uint) -> LruCache<K, V> {
+ let cache = LruCache {
+ map: HashMap::new(),
+ max_size: capacity,
+ head: unsafe{ mem::transmute(box mem::uninitialized::<LruEntry<K, V>>()) },
+ };
+ unsafe {
+ (*cache.head).next = cache.head;
+ (*cache.head).prev = cache.head;
+ }
+ return cache;
+ }
+
+ /// Put a key-value pair into cache.
+ pub fn put(&mut self, k: K, v: V) {
+ let (node_ptr, node_opt) = match self.map.find_mut(&KeyRef{k: &k}) {
+ Some(node) => {
+ node.value = v;
+ let node_ptr: *mut LruEntry<K, V> = &mut **node;
+ (node_ptr, None)
+ }
+ None => {
+ let mut node = box LruEntry::new(k, v);
+ let node_ptr: *mut LruEntry<K, V> = &mut *node;
+ (node_ptr, Some(node))
+ }
+ };
+ match node_opt {
+ None => {
+ // Existing node, just update LRU position
+ self.detach(node_ptr);
+ self.attach(node_ptr);
+ }
+ Some(node) => {
+ let keyref = unsafe { &(*node_ptr).key };
+ self.map.swap(KeyRef{k: keyref}, node);
+ self.attach(node_ptr);
+ if self.len() > self.capacity() {
+ self.remove_lru();
+ }
+ }
+ }
+ }
+
+ /// Return a value corresponding to the key in the cache.
+ pub fn get<'a>(&'a mut self, k: &K) -> Option<&'a V> {
+ let (value, node_ptr_opt) = match self.map.find_mut(&KeyRef{k: k}) {
+ None => (None, None),
+ Some(node) => {
+ let node_ptr: *mut LruEntry<K, V> = &mut **node;
+ (Some(unsafe { &(*node_ptr).value }), Some(node_ptr))
+ }
+ };
+ match node_ptr_opt {
+ None => (),
+ Some(node_ptr) => {
+ self.detach(node_ptr);
+ self.attach(node_ptr);
+ }
+ }
+ return value;
+ }
+
+ /// Remove and return a value corresponding to the key from the cache.
+ pub fn pop(&mut self, k: &K) -> Option<V> {
+ match self.map.pop(&KeyRef{k: k}) {
+ None => None,
+ Some(lru_entry) => Some(lru_entry.value)
+ }
+ }
+
+ /// Return the maximum number of key-value pairs the cache can hold.
+ pub fn capacity(&self) -> uint {
+ self.max_size
+ }
+
+ /// Change the number of key-value pairs the cache can hold. Remove
+ /// least-recently-used key-value pairs if necessary.
+ pub fn change_capacity(&mut self, capacity: uint) {
+ for _ in range(capacity, self.len()) {
+ self.remove_lru();
+ }
+ self.max_size = capacity;
+ }
+
+ #[inline]
+ fn remove_lru(&mut self) {
+ if self.len() > 0 {
+ let lru = unsafe { (*self.head).prev };
+ self.detach(lru);
+ self.map.pop(&KeyRef{k: unsafe { &(*lru).key }});
+ }
+ }
+
+ #[inline]
+ fn detach(&mut self, node: *mut LruEntry<K, V>) {
+ unsafe {
+ (*(*node).prev).next = (*node).next;
+ (*(*node).next).prev = (*node).prev;
+ }
+ }
+
+ #[inline]
+ fn attach(&mut self, node: *mut LruEntry<K, V>) {
+ unsafe {
+ (*node).next = (*self.head).next;
+ (*node).prev = self.head;
+ (*self.head).next = node;
+ (*(*node).next).prev = node;
+ }
+ }
+}
+
+impl<A: fmt::Show + Hash + Eq, B: fmt::Show> fmt::Show for LruCache<A, B> {
+ /// Return a string that lists the key-value pairs from most-recently
+ /// used to least-recently used.
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, r"\{"));
+ let mut cur = self.head;
+ for i in range(0, self.len()) {
+ if i > 0 { try!(write!(f, ", ")) }
+ unsafe {
+ cur = (*cur).next;
+ try!(write!(f, "{}", (*cur).key));
+ }
+ try!(write!(f, ": "));
+ unsafe {
+ try!(write!(f, "{}", (*cur).value));
+ }
+ }
+ write!(f, r"\}")
+ }
+}
+
+impl<K: Hash + Eq, V> Container for LruCache<K, V> {
+ /// Return the number of key-value pairs in the cache.
+ fn len(&self) -> uint {
+ self.map.len()
+ }
+}
+
+impl<K: Hash + Eq, V> Mutable for LruCache<K, V> {
+ /// Clear the cache of all key-value pairs.
+ fn clear(&mut self) {
+ self.map.clear();
+ }
+}
+
+#[unsafe_destructor]
+impl<K, V> Drop for LruCache<K, V> {
+ fn drop(&mut self) {
+ unsafe {
+ let node: Box<LruEntry<K, V>> = mem::transmute(self.head);
+ // Prevent compiler from trying to drop the un-initialized field in the sigil node.
+ let box LruEntry { key: k, value: v, .. } = node;
+ mem::forget(k);
+ mem::forget(v);
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::LruCache;
+
+ fn assert_opt_eq<V: PartialEq>(opt: Option<&V>, v: V) {
+ assert!(opt.is_some());
+ assert!(opt.unwrap() == &v);
+ }
+
+ #[test]
+ fn test_put_and_get() {
+ let mut cache: LruCache<int, int> = LruCache::new(2);
+ cache.put(1, 10);
+ cache.put(2, 20);
+ assert_opt_eq(cache.get(&1), 10);
+ assert_opt_eq(cache.get(&2), 20);
+ assert_eq!(cache.len(), 2);
+ }
+
+ #[test]
+ fn test_put_update() {
+ let mut cache: LruCache<String, Vec<u8>> = LruCache::new(1);
+ cache.put("1".to_string(), vec![10, 10]);
+ cache.put("1".to_string(), vec![10, 19]);
+ assert_opt_eq(cache.get(&"1".to_string()), vec![10, 19]);
+ assert_eq!(cache.len(), 1);
+ }
+
+ #[test]
+ fn test_expire_lru() {
+ let mut cache: LruCache<String, String> = LruCache::new(2);
+ cache.put("foo1".to_string(), "bar1".to_string());
+ cache.put("foo2".to_string(), "bar2".to_string());
+ cache.put("foo3".to_string(), "bar3".to_string());
+ assert!(cache.get(&"foo1".to_string()).is_none());
+ cache.put("foo2".to_string(), "bar2update".to_string());
+ cache.put("foo4".to_string(), "bar4".to_string());
+ assert!(cache.get(&"foo3".to_string()).is_none());
+ }
+
+ #[test]
+ fn test_pop() {
+ let mut cache: LruCache<int, int> = LruCache::new(2);
+ cache.put(1, 10);
+ cache.put(2, 20);
+ assert_eq!(cache.len(), 2);
+ let opt1 = cache.pop(&1);
+ assert!(opt1.is_some());
+ assert_eq!(opt1.unwrap(), 10);
+ assert!(cache.get(&1).is_none());
+ assert_eq!(cache.len(), 1);
+ }
+
+ #[test]
+ fn test_change_capacity() {
+ let mut cache: LruCache<int, int> = LruCache::new(2);
+ assert_eq!(cache.capacity(), 2);
+ cache.put(1, 10);
+ cache.put(2, 20);
+ cache.change_capacity(1);
+ assert!(cache.get(&1).is_none());
+ assert_eq!(cache.capacity(), 1);
+ }
+
+ #[test]
+ fn test_to_str() {
+ let mut cache: LruCache<int, int> = LruCache::new(3);
+ cache.put(1, 10);
+ cache.put(2, 20);
+ cache.put(3, 30);
+ assert_eq!(cache.to_str(), "{3: 30, 2: 20, 1: 10}".to_string());
+ cache.put(2, 22);
+ assert_eq!(cache.to_str(), "{2: 22, 3: 30, 1: 10}".to_string());
+ cache.put(6, 60);
+ assert_eq!(cache.to_str(), "{6: 60, 2: 22, 3: 30}".to_string());
+ cache.get(&3);
+ assert_eq!(cache.to_str(), "{3: 30, 6: 60, 2: 22}".to_string());
+ cache.change_capacity(2);
+ assert_eq!(cache.to_str(), "{3: 30, 6: 60}".to_string());
+ }
+
+ #[test]
+ fn test_clear() {
+ let mut cache: LruCache<int, int> = LruCache::new(2);
+ cache.put(1, 10);
+ cache.put(2, 20);
+ cache.clear();
+ assert!(cache.get(&1).is_none());
+ assert!(cache.get(&2).is_none());
+ assert_eq!(cache.to_str(), "{}".to_string());
+ }
+}
--- /dev/null
+// 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.
+
+/*!
+ * Collection types.
+ */
+
+pub use core_collections::{Bitv, BitvSet, BTree, Deque, DList, EnumSet};
+pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap};
+pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet};
+pub use core_collections::{bitv, btree, deque, dlist, enum_set};
+pub use core_collections::{priority_queue, ringbuf, smallintmap, treemap, trie};
+
+pub use self::hashmap::{HashMap, HashSet};
+pub use self::lru_cache::LruCache;
+
+pub mod hashmap;
+pub mod lru_cache;
//! The `FromStr` trait for types that can be created from strings
use option::{Option, Some, None};
+use string::String;
+use str::StrAllocating;
/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
}
}
+impl FromStr for String {
+ #[inline]
+ fn from_str(s: &str) -> Option<String> {
+ Some(s.to_string())
+ }
+}
+
#[cfg(test)]
mod test {
use prelude::*;
+++ /dev/null
-// 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.
-
-/*!
- * Generic hashing support.
- *
- * This module provides a generic way to compute the hash of a value. The
- * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
- *
- * # Example
- *
- * ```rust
- * use std::hash;
- * use std::hash::Hash;
- *
- * #[deriving(Hash)]
- * struct Person {
- * id: uint,
- * name: String,
- * phone: u64,
- * }
- *
- * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
- * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
- *
- * assert!(hash::hash(&person1) != hash::hash(&person2));
- * ```
- *
- * If you need more control over how a value is hashed, you need to implement
- * the trait `Hash`:
- *
- * ```rust
- * use std::hash;
- * use std::hash::Hash;
- * use std::hash::sip::SipState;
- *
- * struct Person {
- * id: uint,
- * name: String,
- * phone: u64,
- * }
- *
- * impl Hash for Person {
- * fn hash(&self, state: &mut SipState) {
- * self.id.hash(state);
- * self.phone.hash(state);
- * }
- * }
- *
- * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
- * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
- *
- * assert!(hash::hash(&person1) == hash::hash(&person2));
- * ```
- */
-
-#![allow(unused_must_use)]
-
-use container::Container;
-use intrinsics::TypeId;
-use iter::Iterator;
-use option::{Option, Some, None};
-use owned::Box;
-use rc::Rc;
-use result::{Result, Ok, Err};
-use slice::{Vector, ImmutableVector};
-use str::{Str, StrSlice};
-use vec::Vec;
-
-/// Reexport the `sip::hash` function as our default hasher.
-pub use hash = self::sip::hash;
-
-pub use Writer = io::Writer;
-
-pub mod sip;
-
-/// A trait that represents a hashable type. The `S` type parameter is an
-/// abstract hash state that is used by the `Hash` to compute the hash.
-/// It defaults to `std::hash::sip::SipState`.
-pub trait Hash<S = sip::SipState> {
- /// Compute a hash of the value.
- fn hash(&self, state: &mut S);
-}
-
-/// A trait that computes a hash for a value. The main users of this trait are
-/// containers like `HashMap`, which need a generic way hash multiple types.
-pub trait Hasher<S> {
- /// Compute a hash of the value.
- fn hash<T: Hash<S>>(&self, value: &T) -> u64;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-macro_rules! impl_hash(
- ( $( $ty:ty => $method:ident;)* ) => (
- $(
- impl<S: Writer> Hash<S> for $ty {
- #[inline]
- fn hash(&self, state: &mut S) {
- state.$method(*self);
- }
- }
- )*
- )
-)
-
-impl_hash!(
- u8 => write_u8;
- u16 => write_le_u16;
- u32 => write_le_u32;
- u64 => write_le_u64;
- uint => write_le_uint;
- i8 => write_i8;
- i16 => write_le_i16;
- i32 => write_le_i32;
- i64 => write_le_i64;
- int => write_le_int;
-)
-
-impl<S: Writer> Hash<S> for bool {
- #[inline]
- fn hash(&self, state: &mut S) {
- (*self as u8).hash(state);
- }
-}
-
-impl<S: Writer> Hash<S> for char {
- #[inline]
- fn hash(&self, state: &mut S) {
- (*self as u32).hash(state);
- }
-}
-
-impl<'a, S: Writer> Hash<S> for &'a str {
- #[inline]
- fn hash(&self, state: &mut S) {
- state.write(self.as_bytes());
- state.write_u8(0xFF);
- }
-}
-
-macro_rules! impl_hash_tuple(
- () => (
- impl<S: Writer> Hash<S> for () {
- #[inline]
- fn hash(&self, state: &mut S) {
- state.write([]);
- }
- }
- );
-
- ($A:ident $($B:ident)*) => (
- impl<
- S: Writer,
- $A: Hash<S> $(, $B: Hash<S>)*
- > Hash<S> for ($A, $($B),*) {
- #[inline]
- fn hash(&self, state: &mut S) {
- match *self {
- (ref $A, $(ref $B),*) => {
- $A.hash(state);
- $(
- $B.hash(state);
- )*
- }
- }
- }
- }
-
- impl_hash_tuple!($($B)*)
- );
-)
-
-impl_hash_tuple!(a0 a1 a2 a3 a4 a5 a6 a7)
-
-impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
- #[inline]
- fn hash(&self, state: &mut S) {
- self.len().hash(state);
- for elt in self.iter() {
- elt.hash(state);
- }
- }
-}
-
-
-impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
- #[inline]
- fn hash(&self, state: &mut S) {
- self.as_slice().hash(state);
- }
-}
-
-impl<S: Writer, T: Hash<S>> Hash<S> for ~[T] {
- #[inline]
- fn hash(&self, state: &mut S) {
- self.as_slice().hash(state);
- }
-}
-
-impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
- #[inline]
- fn hash(&self, state: &mut S) {
- self.as_slice().hash(state);
- }
-}
-
-impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
- #[inline]
- fn hash(&self, state: &mut S) {
- (**self).hash(state);
- }
-}
-
-impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
- #[inline]
- fn hash(&self, state: &mut S) {
- (**self).hash(state);
- }
-}
-
-impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
- #[inline]
- fn hash(&self, state: &mut S) {
- (**self).hash(state);
- }
-}
-
-impl<S: Writer, T: Hash<S>> Hash<S> for @T {
- #[inline]
- fn hash(&self, state: &mut S) {
- (**self).hash(state);
- }
-}
-
-impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
- #[inline]
- fn hash(&self, state: &mut S) {
- (**self).hash(state);
- }
-}
-
-impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
- #[inline]
- fn hash(&self, state: &mut S) {
- match *self {
- Some(ref x) => {
- 0u8.hash(state);
- x.hash(state);
- }
- None => {
- 1u8.hash(state);
- }
- }
- }
-}
-
-impl<S: Writer, T> Hash<S> for *T {
- #[inline]
- fn hash(&self, state: &mut S) {
- // NB: raw-pointer Hash does _not_ dereference
- // to the target; it just gives you the pointer-bytes.
- (*self as uint).hash(state);
- }
-}
-
-impl<S: Writer, T> Hash<S> for *mut T {
- #[inline]
- fn hash(&self, state: &mut S) {
- // NB: raw-pointer Hash does _not_ dereference
- // to the target; it just gives you the pointer-bytes.
- (*self as uint).hash(state);
- }
-}
-
-impl<S: Writer> Hash<S> for TypeId {
- #[inline]
- fn hash(&self, state: &mut S) {
- self.hash().hash(state)
- }
-}
-
-impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
- #[inline]
- fn hash(&self, state: &mut S) {
- match *self {
- Ok(ref t) => { 1u.hash(state); t.hash(state); }
- Err(ref t) => { 2u.hash(state); t.hash(state); }
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-#[cfg(test)]
-mod tests {
- use mem;
- use io::{IoResult, Writer};
- use iter::{Iterator};
- use option::{Some, None};
- use result::Ok;
- use slice::ImmutableVector;
-
- use super::{Hash, Hasher};
-
- struct MyWriterHasher;
-
- impl Hasher<MyWriter> for MyWriterHasher {
- fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
- let mut state = MyWriter { hash: 0 };
- value.hash(&mut state);
- state.hash
- }
- }
-
- struct MyWriter {
- hash: u64,
- }
-
- impl Writer for MyWriter {
- // Most things we'll just add up the bytes.
- fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- for byte in buf.iter() {
- self.hash += *byte as u64;
- }
- Ok(())
- }
- }
-
- #[test]
- fn test_writer_hasher() {
- let hasher = MyWriterHasher;
-
- assert_eq!(hasher.hash(&()), 0);
-
- assert_eq!(hasher.hash(&5u8), 5);
- assert_eq!(hasher.hash(&5u16), 5);
- assert_eq!(hasher.hash(&5u32), 5);
- assert_eq!(hasher.hash(&5u64), 5);
- assert_eq!(hasher.hash(&5u), 5);
-
- assert_eq!(hasher.hash(&5i8), 5);
- assert_eq!(hasher.hash(&5i16), 5);
- assert_eq!(hasher.hash(&5i32), 5);
- assert_eq!(hasher.hash(&5i64), 5);
- assert_eq!(hasher.hash(&5i), 5);
-
- assert_eq!(hasher.hash(&false), 0);
- assert_eq!(hasher.hash(&true), 1);
-
- assert_eq!(hasher.hash(&'a'), 97);
-
- assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
- assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);
-
- unsafe {
- let ptr: *int = mem::transmute(5);
- assert_eq!(hasher.hash(&ptr), 5);
- }
-
- unsafe {
- let ptr: *mut int = mem::transmute(5);
- assert_eq!(hasher.hash(&ptr), 5);
- }
- }
-
- struct Custom {
- hash: u64
- }
-
- impl Hash<u64> for Custom {
- fn hash(&self, state: &mut u64) {
- *state = self.hash;
- }
- }
-
- #[test]
- fn test_custom_state() {
- let custom = Custom { hash: 5 };
- let mut state = 0;
- custom.hash(&mut state);
- assert_eq!(state, 5);
- }
-}
+++ /dev/null
-// 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.
-
-/*!
- * Implementation of SipHash 2-4
- *
- * See: http://131002.net/siphash/
- *
- * Consider this as a main "general-purpose" hash for all hashtables: it
- * runs at good speed (competitive with spooky and city) and permits
- * strong _keyed_ hashing. Key your hashtables from a strong RNG,
- * such as `rand::Rng`.
- *
- * Although the SipHash algorithm is considered to be cryptographically
- * strong, this implementation has not been reviewed for such purposes.
- * As such, all cryptographic uses of this implementation are strongly
- * discouraged.
- */
-
-use clone::Clone;
-use container::Container;
-use default::Default;
-use int;
-use io::{IoResult, Writer};
-use iter::Iterator;
-use result::Ok;
-use slice::ImmutableVector;
-use uint;
-
-use super::{Hash, Hasher};
-
-/// `SipState` computes a SipHash 2-4 hash over a stream of bytes.
-pub struct SipState {
- k0: u64,
- k1: u64,
- length: uint, // how many bytes we've processed
- v0: u64, // hash state
- v1: u64,
- v2: u64,
- v3: u64,
- tail: u64, // unprocessed bytes le
- ntail: uint, // how many bytes in tail are valid
-}
-
-// sadly, these macro definitions can't appear later,
-// because they're needed in the following defs;
-// this design could be improved.
-
-macro_rules! u8to64_le (
- ($buf:expr, $i:expr) =>
- ($buf[0+$i] as u64 |
- $buf[1+$i] as u64 << 8 |
- $buf[2+$i] as u64 << 16 |
- $buf[3+$i] as u64 << 24 |
- $buf[4+$i] as u64 << 32 |
- $buf[5+$i] as u64 << 40 |
- $buf[6+$i] as u64 << 48 |
- $buf[7+$i] as u64 << 56);
- ($buf:expr, $i:expr, $len:expr) =>
- ({
- let mut t = 0;
- let mut out = 0u64;
- while t < $len {
- out |= $buf[t+$i] as u64 << t*8;
- t += 1;
- }
- out
- });
-)
-
-macro_rules! rotl (
- ($x:expr, $b:expr) =>
- (($x << $b) | ($x >> (64 - $b)))
-)
-
-macro_rules! compress (
- ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
- ({
- $v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
- $v0 = rotl!($v0, 32);
- $v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
- $v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
- $v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
- $v2 = rotl!($v2, 32);
- })
-)
-
-impl SipState {
- /// Create a `SipState` that is keyed off the provided keys.
- #[inline]
- pub fn new() -> SipState {
- SipState::new_with_keys(0, 0)
- }
-
- /// Create a `SipState` that is keyed off the provided keys.
- #[inline]
- pub fn new_with_keys(key0: u64, key1: u64) -> SipState {
- let mut state = SipState {
- k0: key0,
- k1: key1,
- length: 0,
- v0: 0,
- v1: 0,
- v2: 0,
- v3: 0,
- tail: 0,
- ntail: 0,
- };
- state.reset();
- state
- }
-
- /// Reset the state back to it's initial state.
- #[inline]
- pub fn reset(&mut self) {
- self.length = 0;
- self.v0 = self.k0 ^ 0x736f6d6570736575;
- self.v1 = self.k1 ^ 0x646f72616e646f6d;
- self.v2 = self.k0 ^ 0x6c7967656e657261;
- self.v3 = self.k1 ^ 0x7465646279746573;
- self.ntail = 0;
- }
-
- /// Return the computed hash.
- #[inline]
- pub fn result(&self) -> u64 {
- let mut v0 = self.v0;
- let mut v1 = self.v1;
- let mut v2 = self.v2;
- let mut v3 = self.v3;
-
- let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
-
- v3 ^= b;
- compress!(v0, v1, v2, v3);
- compress!(v0, v1, v2, v3);
- v0 ^= b;
-
- v2 ^= 0xff;
- compress!(v0, v1, v2, v3);
- compress!(v0, v1, v2, v3);
- compress!(v0, v1, v2, v3);
- compress!(v0, v1, v2, v3);
-
- v0 ^ v1 ^ v2 ^ v3
- }
-
- #[inline]
- fn write_le(&mut self, n: u64, size: uint) {
- self.tail |= n << 8*self.ntail;
- self.ntail += size;
-
- if self.ntail >= 8 {
- let m = self.tail;
-
- self.v3 ^= m;
- compress!(self.v0, self.v1, self.v2, self.v3);
- compress!(self.v0, self.v1, self.v2, self.v3);
- self.v0 ^= m;
-
- self.ntail -= 8;
- if self.ntail == 0 {
- self.tail = 0;
- } else {
- self.tail = n >> 64 - 8*self.ntail;
- }
- }
- }
-}
-
-macro_rules! make_write_le(
- ($this:expr, $n:expr, $size:expr) => ({
- $this.write_le($n as u64, $size);
- $this.length += $size;
- Ok(())
- })
-)
-
-impl Writer for SipState {
- #[inline]
- fn write(&mut self, msg: &[u8]) -> IoResult<()> {
- let length = msg.len();
- self.length += length;
-
- let mut needed = 0u;
-
- if self.ntail != 0 {
- needed = 8 - self.ntail;
- if length < needed {
- self.tail |= u8to64_le!(msg, 0, length) << 8*self.ntail;
- self.ntail += length;
- return Ok(());
- }
-
- let m = self.tail | u8to64_le!(msg, 0, needed) << 8*self.ntail;
-
- self.v3 ^= m;
- compress!(self.v0, self.v1, self.v2, self.v3);
- compress!(self.v0, self.v1, self.v2, self.v3);
- self.v0 ^= m;
-
- self.ntail = 0;
- }
-
- // Buffered tail is now flushed, process new input.
- let len = length - needed;
- let end = len & (!0x7);
- let left = len & 0x7;
-
- let mut i = needed;
- while i < end {
- let mi = u8to64_le!(msg, i);
-
- self.v3 ^= mi;
- compress!(self.v0, self.v1, self.v2, self.v3);
- compress!(self.v0, self.v1, self.v2, self.v3);
- self.v0 ^= mi;
-
- i += 8;
- }
-
- self.tail = u8to64_le!(msg, i, left);
- self.ntail = left;
-
- Ok(())
- }
-
- #[inline]
- fn write_u8(&mut self, n: u8) -> IoResult<()> {
- make_write_le!(self, n, 1)
- }
-
- #[inline]
- fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
- make_write_le!(self, n, 2)
- }
-
- #[inline]
- fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
- make_write_le!(self, n, 4)
- }
-
- #[inline]
- fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
- make_write_le!(self, n, 8)
- }
-
- #[inline]
- fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
- make_write_le!(self, n, uint::BYTES)
- }
-
- #[inline]
- fn write_i8(&mut self, n: i8) -> IoResult<()> {
- make_write_le!(self, n, 1)
- }
-
- #[inline]
- fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
- make_write_le!(self, n, 2)
- }
-
- #[inline]
- fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
- make_write_le!(self, n, 4)
- }
-
- #[inline]
- fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
- make_write_le!(self, n, 8)
- }
-
- #[inline]
- fn write_le_int(&mut self, n: int) -> IoResult<()> {
- make_write_le!(self, n, int::BYTES)
- }
-
-}
-
-impl Clone for SipState {
- #[inline]
- fn clone(&self) -> SipState {
- *self
- }
-}
-
-impl Default for SipState {
- #[inline]
- fn default() -> SipState {
- SipState::new()
- }
-}
-
-/// `SipHasher` computes the SipHash algorithm from a stream of bytes.
-#[deriving(Clone)]
-pub struct SipHasher {
- k0: u64,
- k1: u64,
-}
-
-impl SipHasher {
- /// Create a `Sip`.
- #[inline]
- pub fn new() -> SipHasher {
- SipHasher::new_with_keys(0, 0)
- }
-
- /// Create a `Sip` that is keyed off the provided keys.
- #[inline]
- pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
- SipHasher {
- k0: key0,
- k1: key1,
- }
- }
-}
-
-impl Hasher<SipState> for SipHasher {
- #[inline]
- fn hash<T: Hash<SipState>>(&self, value: &T) -> u64 {
- let mut state = SipState::new_with_keys(self.k0, self.k1);
- value.hash(&mut state);
- state.result()
- }
-}
-
-impl Default for SipHasher {
- #[inline]
- fn default() -> SipHasher {
- SipHasher::new()
- }
-}
-
-/// Hash a value using the SipHash algorithm.
-#[inline]
-pub fn hash<T: Hash<SipState>>(value: &T) -> u64 {
- let mut state = SipState::new();
- value.hash(&mut state);
- state.result()
-}
-
-/// Hash a value with the SipHash algorithm with the provided keys.
-#[inline]
-pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
- let mut state = SipState::new_with_keys(k0, k1);
- value.hash(&mut state);
- state.result()
-}
-
-
-
-#[cfg(test)]
-mod tests {
- extern crate test;
- use prelude::*;
- use num::ToStrRadix;
- use option::{Some, None};
- use str::Str;
- use string::String;
- use slice::{Vector, ImmutableVector};
- use self::test::Bencher;
-
- use super::super::Hash;
- use super::{SipState, hash, hash_with_keys};
-
- // Hash just the bytes of the slice, without length prefix
- struct Bytes<'a>(&'a [u8]);
-
- impl<'a, S: Writer> Hash<S> for Bytes<'a> {
- #[allow(unused_must_use)]
- fn hash(&self, state: &mut S) {
- let Bytes(v) = *self;
- state.write(v);
- }
- }
-
- #[test]
- #[allow(unused_must_use)]
- fn test_siphash() {
- let vecs : [[u8, ..8], ..64] = [
- [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
- [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
- [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
- [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
- [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
- [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
- [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
- [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
- [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
- [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
- [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
- [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
- [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
- [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
- [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
- [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
- [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
- [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
- [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
- [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
- [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
- [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
- [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
- [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
- [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
- [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
- [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
- [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
- [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
- [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
- [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
- [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
- [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
- [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
- [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
- [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
- [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
- [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
- [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
- [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
- [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
- [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
- [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
- [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
- [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
- [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
- [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
- [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
- [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
- [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
- [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
- [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
- [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
- [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
- [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
- [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
- [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
- [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
- [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
- [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
- [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
- [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
- [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
- [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
- ];
-
- let k0 = 0x_07_06_05_04_03_02_01_00_u64;
- let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64;
- let mut buf = Vec::new();
- let mut t = 0;
- let mut state_inc = SipState::new_with_keys(k0, k1);
- let mut state_full = SipState::new_with_keys(k0, k1);
-
- fn to_hex_str(r: &[u8, ..8]) -> String {
- let mut s = String::new();
- for b in r.iter() {
- s.push_str((*b as uint).to_str_radix(16u).as_slice());
- }
- s
- }
-
- fn result_bytes(h: u64) -> ~[u8] {
- box [(h >> 0) as u8,
- (h >> 8) as u8,
- (h >> 16) as u8,
- (h >> 24) as u8,
- (h >> 32) as u8,
- (h >> 40) as u8,
- (h >> 48) as u8,
- (h >> 56) as u8,
- ]
- }
-
- fn result_str(h: u64) -> String {
- let r = result_bytes(h);
- let mut s = String::new();
- for b in r.iter() {
- s.push_str((*b as uint).to_str_radix(16u).as_slice());
- }
- s
- }
-
- while t < 64 {
- debug!("siphash test {}", t);
- let vec = u8to64_le!(vecs[t], 0);
- let out = hash_with_keys(k0, k1, &Bytes(buf.as_slice()));
- debug!("got {:?}, expected {:?}", out, vec);
- assert_eq!(vec, out);
-
- state_full.reset();
- state_full.write(buf.as_slice());
- let f = result_str(state_full.result());
- let i = result_str(state_inc.result());
- let v = to_hex_str(&vecs[t]);
- debug!("{}: ({}) => inc={} full={}", t, v, i, f);
-
- assert!(f == i && f == v);
-
- buf.push(t as u8);
- state_inc.write_u8(t as u8);
-
- t += 1;
- }
- }
-
- #[test] #[cfg(target_arch = "arm")]
- fn test_hash_uint() {
- let val = 0xdeadbeef_deadbeef_u64;
- assert!(hash(&(val as u64)) != hash(&(val as uint)));
- assert_eq!(hash(&(val as u32)), hash(&(val as uint)));
- }
- #[test] #[cfg(target_arch = "x86_64")]
- fn test_hash_uint() {
- let val = 0xdeadbeef_deadbeef_u64;
- assert_eq!(hash(&(val as u64)), hash(&(val as uint)));
- assert!(hash(&(val as u32)) != hash(&(val as uint)));
- }
- #[test] #[cfg(target_arch = "x86")]
- fn test_hash_uint() {
- let val = 0xdeadbeef_deadbeef_u64;
- assert!(hash(&(val as u64)) != hash(&(val as uint)));
- assert_eq!(hash(&(val as u32)), hash(&(val as uint)));
- }
-
- #[test]
- fn test_hash_idempotent() {
- let val64 = 0xdeadbeef_deadbeef_u64;
- assert_eq!(hash(&val64), hash(&val64));
- let val32 = 0xdeadbeef_u32;
- assert_eq!(hash(&val32), hash(&val32));
- }
-
- #[test]
- fn test_hash_no_bytes_dropped_64() {
- let val = 0xdeadbeef_deadbeef_u64;
-
- assert!(hash(&val) != hash(&zero_byte(val, 0)));
- assert!(hash(&val) != hash(&zero_byte(val, 1)));
- assert!(hash(&val) != hash(&zero_byte(val, 2)));
- assert!(hash(&val) != hash(&zero_byte(val, 3)));
- assert!(hash(&val) != hash(&zero_byte(val, 4)));
- assert!(hash(&val) != hash(&zero_byte(val, 5)));
- assert!(hash(&val) != hash(&zero_byte(val, 6)));
- assert!(hash(&val) != hash(&zero_byte(val, 7)));
-
- fn zero_byte(val: u64, byte: uint) -> u64 {
- assert!(byte < 8);
- val & !(0xff << (byte * 8))
- }
- }
-
- #[test]
- fn test_hash_no_bytes_dropped_32() {
- let val = 0xdeadbeef_u32;
-
- assert!(hash(&val) != hash(&zero_byte(val, 0)));
- assert!(hash(&val) != hash(&zero_byte(val, 1)));
- assert!(hash(&val) != hash(&zero_byte(val, 2)));
- assert!(hash(&val) != hash(&zero_byte(val, 3)));
-
- fn zero_byte(val: u32, byte: uint) -> u32 {
- assert!(byte < 4);
- val & !(0xff << (byte * 8))
- }
- }
-
- #[test]
- fn test_hash_no_concat_alias() {
- let s = ("aa", "bb");
- let t = ("aabb", "");
- let u = ("a", "abb");
-
- assert!(s != t && t != u);
- assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
-
- let v = (&[1u8], &[0u8, 0], &[0u8]);
- let w = (&[1u8, 0, 0, 0], &[], &[]);
-
- assert!(v != w);
- assert!(hash(&v) != hash(&w));
- }
-
- #[bench]
- fn bench_str_under_8_bytes(b: &mut Bencher) {
- let s = "foo";
- b.iter(|| {
- assert_eq!(hash(&s), 16262950014981195938);
- })
- }
-
- #[bench]
- fn bench_str_of_8_bytes(b: &mut Bencher) {
- let s = "foobar78";
- b.iter(|| {
- assert_eq!(hash(&s), 4898293253460910787);
- })
- }
-
- #[bench]
- fn bench_str_over_8_bytes(b: &mut Bencher) {
- let s = "foobarbaz0";
- b.iter(|| {
- assert_eq!(hash(&s), 10581415515220175264);
- })
- }
-
- #[bench]
- fn bench_long_str(b: &mut Bencher) {
- let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
-incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
-exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
-irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
-pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
-officia deserunt mollit anim id est laborum.";
- b.iter(|| {
- assert_eq!(hash(&s), 17717065544121360093);
- })
- }
-
- #[bench]
- fn bench_u64(b: &mut Bencher) {
- let u = 16262950014981195938u64;
- b.iter(|| {
- assert_eq!(hash(&u), 5254097107239593357);
- })
- }
-
- #[deriving(Hash)]
- struct Compound {
- x: u8,
- y: u64,
- }
-
- #[bench]
- fn bench_compound_1(b: &mut Bencher) {
- let compound = Compound {
- x: 1,
- y: 2,
- };
- b.iter(|| {
- assert_eq!(hash(&compound), 12506681940457338191);
- })
- }
-}
extern crate core;
extern crate libc;
extern crate core_rand = "rand";
+extern crate core_collections = "collections";
// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate realstd = "std";
pub use alloc::owned;
pub use alloc::rc;
+pub use core_collections::hash;
+pub use core_collections::slice;
+pub use core_collections::str;
+pub use core_collections::string;
+pub use core_collections::vec;
+
// Run tests with libgreen instead of libnative.
//
// FIXME: This egregiously hacks around starting the test runner in a different
#[path = "num/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64;
-pub mod slice;
-pub mod vec;
-pub mod str;
-pub mod string;
pub mod rand;
pub mod ascii;
pub mod from_str;
pub mod num;
pub mod to_str;
-pub mod hash;
+
+/* Common data structures */
+
+pub mod collections;
/* Tasks and communication */
#[unstable]
pub mod unstable;
-/* For internal use, not exported */
-
-mod unicode;
-
// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
// but name resolution doesn't work without it being pub.
#[unstable]
//! POSIX file path handling
-use container::Container;
use c_str::{CString, ToCStr};
use clone::Clone;
use cmp::{PartialEq, Eq};
+use container::Container;
use from_str::FromStr;
+use hash;
use io::Writer;
use iter::{DoubleEndedIterator, AdditiveIterator, Extendable, Iterator, Map};
use option::{Option, None, Some};
-use str;
use str::Str;
+use str;
use slice::{CloneableVector, Splits, Vector, VectorVector,
ImmutableEqVector, OwnedVector, ImmutableVector};
use vec::Vec;
}
}
-impl<S: Writer> ::hash::Hash<S> for Path {
+impl<S: hash::Writer> hash::Hash<S> for Path {
#[inline]
fn hash(&self, state: &mut S) {
self.repr.hash(state)
use cmp::{PartialEq, Eq};
use container::Container;
use from_str::FromStr;
+use hash;
use io::Writer;
use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Iterator, Map};
use mem;
}
}
-impl<S: Writer> ::hash::Hash<S> for Path {
+impl<S: hash::Writer> hash::Hash<S> for Path {
#[cfg(not(test))]
#[inline]
fn hash(&self, state: &mut S) {
+++ /dev/null
-// 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.
-
-/*!
-
-Utilities for vector manipulation
-
-The `vec` module contains useful code to help work with vector values.
-Vectors are Rust's list type. Vectors contain zero or more values of
-homogeneous types:
-
-```rust
-let int_vector = [1,2,3];
-let str_vector = ["one", "two", "three"];
-```
-
-This is a big module, but for a high-level overview:
-
-## Structs
-
-Several structs that are useful for vectors, such as `Items`, which
-represents iteration over a vector.
-
-## Traits
-
-A number of traits add methods that allow you to accomplish tasks with vectors.
-
-Traits defined for the `&[T]` type (a vector slice), have methods that can be
-called on either owned vectors, denoted `~[T]`, or on vector slices themselves.
-These traits include `ImmutableVector`, and `MutableVector` for the `&mut [T]`
-case.
-
-An example is the method `.slice(a, b)` that returns an immutable "view" into
-a vector or a vector slice from the index interval `[a, b)`:
-
-```rust
-let numbers = [0, 1, 2];
-let last_numbers = numbers.slice(1, 3);
-// last_numbers is now &[1, 2]
-```
-
-Traits defined for the `~[T]` type, like `OwnedVector`, can only be called
-on such vectors. These methods deal with adding elements or otherwise changing
-the allocation of the vector.
-
-An example is the method `.push(element)` that will add an element at the end
-of the vector:
-
-```rust
-let mut numbers = vec![0, 1, 2];
-numbers.push(7);
-// numbers is now vec![0, 1, 2, 7];
-```
-
-## Implementations of other traits
-
-Vectors are a very useful type, and so there's several implementations of
-traits from other modules. Some notable examples:
-
-* `Clone`
-* `Eq`, `Ord`, `Eq`, `Ord` -- vectors can be compared,
- if the element type defines the corresponding trait.
-
-## Iteration
-
-The method `iter()` returns an iteration value for a vector or a vector slice.
-The iterator yields references to the vector's elements, so if the element
-type of the vector is `int`, the element type of the iterator is `&int`.
-
-```rust
-let numbers = [0, 1, 2];
-for &x in numbers.iter() {
- println!("{} is a number!", x);
-}
-```
-
-* `.mut_iter()` returns an iterator that allows modifying each value.
-* `.move_iter()` converts an owned vector into an iterator that
- moves out a value from the vector each iteration.
-* Further iterators exist that split, chunk or permute the vector.
-
-## Function definitions
-
-There are a number of free functions that create or take vectors, for example:
-
-* Creating a vector, like `from_elem` and `from_fn`
-* Creating a vector with a given size: `with_capacity`
-* Modifying a vector and returning it, like `append`
-* Operations on paired elements, like `unzip`.
-
-*/
-
-#![doc(primitive = "slice")]
-
-use mem::transmute;
-use clone::Clone;
-use cmp::{Ord, Ordering, Less, Greater};
-use cmp;
-use container::Container;
-use iter::*;
-use mem::size_of;
-use mem;
-use ops::Drop;
-use option::{None, Option, Some};
-use ptr::RawPtr;
-use ptr;
-use rt::heap::{allocate, deallocate};
-use finally::try_finally;
-use vec::Vec;
-
-pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
-pub use core::slice::{Chunks, Vector, ImmutableVector, ImmutableEqVector};
-pub use core::slice::{ImmutableOrdVector, MutableVector, Items, MutItems};
-pub use core::slice::{MutSplits, MutChunks};
-pub use core::slice::{bytes, MutableCloneableVector};
-
-// Functional utilities
-
-#[allow(missing_doc)]
-pub trait VectorVector<T> {
- // FIXME #5898: calling these .concat and .connect conflicts with
- // StrVector::con{cat,nect}, since they have generic contents.
- /// Flattens a vector of vectors of T into a single vector of T.
- fn concat_vec(&self) -> Vec<T>;
-
- /// Concatenate a vector of vectors, placing a given separator between each.
- fn connect_vec(&self, sep: &T) -> Vec<T>;
-}
-
-impl<'a, T: Clone, V: Vector<T>> VectorVector<T> for &'a [V] {
- fn concat_vec(&self) -> Vec<T> {
- let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
- let mut result = Vec::with_capacity(size);
- for v in self.iter() {
- result.push_all(v.as_slice())
- }
- result
- }
-
- fn connect_vec(&self, sep: &T) -> Vec<T> {
- let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
- let mut result = Vec::with_capacity(size + self.len());
- let mut first = true;
- for v in self.iter() {
- if first { first = false } else { result.push(sep.clone()) }
- result.push_all(v.as_slice())
- }
- result
- }
-}
-
-/// An Iterator that yields the element swaps needed to produce
-/// a sequence of all possible permutations for an indexed sequence of
-/// elements. Each permutation is only a single swap apart.
-///
-/// The Steinhaus–Johnson–Trotter algorithm is used.
-///
-/// Generates even and odd permutations alternately.
-///
-/// The last generated swap is always (0, 1), and it returns the
-/// sequence to its initial order.
-pub struct ElementSwaps {
- sdir: Vec<SizeDirection>,
- /// If true, emit the last swap that returns the sequence to initial state
- emit_reset: bool,
- swaps_made : uint,
-}
-
-impl ElementSwaps {
- /// Create an `ElementSwaps` iterator for a sequence of `length` elements
- pub fn new(length: uint) -> ElementSwaps {
- // Initialize `sdir` with a direction that position should move in
- // (all negative at the beginning) and the `size` of the
- // element (equal to the original index).
- ElementSwaps{
- emit_reset: true,
- sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(),
- swaps_made: 0
- }
- }
-}
-
-enum Direction { Pos, Neg }
-
-/// An Index and Direction together
-struct SizeDirection {
- size: uint,
- dir: Direction,
-}
-
-impl Iterator<(uint, uint)> for ElementSwaps {
- #[inline]
- fn next(&mut self) -> Option<(uint, uint)> {
- fn new_pos(i: uint, s: Direction) -> uint {
- i + match s { Pos => 1, Neg => -1 }
- }
-
- // Find the index of the largest mobile element:
- // The direction should point into the vector, and the
- // swap should be with a smaller `size` element.
- let max = self.sdir.iter().map(|&x| x).enumerate()
- .filter(|&(i, sd)|
- new_pos(i, sd.dir) < self.sdir.len() &&
- self.sdir.get(new_pos(i, sd.dir)).size < sd.size)
- .max_by(|&(_, sd)| sd.size);
- match max {
- Some((i, sd)) => {
- let j = new_pos(i, sd.dir);
- self.sdir.as_mut_slice().swap(i, j);
-
- // Swap the direction of each larger SizeDirection
- for x in self.sdir.mut_iter() {
- if x.size > sd.size {
- x.dir = match x.dir { Pos => Neg, Neg => Pos };
- }
- }
- self.swaps_made += 1;
- Some((i, j))
- },
- None => if self.emit_reset {
- self.emit_reset = false;
- if self.sdir.len() > 1 {
- // The last swap
- self.swaps_made += 1;
- Some((0, 1))
- } else {
- // Vector is of the form [] or [x], and the only permutation is itself
- self.swaps_made += 1;
- Some((0,0))
- }
- } else { None }
- }
- }
-
- #[inline]
- fn size_hint(&self) -> (uint, Option<uint>) {
- // For a vector of size n, there are exactly n! permutations.
- let n = range(2, self.sdir.len() + 1).product();
- (n - self.swaps_made, Some(n - self.swaps_made))
- }
-}
-
-/// An Iterator that uses `ElementSwaps` to iterate through
-/// all possible permutations of a vector.
-///
-/// The first iteration yields a clone of the vector as it is,
-/// then each successive element is the vector with one
-/// swap applied.
-///
-/// Generates even and odd permutations alternately.
-pub struct Permutations<T> {
- swaps: ElementSwaps,
- v: ~[T],
-}
-
-impl<T: Clone> Iterator<~[T]> for Permutations<T> {
- #[inline]
- fn next(&mut self) -> Option<~[T]> {
- match self.swaps.next() {
- None => None,
- Some((0,0)) => Some(self.v.clone()),
- Some((a, b)) => {
- let elt = self.v.clone();
- self.v.swap(a, b);
- Some(elt)
- }
- }
- }
-
- #[inline]
- fn size_hint(&self) -> (uint, Option<uint>) {
- self.swaps.size_hint()
- }
-}
-
-/// Extension methods for vector slices with cloneable elements
-pub trait CloneableVector<T> {
- /// Copy `self` into a new owned vector
- fn to_owned(&self) -> ~[T];
-
- /// Convert `self` into an owned vector, not making a copy if possible.
- fn into_owned(self) -> ~[T];
-}
-
-/// Extension methods for vector slices
-impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
- /// Returns a copy of `v`.
- #[inline]
- fn to_owned(&self) -> ~[T] {
- use RawVec = core::raw::Vec;
- use num::{CheckedAdd, CheckedMul};
-
- let len = self.len();
- let data_size = len.checked_mul(&mem::size_of::<T>());
- let data_size = data_size.expect("overflow in to_owned()");
- let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
- let size = size.expect("overflow in to_owned()");
-
- unsafe {
- // this should pass the real required alignment
- let ret = allocate(size, 8) as *mut RawVec<()>;
-
- let a_size = mem::size_of::<T>();
- let a_size = if a_size == 0 {1} else {a_size};
- (*ret).fill = len * a_size;
- (*ret).alloc = len * a_size;
-
- // Be careful with the following loop. We want it to be optimized
- // to a memcpy (or something similarly fast) when T is Copy. LLVM
- // is easily confused, so any extra operations during the loop can
- // prevent this optimization.
- let mut i = 0;
- let p = &mut (*ret).data as *mut _ as *mut T;
- try_finally(
- &mut i, (),
- |i, ()| while *i < len {
- mem::overwrite(
- &mut(*p.offset(*i as int)),
- self.unsafe_ref(*i).clone());
- *i += 1;
- },
- |i| if *i < len {
- // we must be failing, clean up after ourselves
- for j in range(0, *i as int) {
- ptr::read(&*p.offset(j));
- }
- // FIXME: #13994 (should pass align and size here)
- deallocate(ret as *mut u8, 0, 8);
- });
- mem::transmute(ret)
- }
- }
-
- #[inline(always)]
- fn into_owned(self) -> ~[T] { self.to_owned() }
-}
-
-/// Extension methods for owned vectors
-impl<T: Clone> CloneableVector<T> for ~[T] {
- #[inline]
- fn to_owned(&self) -> ~[T] { self.clone() }
-
- #[inline(always)]
- fn into_owned(self) -> ~[T] { self }
-}
-
-/// Extension methods for vectors containing `Clone` elements.
-pub trait ImmutableCloneableVector<T> {
- /// Partitions the vector into two vectors `(A,B)`, where all
- /// elements of `A` satisfy `f` and all elements of `B` do not.
- fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
-
- /// Create an iterator that yields every possible permutation of the
- /// vector in succession.
- fn permutations(self) -> Permutations<T>;
-}
-
-impl<'a,T:Clone> ImmutableCloneableVector<T> for &'a [T] {
- #[inline]
- fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
- let mut lefts = Vec::new();
- let mut rights = Vec::new();
-
- for elt in self.iter() {
- if f(elt) {
- lefts.push((*elt).clone());
- } else {
- rights.push((*elt).clone());
- }
- }
-
- (lefts, rights)
- }
-
- fn permutations(self) -> Permutations<T> {
- Permutations{
- swaps: ElementSwaps::new(self.len()),
- v: self.to_owned(),
- }
- }
-
-}
-
-/// Extension methods for owned vectors.
-pub trait OwnedVector<T> {
- /// Creates a consuming iterator, that is, one that moves each
- /// value out of the vector (from start to end). The vector cannot
- /// be used after calling this.
- ///
- /// # Examples
- ///
- /// ```rust
- /// let v = ~["a".to_string(), "b".to_string()];
- /// for s in v.move_iter() {
- /// // s has type ~str, not &~str
- /// println!("{}", s);
- /// }
- /// ```
- fn move_iter(self) -> MoveItems<T>;
-
- /**
- * Partitions the vector into two vectors `(A,B)`, where all
- * elements of `A` satisfy `f` and all elements of `B` do not.
- */
- fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
-}
-
-impl<T> OwnedVector<T> for ~[T] {
- #[inline]
- fn move_iter(self) -> MoveItems<T> {
- unsafe {
- let iter = transmute(self.iter());
- let ptr = transmute(self);
- MoveItems { allocation: ptr, iter: iter }
- }
- }
-
- #[inline]
- fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
- let mut lefts = Vec::new();
- let mut rights = Vec::new();
-
- for elt in self.move_iter() {
- if f(&elt) {
- lefts.push(elt);
- } else {
- rights.push(elt);
- }
- }
-
- (lefts, rights)
- }
-}
-
-fn insertion_sort<T>(v: &mut [T], compare: |&T, &T| -> Ordering) {
- let len = v.len() as int;
- let buf_v = v.as_mut_ptr();
-
- // 1 <= i < len;
- for i in range(1, len) {
- // j satisfies: 0 <= j <= i;
- let mut j = i;
- unsafe {
- // `i` is in bounds.
- let read_ptr = buf_v.offset(i) as *T;
-
- // find where to insert, we need to do strict <,
- // rather than <=, to maintain stability.
-
- // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
- while j > 0 &&
- compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
- j -= 1;
- }
-
- // shift everything to the right, to make space to
- // insert this value.
-
- // j + 1 could be `len` (for the last `i`), but in
- // that case, `i == j` so we don't copy. The
- // `.offset(j)` is always in bounds.
-
- if i != j {
- let tmp = ptr::read(read_ptr);
- ptr::copy_memory(buf_v.offset(j + 1),
- &*buf_v.offset(j),
- (i - j) as uint);
- ptr::copy_nonoverlapping_memory(buf_v.offset(j),
- &tmp as *T,
- 1);
- mem::forget(tmp);
- }
- }
- }
-}
-
-fn merge_sort<T>(v: &mut [T], compare: |&T, &T| -> Ordering) {
- // warning: this wildly uses unsafe.
- static BASE_INSERTION: uint = 32;
- static LARGE_INSERTION: uint = 16;
-
- // FIXME #12092: smaller insertion runs seems to make sorting
- // vectors of large elements a little faster on some platforms,
- // but hasn't been tested/tuned extensively
- let insertion = if size_of::<T>() <= 16 {
- BASE_INSERTION
- } else {
- LARGE_INSERTION
- };
-
- let len = v.len();
-
- // short vectors get sorted in-place via insertion sort to avoid allocations
- if len <= insertion {
- insertion_sort(v, compare);
- return;
- }
-
- // allocate some memory to use as scratch memory, we keep the
- // length 0 so we can keep shallow copies of the contents of `v`
- // without risking the dtors running on an object twice if
- // `compare` fails.
- let mut working_space = Vec::with_capacity(2 * len);
- // these both are buffers of length `len`.
- let mut buf_dat = working_space.as_mut_ptr();
- let mut buf_tmp = unsafe {buf_dat.offset(len as int)};
-
- // length `len`.
- let buf_v = v.as_ptr();
-
- // step 1. sort short runs with insertion sort. This takes the
- // values from `v` and sorts them into `buf_dat`, leaving that
- // with sorted runs of length INSERTION.
-
- // 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) {
- // start <= i < len;
- for i in range(start, cmp::min(start + insertion, len)) {
- // j satisfies: start <= j <= i;
- let mut j = i as int;
- unsafe {
- // `i` is in bounds.
- let read_ptr = buf_v.offset(i as int);
-
- // find where to insert, we need to do strict <,
- // rather than <=, to maintain stability.
-
- // start <= j - 1 < len, so .offset(j - 1) is in
- // bounds.
- while j > start as int &&
- compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less {
- j -= 1;
- }
-
- // shift everything to the right, to make space to
- // insert this value.
-
- // j + 1 could be `len` (for the last `i`), but in
- // that case, `i == j` so we don't copy. The
- // `.offset(j)` is always in bounds.
- ptr::copy_memory(buf_dat.offset(j + 1),
- &*buf_dat.offset(j),
- i - j as uint);
- ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
- }
- }
- }
-
- // step 2. merge the sorted runs.
- let mut width = insertion;
- while width < len {
- // merge the sorted runs of length `width` in `buf_dat` two at
- // a time, placing the result in `buf_tmp`.
-
- // 0 <= start <= len.
- for start in range_step(0, len, 2 * width) {
- // manipulate pointers directly for speed (rather than
- // using a `for` loop with `range` and `.offset` inside
- // that loop).
- unsafe {
- // the end of the first run & start of the
- // second. Offset of `len` is defined, since this is
- // precisely one byte past the end of the object.
- let right_start = buf_dat.offset(cmp::min(start + width, len) as int);
- // end of the second. Similar reasoning to the above re safety.
- let right_end_idx = cmp::min(start + 2 * width, len);
- let right_end = buf_dat.offset(right_end_idx as int);
-
- // the pointers to the elements under consideration
- // from the two runs.
-
- // both of these are in bounds.
- let mut left = buf_dat.offset(start as int);
- let mut right = right_start;
-
- // where we're putting the results, it is a run of
- // length `2*width`, so we step it once for each step
- // of either `left` or `right`. `buf_tmp` has length
- // `len`, so these are in bounds.
- let mut out = buf_tmp.offset(start as int);
- let out_end = buf_tmp.offset(right_end_idx as int);
-
- while out < out_end {
- // Either the left or the right run are exhausted,
- // so just copy the remainder from the other run
- // and move on; this gives a huge speed-up (order
- // of 25%) for mostly sorted vectors (the best
- // case).
- if left == right_start {
- // the number remaining in this run.
- let elems = (right_end as uint - right as uint) / mem::size_of::<T>();
- ptr::copy_nonoverlapping_memory(out, &*right, elems);
- break;
- } else if right == right_end {
- let elems = (right_start as uint - left as uint) / mem::size_of::<T>();
- ptr::copy_nonoverlapping_memory(out, &*left, elems);
- break;
- }
-
- // check which side is smaller, and that's the
- // next element for the new run.
-
- // `left < right_start` and `right < right_end`,
- // so these are valid.
- let to_copy = if compare(&*left, &*right) == Greater {
- step(&mut right)
- } else {
- step(&mut left)
- };
- ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
- step(&mut out);
- }
- }
- }
-
- mem::swap(&mut buf_dat, &mut buf_tmp);
-
- width *= 2;
- }
-
- // write the result to `v` in one go, so that there are never two copies
- // of the same object in `v`.
- unsafe {
- ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
- }
-
- // increment the pointer, returning the old pointer.
- #[inline(always)]
- unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
- let old = *ptr;
- *ptr = ptr.offset(1);
- old
- }
-}
-
-/// Extension methods for vectors such that their elements are
-/// mutable.
-pub trait MutableVectorAllocating<'a, T> {
- /// Sort the vector, 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`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut v = [5i, 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]);
- /// ```
- fn sort_by(self, compare: |&T, &T| -> Ordering);
-
- /**
- * 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 `str` to stop copying from
- */
- fn move_from(self, src: ~[T], start: uint, end: uint) -> uint;
-}
-
-impl<'a,T> MutableVectorAllocating<'a, T> for &'a mut [T] {
- #[inline]
- fn sort_by(self, compare: |&T, &T| -> Ordering) {
- merge_sort(self, compare)
- }
-
- #[inline]
- fn move_from(self, mut src: ~[T], start: uint, end: uint) -> uint {
- for (a, b) in self.mut_iter().zip(src.mut_slice(start, end).mut_iter()) {
- mem::swap(a, b);
- }
- cmp::min(self.len(), end-start)
- }
-}
-
-/// Methods for mutable vectors with orderable elements, such as
-/// in-place sorting.
-pub trait MutableOrdVector<T> {
- /// Sort the vector, in place.
- ///
- /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut v = [-5, 4, 1, -3, 2];
- ///
- /// v.sort();
- /// assert!(v == [-5, -3, 1, 2, 4]);
- /// ```
- fn sort(self);
-
- /// Mutates the slice to the next lexicographic permutation.
- ///
- /// Returns `true` if successful, `false` if the slice is at the last-ordered permutation.
- ///
- /// # Example
- ///
- /// ```rust
- /// let v = &mut [0, 1, 2];
- /// v.next_permutation();
- /// assert_eq!(v, &mut [0, 2, 1]);
- /// v.next_permutation();
- /// assert_eq!(v, &mut [1, 0, 2]);
- /// ```
- fn next_permutation(self) -> bool;
-
- /// Mutates the slice to the previous lexicographic permutation.
- ///
- /// Returns `true` if successful, `false` if the slice is at the first-ordered permutation.
- ///
- /// # Example
- ///
- /// ```rust
- /// let v = &mut [1, 0, 2];
- /// v.prev_permutation();
- /// assert_eq!(v, &mut [0, 2, 1]);
- /// v.prev_permutation();
- /// assert_eq!(v, &mut [0, 1, 2]);
- /// ```
- fn prev_permutation(self) -> bool;
-}
-
-impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
- #[inline]
- fn sort(self) {
- self.sort_by(|a,b| a.cmp(b))
- }
-
- fn next_permutation(self) -> bool {
- // These cases only have 1 permutation each, so we can't do anything.
- if self.len() < 2 { return false; }
-
- // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
- let mut i = self.len() - 1;
- while i > 0 && self[i-1] >= self[i] {
- i -= 1;
- }
-
- // If that is the entire vector, this is the last-ordered permutation.
- if i == 0 {
- return false;
- }
-
- // Step 2: Find the rightmost element larger than the pivot (i-1)
- let mut j = self.len() - 1;
- while j >= i && self[j] <= self[i-1] {
- j -= 1;
- }
-
- // Step 3: Swap that element with the pivot
- self.swap(j, i-1);
-
- // Step 4: Reverse the (previously) weakly decreasing part
- self.mut_slice_from(i).reverse();
-
- true
- }
-
- fn prev_permutation(self) -> bool {
- // These cases only have 1 permutation each, so we can't do anything.
- if self.len() < 2 { return false; }
-
- // Step 1: Identify the longest, rightmost weakly increasing part of the vector
- let mut i = self.len() - 1;
- while i > 0 && self[i-1] <= self[i] {
- i -= 1;
- }
-
- // If that is the entire vector, this is the first-ordered permutation.
- if i == 0 {
- return false;
- }
-
- // Step 2: Reverse the weakly increasing part
- self.mut_slice_from(i).reverse();
-
- // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
- let mut j = self.len() - 1;
- while j >= i && self[j-1] < self[i-1] {
- j -= 1;
- }
-
- // Step 4: Swap that element with the pivot
- self.swap(i-1, j);
-
- true
- }
-}
-
-/// Unsafe operations
-pub mod raw {
- pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};
- pub use core::slice::raw::{shift_ptr, pop_ptr};
-}
-
-/// An iterator that moves out of a vector.
-pub struct MoveItems<T> {
- allocation: *mut u8, // the block of memory allocated for the vector
- iter: Items<'static, T>
-}
-
-impl<T> Iterator<T> for MoveItems<T> {
- #[inline]
- fn next(&mut self) -> Option<T> {
- unsafe {
- self.iter.next().map(|x| ptr::read(x))
- }
- }
-
- #[inline]
- fn size_hint(&self) -> (uint, Option<uint>) {
- self.iter.size_hint()
- }
-}
-
-impl<T> DoubleEndedIterator<T> for MoveItems<T> {
- #[inline]
- fn next_back(&mut self) -> Option<T> {
- unsafe {
- self.iter.next_back().map(|x| ptr::read(x))
- }
- }
-}
-
-#[unsafe_destructor]
-impl<T> Drop for MoveItems<T> {
- fn drop(&mut self) {
- // destroy the remaining elements
- for _x in *self {}
- unsafe {
- // FIXME: #13994 (should pass align and size here)
- deallocate(self.allocation, 0, 8)
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use prelude::*;
- use cmp::*;
- use mem;
- use owned::Box;
- use rand::{Rng, task_rng};
- use slice::*;
-
- fn square(n: uint) -> uint { n * n }
-
- fn is_odd(n: &uint) -> bool { *n % 2u == 1u }
-
- #[test]
- fn test_from_fn() {
- // Test on-stack from_fn.
- let mut v = Vec::from_fn(3u, square);
- {
- let v = v.as_slice();
- assert_eq!(v.len(), 3u);
- assert_eq!(v[0], 0u);
- assert_eq!(v[1], 1u);
- assert_eq!(v[2], 4u);
- }
-
- // Test on-heap from_fn.
- v = Vec::from_fn(5u, square);
- {
- let v = v.as_slice();
- assert_eq!(v.len(), 5u);
- assert_eq!(v[0], 0u);
- assert_eq!(v[1], 1u);
- assert_eq!(v[2], 4u);
- assert_eq!(v[3], 9u);
- assert_eq!(v[4], 16u);
- }
- }
-
- #[test]
- fn test_from_elem() {
- // Test on-stack from_elem.
- let mut v = Vec::from_elem(2u, 10u);
- {
- let v = v.as_slice();
- assert_eq!(v.len(), 2u);
- assert_eq!(v[0], 10u);
- assert_eq!(v[1], 10u);
- }
-
- // Test on-heap from_elem.
- v = Vec::from_elem(6u, 20u);
- {
- let v = v.as_slice();
- assert_eq!(v[0], 20u);
- assert_eq!(v[1], 20u);
- assert_eq!(v[2], 20u);
- assert_eq!(v[3], 20u);
- assert_eq!(v[4], 20u);
- assert_eq!(v[5], 20u);
- }
- }
-
- #[test]
- fn test_is_empty() {
- let xs: [int, ..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 = box [11];
- assert_eq!(a.get(1), None);
- a = box [11, 12];
- assert_eq!(a.get(1).unwrap(), &12);
- a = box [11, 12, 13];
- assert_eq!(a.get(1).unwrap(), &12);
- }
-
- #[test]
- fn test_head() {
- let mut a = box [];
- assert_eq!(a.head(), None);
- a = box [11];
- assert_eq!(a.head().unwrap(), &11);
- a = box [11, 12];
- assert_eq!(a.head().unwrap(), &11);
- }
-
- #[test]
- fn test_tail() {
- let mut a = box [11];
- assert_eq!(a.tail(), &[]);
- a = box [11, 12];
- assert_eq!(a.tail(), &[12]);
- }
-
- #[test]
- #[should_fail]
- fn test_tail_empty() {
- let a: ~[int] = box [];
- a.tail();
- }
-
- #[test]
- fn test_tailn() {
- let mut a = box [11, 12, 13];
- assert_eq!(a.tailn(0), &[11, 12, 13]);
- a = box [11, 12, 13];
- assert_eq!(a.tailn(2), &[13]);
- }
-
- #[test]
- #[should_fail]
- fn test_tailn_empty() {
- let a: ~[int] = box [];
- a.tailn(2);
- }
-
- #[test]
- fn test_init() {
- let mut a = box [11];
- assert_eq!(a.init(), &[]);
- a = box [11, 12];
- assert_eq!(a.init(), &[11]);
- }
-
- #[test]
- #[should_fail]
- fn test_init_empty() {
- let a: ~[int] = box [];
- a.init();
- }
-
- #[test]
- fn test_initn() {
- let mut a = box [11, 12, 13];
- assert_eq!(a.initn(0), &[11, 12, 13]);
- a = box [11, 12, 13];
- assert_eq!(a.initn(2), &[11]);
- }
-
- #[test]
- #[should_fail]
- fn test_initn_empty() {
- let a: ~[int] = box [];
- a.initn(2);
- }
-
- #[test]
- fn test_last() {
- let mut a = box [];
- assert_eq!(a.last(), None);
- a = box [11];
- assert_eq!(a.last().unwrap(), &11);
- a = box [11, 12];
- assert_eq!(a.last().unwrap(), &12);
- }
-
- #[test]
- fn test_slice() {
- // Test fixed length vector.
- let vec_fixed = [1, 2, 3, 4];
- let v_a = vec_fixed.slice(1u, vec_fixed.len()).to_owned();
- assert_eq!(v_a.len(), 3u);
- 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.slice(1u, 3u).to_owned();
- assert_eq!(v_b.len(), 2u);
- assert_eq!(v_b[0], 2);
- assert_eq!(v_b[1], 3);
-
- // Test `Box<[T]>`
- let vec_unique = box [1, 2, 3, 4, 5, 6];
- let v_d = vec_unique.slice(1u, 6u).to_owned();
- assert_eq!(v_d.len(), 5u);
- 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.slice_from(0), vec);
- assert_eq!(vec.slice_from(2), &[3, 4]);
- assert_eq!(vec.slice_from(4), &[]);
- }
-
- #[test]
- fn test_slice_to() {
- let vec = &[1, 2, 3, 4];
- assert_eq!(vec.slice_to(4), vec);
- assert_eq!(vec.slice_to(2), &[1, 2]);
- assert_eq!(vec.slice_to(0), &[]);
- }
-
-
- #[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, Some(1));
- assert_eq!(v, vec![5, 2, 3, 4]);
- e = v.swap_remove(3);
- assert_eq!(e, Some(4));
- assert_eq!(v, vec![5, 2, 3]);
-
- e = v.swap_remove(3);
- assert_eq!(e, None);
- assert_eq!(v, vec![5, 2, 3]);
- }
-
- #[test]
- fn test_swap_remove_noncopyable() {
- // Tests that we don't accidentally run destructors twice.
- let mut v = vec![::unstable::sync::Exclusive::new(()),
- ::unstable::sync::Exclusive::new(()),
- ::unstable::sync::Exclusive::new(())];
- 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(), 1u);
- assert_eq!(v.as_slice()[0], 1);
-
- // Test on-heap push().
- v.push(2);
- assert_eq!(v.len(), 2u);
- assert_eq!(v.as_slice()[0], 1);
- assert_eq!(v.as_slice()[1], 2);
- }
-
- #[test]
- fn test_grow() {
- // Test on-stack grow().
- let mut v = vec![];
- v.grow(2u, &1);
- {
- let v = v.as_slice();
- assert_eq!(v.len(), 2u);
- assert_eq!(v[0], 1);
- assert_eq!(v[1], 1);
- }
-
- // Test on-heap grow().
- v.grow(3u, &2);
- {
- let v = v.as_slice();
- assert_eq!(v.len(), 5u);
- assert_eq!(v[0], 1);
- assert_eq!(v[1], 1);
- assert_eq!(v[2], 2);
- assert_eq!(v[3], 2);
- assert_eq!(v[4], 2);
- }
- }
-
- #[test]
- fn test_grow_fn() {
- let mut v = vec![];
- v.grow_fn(3u, square);
- let v = v.as_slice();
- assert_eq!(v.len(), 3u);
- assert_eq!(v[0], 0u);
- assert_eq!(v[1], 1u);
- assert_eq!(v[2], 4u);
- }
-
- #[test]
- fn test_grow_set() {
- let mut v = vec![1, 2, 3];
- v.grow_set(4u, &4, 5);
- let v = v.as_slice();
- assert_eq!(v.len(), 5u);
- assert_eq!(v[0], 1);
- assert_eq!(v[1], 2);
- assert_eq!(v[2], 3);
- assert_eq!(v[3], 4);
- assert_eq!(v[4], 5);
- }
-
- #[test]
- fn test_truncate() {
- let mut v = vec![box 6,box 5,box 4];
- v.truncate(1);
- let v = v.as_slice();
- 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 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<uint>, b: Vec<uint>) {
- 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 1, box 1, box 2, box 3];
- v0.dedup();
- let mut v1 = vec![box 1, box 2, box 2, box 3];
- v1.dedup();
- let mut v2 = vec![box 1, box 2, box 3, box 3];
- v2.dedup();
- /*
- * If the boxed pointers were leaked or otherwise misused, valgrind
- * and/or rustrt should raise errors.
- */
- }
-
- #[test]
- fn test_dedup_shared() {
- let mut v0 = vec![box 1, box 1, box 2, box 3];
- v0.dedup();
- let mut v1 = vec![box 1, box 2, box 2, box 3];
- v1.dedup();
- let mut v2 = vec![box 1, box 2, box 3, box 3];
- v2.dedup();
- /*
- * If the pointers were leaked or otherwise misused, valgrind and/or
- * rustrt should raise errors.
- */
- }
-
- #[test]
- fn test_retain() {
- let mut v = vec![1, 2, 3, 4, 5];
- v.retain(is_odd);
- assert_eq!(v, vec![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]),
- _ => fail!(),
- }
- }
- }
-
- #[test]
- fn test_permutations() {
- {
- let v: [int, ..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.as_slice().to_owned()));
- 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.as_slice().to_owned()));
- 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(box [1,2,3]));
- assert_eq!(it.next(), Some(box [1,3,2]));
- assert_eq!(it.next(), Some(box [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(box [3,2,1]));
- assert_eq!(it.next(), Some(box [2,3,1]));
- assert_eq!(it.next(), Some(box [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 {
- 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[int] = &mut[1, 2, 3, 4, 5];
- assert!(v.prev_permutation() == false);
- assert!(v.next_permutation());
- assert_eq!(v, &mut[1, 2, 3, 5, 4]);
- assert!(v.prev_permutation());
- assert_eq!(v, &mut[1, 2, 3, 4, 5]);
- assert!(v.next_permutation());
- assert!(v.next_permutation());
- assert_eq!(v, &mut[1, 2, 4, 3, 5]);
- assert!(v.next_permutation());
- assert_eq!(v, &mut[1, 2, 4, 5, 3]);
-
- let v : &mut[int] = &mut[1, 0, 0, 0];
- assert!(v.next_permutation() == false);
- assert!(v.prev_permutation());
- assert_eq!(v, &mut[0, 1, 0, 0]);
- assert!(v.prev_permutation());
- assert_eq!(v, &mut[0, 0, 1, 0]);
- assert!(v.prev_permutation());
- assert_eq!(v, &mut[0, 0, 0, 1]);
- assert!(v.prev_permutation() == false);
- }
-
- #[test]
- fn test_lexicographic_permutations_empty_and_short() {
- let empty : &mut[int] = &mut[];
- assert!(empty.next_permutation() == false);
- assert_eq!(empty, &mut[]);
- assert!(empty.prev_permutation() == false);
- assert_eq!(empty, &mut[]);
-
- let one_elem : &mut[int] = &mut[4];
- assert!(one_elem.prev_permutation() == false);
- assert_eq!(one_elem, &mut[4]);
- assert!(one_elem.next_permutation() == false);
- assert_eq!(one_elem, &mut[4]);
-
- let two_elem : &mut[int] = &mut[1, 2];
- assert!(two_elem.prev_permutation() == false);
- assert_eq!(two_elem, &mut[1, 2]);
- assert!(two_elem.next_permutation());
- assert_eq!(two_elem, &mut[2, 1]);
- assert!(two_elem.next_permutation() == false);
- assert_eq!(two_elem, &mut[2, 1]);
- assert!(two_elem.prev_permutation());
- assert_eq!(two_elem, &mut[1, 2]);
- assert!(two_elem.prev_permutation() == false);
- assert_eq!(two_elem, &mut[1, 2]);
- }
-
- #[test]
- fn test_position_elem() {
- assert!([].position_elem(&1).is_none());
-
- let v1 = box [1, 2, 3, 3, 2, 5];
- assert_eq!(v1.position_elem(&1), Some(0u));
- assert_eq!(v1.position_elem(&2), Some(1u));
- assert_eq!(v1.position_elem(&5), Some(5u));
- assert!(v1.position_elem(&4).is_none());
- }
-
- #[test]
- fn test_bsearch_elem() {
- assert_eq!([1,2,3,4,5].bsearch_elem(&5), Some(4));
- assert_eq!([1,2,3,4,5].bsearch_elem(&4), Some(3));
- assert_eq!([1,2,3,4,5].bsearch_elem(&3), Some(2));
- assert_eq!([1,2,3,4,5].bsearch_elem(&2), Some(1));
- assert_eq!([1,2,3,4,5].bsearch_elem(&1), Some(0));
-
- assert_eq!([2,4,6,8,10].bsearch_elem(&1), None);
- assert_eq!([2,4,6,8,10].bsearch_elem(&5), None);
- assert_eq!([2,4,6,8,10].bsearch_elem(&4), Some(1));
- assert_eq!([2,4,6,8,10].bsearch_elem(&10), Some(4));
-
- assert_eq!([2,4,6,8].bsearch_elem(&1), None);
- assert_eq!([2,4,6,8].bsearch_elem(&5), None);
- assert_eq!([2,4,6,8].bsearch_elem(&4), Some(1));
- assert_eq!([2,4,6,8].bsearch_elem(&8), Some(3));
-
- assert_eq!([2,4,6].bsearch_elem(&1), None);
- assert_eq!([2,4,6].bsearch_elem(&5), None);
- assert_eq!([2,4,6].bsearch_elem(&4), Some(1));
- assert_eq!([2,4,6].bsearch_elem(&6), Some(2));
-
- assert_eq!([2,4].bsearch_elem(&1), None);
- assert_eq!([2,4].bsearch_elem(&5), None);
- assert_eq!([2,4].bsearch_elem(&2), Some(0));
- assert_eq!([2,4].bsearch_elem(&4), Some(1));
-
- assert_eq!([2].bsearch_elem(&1), None);
- assert_eq!([2].bsearch_elem(&5), None);
- assert_eq!([2].bsearch_elem(&2), Some(0));
-
- assert_eq!([].bsearch_elem(&1), None);
- assert_eq!([].bsearch_elem(&5), None);
-
- assert!([1,1,1,1,1].bsearch_elem(&1) != None);
- assert!([1,1,1,1,2].bsearch_elem(&1) != None);
- assert!([1,1,1,2,2].bsearch_elem(&1) != None);
- assert!([1,1,2,2,2].bsearch_elem(&1) != None);
- assert_eq!([1,2,2,2,2].bsearch_elem(&1), Some(0));
-
- assert_eq!([1,2,3,4,5].bsearch_elem(&6), None);
- assert_eq!([1,2,3,4,5].bsearch_elem(&0), None);
- }
-
- #[test]
- fn test_reverse() {
- let mut v: ~[int] = box [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: ~[int] = box [];
- v3.reverse();
- assert!(v3.is_empty());
- }
-
- #[test]
- fn test_sort() {
- use realstd::slice::Vector;
- use realstd::clone::Clone;
- for len in range(4u, 25) {
- for _ in range(0, 100) {
- let mut v = task_rng().gen_iter::<uint>().take(len)
- .collect::<Vec<uint>>();
- let mut v1 = v.clone();
-
- v.as_mut_slice().sort();
- assert!(v.as_slice().windows(2).all(|w| w[0] <= w[1]));
-
- v1.as_mut_slice().sort_by(|a, b| a.cmp(b));
- assert!(v1.as_slice().windows(2).all(|w| w[0] <= w[1]));
-
- v1.as_mut_slice().sort_by(|a, b| b.cmp(a));
- assert!(v1.as_slice().windows(2).all(|w| w[0] >= w[1]));
- }
- }
-
- // shouldn't fail/crash
- let mut v: [uint, .. 0] = [];
- v.sort();
-
- let mut v = [0xDEADBEEFu];
- v.sort();
- assert!(v == [0xDEADBEEF]);
- }
-
- #[test]
- fn test_sort_stability() {
- for len in range(4, 25) {
- for _ in range(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 = range(0, len).map(|_| {
- let n = task_rng().gen::<uint>() % 10;
- counts[n] += 1;
- (n, counts[n])
- }).collect::<Vec<(uint, int)>>();
-
- // 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.as_slice().windows(2).all(|w| w[0] <= w[1]));
- }
- }
- }
-
- #[test]
- fn test_partition() {
- assert_eq!((box []).partition(|x: &int| *x < 3), (vec![], vec![]));
- assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
- assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
- assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
- }
-
- #[test]
- fn test_partitioned() {
- assert_eq!(([]).partitioned(|x: &int| *x < 3), (vec![], vec![]));
- assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
- assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
- assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
- }
-
- #[test]
- fn test_concat() {
- let v: [~[int], ..0] = [];
- assert_eq!(v.concat_vec(), vec![]);
- assert_eq!([box [1], box [2,3]].concat_vec(), vec![1, 2, 3]);
-
- assert_eq!([&[1], &[2,3]].concat_vec(), vec![1, 2, 3]);
- }
-
- #[test]
- fn test_connect() {
- let v: [~[int], ..0] = [];
- assert_eq!(v.connect_vec(&0), vec![]);
- assert_eq!([box [1], box [2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
- assert_eq!([box [1], box [2], box [3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
-
- assert_eq!([&[1], &[2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
- assert_eq!([&[1], &[2], &[3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
- }
-
- #[test]
- fn test_shift() {
- let mut x = vec![1, 2, 3];
- assert_eq!(x.shift(), Some(1));
- assert_eq!(&x, &vec![2, 3]);
- assert_eq!(x.shift(), Some(2));
- assert_eq!(x.shift(), Some(3));
- assert_eq!(x.shift(), None);
- assert_eq!(x.len(), 0);
- }
-
- #[test]
- fn test_unshift() {
- let mut x = vec![1, 2, 3];
- x.unshift(0);
- assert_eq!(x, vec![0, 1, 2, 3]);
- }
-
- #[test]
- fn test_insert() {
- let mut a = vec![1, 2, 4];
- a.insert(2, 3);
- assert_eq!(a, vec![1, 2, 3, 4]);
-
- let mut a = vec![1, 2, 3];
- a.insert(0, 0);
- assert_eq!(a, vec![0, 1, 2, 3]);
-
- let mut a = vec![1, 2, 3];
- a.insert(3, 4);
- assert_eq!(a, vec![1, 2, 3, 4]);
-
- let mut a = vec![];
- a.insert(0, 1);
- assert_eq!(a, vec![1]);
- }
-
- #[test]
- #[should_fail]
- 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), Some(3));
- assert_eq!(a, vec![1,2,4]);
-
- assert_eq!(a.remove(2), Some(4));
- assert_eq!(a, vec![1,2]);
-
- assert_eq!(a.remove(2), None);
- assert_eq!(a, vec![1,2]);
-
- assert_eq!(a.remove(0), Some(1));
- assert_eq!(a, vec![2]);
-
- assert_eq!(a.remove(0), Some(2));
- assert_eq!(a, vec![]);
-
- assert_eq!(a.remove(0), None);
- assert_eq!(a.remove(10), None);
- }
-
- #[test]
- fn test_capacity() {
- let mut v = vec![0u64];
- v.reserve_exact(10u);
- assert_eq!(v.capacity(), 10u);
- let mut v = vec![0u32];
- v.reserve_exact(10u);
- assert_eq!(v.capacity(), 10u);
- }
-
- #[test]
- fn test_slice_2() {
- let v = vec![1, 2, 3, 4, 5];
- let v = v.slice(1u, 3u);
- assert_eq!(v.len(), 2u);
- assert_eq!(v[0], 2);
- assert_eq!(v[1], 3);
- }
-
-
- #[test]
- #[should_fail]
- fn test_from_fn_fail() {
- Vec::from_fn(100, |v| {
- if v == 50 { fail!() }
- box 0
- });
- }
-
- #[test]
- #[should_fail]
- fn test_from_elem_fail() {
- use cell::Cell;
- use rc::Rc;
-
- struct S {
- f: Cell<int>,
- boxes: (Box<int>, Rc<int>)
- }
-
- impl Clone for S {
- fn clone(&self) -> S {
- self.f.set(self.f.get() + 1);
- if self.f.get() == 10 { fail!() }
- S { f: self.f, boxes: self.boxes.clone() }
- }
- }
-
- let s = S { f: Cell::new(0), boxes: (box 0, Rc::new(0)) };
- let _ = Vec::from_elem(100, s);
- }
-
- #[test]
- #[should_fail]
- fn test_grow_fn_fail() {
- use rc::Rc;
- let mut v = vec![];
- v.grow_fn(100, |i| {
- if i == 50 {
- fail!()
- }
- (box 0, Rc::new(0))
- })
- }
-
- #[test]
- #[should_fail]
- fn test_permute_fail() {
- use rc::Rc;
- let v = [(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 {
- fail!()
- }
- i += 1;
- }
- }
-
- #[test]
- #[should_fail]
- fn test_copy_memory_oob() {
- unsafe {
- let mut a = [1, 2, 3, 4];
- let b = [1, 2, 3, 4, 5];
- a.copy_memory(b);
- }
- }
-
- #[test]
- fn test_total_ord() {
- [1, 2, 3, 4].cmp(& &[1, 2, 3]) == Greater;
- [1, 2, 3].cmp(& &[1, 2, 3, 4]) == Less;
- [1, 2, 3, 4].cmp(& &[1, 2, 3, 4]) == Equal;
- [1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less;
- [2, 2].cmp(& &[1, 2, 3, 4]) == Greater;
- }
-
- #[test]
- fn test_iterator() {
- use iter::*;
- 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() {
- use iter::*;
- 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() {
- use iter::*;
- let mut xs = [1, 2, 5, 10, 11];
- assert_eq!(xs.iter().size_hint(), (5, Some(5)));
- assert_eq!(xs.mut_iter().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() {
- use iter::*;
- let mut xs = [1, 2, 3, 4, 5];
- for x in xs.mut_iter() {
- *x += 1;
- }
- assert!(xs == [2, 3, 4, 5, 6])
- }
-
- #[test]
- fn test_rev_iterator() {
- use iter::*;
-
- 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() {
- use iter::*;
- let mut xs = [1u, 2, 3, 4, 5];
- for (i,x) in xs.mut_iter().rev().enumerate() {
- *x += i;
- }
- assert!(xs == [5, 5, 5, 5, 5])
- }
-
- #[test]
- fn test_move_iterator() {
- use iter::*;
- let xs = box [1u,2,3,4,5];
- assert_eq!(xs.move_iter().fold(0, |a: uint, b: uint| 10*a + b), 12345);
- }
-
- #[test]
- fn test_move_rev_iterator() {
- use iter::*;
- let xs = box [1u,2,3,4,5];
- assert_eq!(xs.move_iter().rev().fold(0, |a: uint, b: uint| 10*a + b), 54321);
- }
-
- #[test]
- fn test_splitator() {
- let xs = &[1i,2,3,4,5];
-
- assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
- &[&[1], &[3], &[5]]);
- assert_eq!(xs.split(|x| *x == 1).collect::<Vec<&[int]>>().as_slice(),
- &[&[], &[2,3,4,5]]);
- assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[int]>>().as_slice(),
- &[&[1,2,3,4], &[]]);
- assert_eq!(xs.split(|x| *x == 10).collect::<Vec<&[int]>>().as_slice(),
- &[&[1,2,3,4,5]]);
- assert_eq!(xs.split(|_| true).collect::<Vec<&[int]>>().as_slice(),
- &[&[], &[], &[], &[], &[], &[]]);
-
- let xs: &[int] = &[];
- assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
- }
-
- #[test]
- fn test_splitnator() {
- let xs = &[1i,2,3,4,5];
-
- assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
- &[&[1,2,3,4,5]]);
- assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
- &[&[1], &[3,4,5]]);
- assert_eq!(xs.splitn(3, |_| true).collect::<Vec<&[int]>>().as_slice(),
- &[&[], &[], &[], &[4,5]]);
-
- let xs: &[int] = &[];
- assert_eq!(xs.splitn(1, |x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
- }
-
- #[test]
- fn test_rsplitator() {
- let xs = &[1i,2,3,4,5];
-
- assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<&[int]>>().as_slice(),
- &[&[5], &[3], &[1]]);
- assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<&[int]>>().as_slice(),
- &[&[2,3,4,5], &[]]);
- assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[int]>>().as_slice(),
- &[&[], &[1,2,3,4]]);
- assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<&[int]>>().as_slice(),
- &[&[1,2,3,4,5]]);
-
- let xs: &[int] = &[];
- assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[int]>>().as_slice(), &[&[]]);
- }
-
- #[test]
- fn test_rsplitnator() {
- let xs = &[1,2,3,4,5];
-
- assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
- &[&[1,2,3,4,5]]);
- assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
- &[&[5], &[1,2,3]]);
- assert_eq!(xs.rsplitn(3, |_| true).collect::<Vec<&[int]>>().as_slice(),
- &[&[], &[], &[], &[1,2]]);
-
- let xs: &[int] = &[];
- assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
- }
-
- #[test]
- fn test_windowsator() {
- let v = &[1i,2,3,4];
-
- assert_eq!(v.windows(2).collect::<Vec<&[int]>>().as_slice(), &[&[1,2], &[2,3], &[3,4]]);
- assert_eq!(v.windows(3).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3], &[2,3,4]]);
- assert!(v.windows(6).next().is_none());
- }
-
- #[test]
- #[should_fail]
- fn test_windowsator_0() {
- let v = &[1i,2,3,4];
- let _it = v.windows(0);
- }
-
- #[test]
- fn test_chunksator() {
- let v = &[1i,2,3,4,5];
-
- assert_eq!(v.chunks(2).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2], &[3,4], &[5]]);
- assert_eq!(v.chunks(3).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3], &[4,5]]);
- assert_eq!(v.chunks(6).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3,4,5]]);
-
- assert_eq!(v.chunks(2).rev().collect::<Vec<&[int]>>().as_slice(), &[&[5i], &[3,4], &[1,2]]);
- let mut it = v.chunks(2);
- assert_eq!(it.indexable(), 3);
- assert_eq!(it.idx(0).unwrap(), &[1,2]);
- assert_eq!(it.idx(1).unwrap(), &[3,4]);
- assert_eq!(it.idx(2).unwrap(), &[5]);
- assert_eq!(it.idx(3), None);
- }
-
- #[test]
- #[should_fail]
- fn test_chunksator_0() {
- let v = &[1i,2,3,4];
- let _it = v.chunks(0);
- }
-
- #[test]
- fn test_move_from() {
- let mut a = [1,2,3,4,5];
- let b = box [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 = box [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 = box [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 = box [5,6,7,8,9,0];
- assert_eq!(a.mut_slice(2,4).move_from(b,1,6), 2);
- assert!(a == [1,2,6,7,5]);
- }
-
- #[test]
- fn test_copy_from() {
- let mut a = [1,2,3,4,5];
- let b = [6,7,8];
- assert_eq!(a.copy_from(b), 3);
- assert!(a == [6,7,8,4,5]);
- let mut c = [7,2,8,1];
- let d = [3,1,4,1,5,9];
- assert_eq!(c.copy_from(d), 4);
- assert!(c == [3,1,4,1]);
- }
-
- #[test]
- fn test_reverse_part() {
- let mut values = [1,2,3,4,5];
- values.mut_slice(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.as_slice()), x_str);
- })
- )
- let empty: ~[int] = box [];
- test_show_vec!(empty, "[]".to_string());
- test_show_vec!(box [1], "[1]".to_string());
- test_show_vec!(box [1, 2, 3], "[1, 2, 3]".to_string());
- test_show_vec!(box [box [], box [1u], box [1u, 1u]],
- "[[], [1], [1, 1]]".to_string());
-
- let empty_mut: &mut [int] = &mut[];
- test_show_vec!(empty_mut, "[]".to_string());
- test_show_vec!(&mut[1], "[1]".to_string());
- test_show_vec!(&mut[1, 2, 3], "[1, 2, 3]".to_string());
- test_show_vec!(&mut[&mut[], &mut[1u], &mut[1u, 1u]],
- "[[], [1], [1, 1]]".to_string());
- }
-
- #[test]
- fn test_vec_default() {
- use default::Default;
- macro_rules! t (
- ($ty:ty) => {{
- let v: $ty = Default::default();
- assert!(v.is_empty());
- }}
- );
-
- t!(&[int]);
- t!(~[int]);
- t!(Vec<int>);
- }
-
- #[test]
- fn test_bytes_set_memory() {
- use slice::bytes::MutableByteVector;
- let mut values = [1u8,2,3,4,5];
- values.mut_slice(0,5).set_memory(0xAB);
- assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]);
- values.mut_slice(2,4).set_memory(0xFF);
- assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]);
- }
-
- #[test]
- #[should_fail]
- fn test_overflow_does_not_cause_segfault() {
- let mut v = vec![];
- v.reserve_exact(-1);
- v.push(1);
- v.push(2);
- }
-
- #[test]
- #[should_fail]
- fn test_overflow_does_not_cause_segfault_managed() {
- use rc::Rc;
- 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.mut_split_at(2);
- assert!(left.slice(0, left.len()) == [1, 2]);
- for p in left.mut_iter() {
- *p += 1;
- }
-
- assert!(right.slice(0, right.len()) == [3, 4, 5]);
- for p in right.mut_iter() {
- *p += 2;
- }
- }
-
- assert!(values == [2, 3, 5, 6, 7]);
- }
-
- #[deriving(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.iter() {
- assert!(*f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 3);
-
- for f in v.slice(1, 3).iter() {
- assert!(*f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 5);
-
- for f in v.mut_iter() {
- assert!(*f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 8);
-
- for f in v.move_iter() {
- assert!(f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 11);
-
- let xs: [Foo, ..3] = [Foo, Foo, Foo];
- cnt = 0;
- for f in xs.iter() {
- 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 range(4, 100) {
- xs.push(i)
- }
- assert_eq!(xs.capacity(), 128);
- xs.shrink_to_fit();
- assert_eq!(xs.capacity(), 100);
- assert_eq!(xs, range(0, 100).collect::<Vec<_>>());
- }
-
- #[test]
- fn test_starts_with() {
- assert!(bytes!("foobar").starts_with(bytes!("foo")));
- assert!(!bytes!("foobar").starts_with(bytes!("oob")));
- assert!(!bytes!("foobar").starts_with(bytes!("bar")));
- assert!(!bytes!("foo").starts_with(bytes!("foobar")));
- assert!(!bytes!("bar").starts_with(bytes!("foobar")));
- assert!(bytes!("foobar").starts_with(bytes!("foobar")));
- let empty: &[u8] = [];
- assert!(empty.starts_with(empty));
- assert!(!empty.starts_with(bytes!("foo")));
- assert!(bytes!("foobar").starts_with(empty));
- }
-
- #[test]
- fn test_ends_with() {
- assert!(bytes!("foobar").ends_with(bytes!("bar")));
- assert!(!bytes!("foobar").ends_with(bytes!("oba")));
- assert!(!bytes!("foobar").ends_with(bytes!("foo")));
- assert!(!bytes!("foo").ends_with(bytes!("foobar")));
- assert!(!bytes!("bar").ends_with(bytes!("foobar")));
- assert!(bytes!("foobar").ends_with(bytes!("foobar")));
- let empty: &[u8] = [];
- assert!(empty.ends_with(empty));
- assert!(!empty.ends_with(bytes!("foo")));
- assert!(bytes!("foobar").ends_with(empty));
- }
-
- #[test]
- fn test_shift_ref() {
- let mut x: &[int] = [1, 2, 3, 4, 5];
- let h = x.shift_ref();
- assert_eq!(*h.unwrap(), 1);
- assert_eq!(x.len(), 4);
- assert_eq!(x[0], 2);
- assert_eq!(x[3], 5);
-
- let mut y: &[int] = [];
- assert_eq!(y.shift_ref(), None);
- }
-
- #[test]
- fn test_pop_ref() {
- let mut x: &[int] = [1, 2, 3, 4, 5];
- let h = x.pop_ref();
- assert_eq!(*h.unwrap(), 5);
- assert_eq!(x.len(), 4);
- assert_eq!(x[0], 1);
- assert_eq!(x[3], 4);
-
- let mut y: &[int] = [];
- assert!(y.pop_ref().is_none());
- }
-
- #[test]
- fn test_mut_splitator() {
- let mut xs = [0,1,0,2,3,0,0,4,5,0];
- assert_eq!(xs.mut_split(|x| *x == 0).len(), 6);
- for slice in xs.mut_split(|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.mut_split(|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.mut_split(|x| *x == 0).rev().take(4) {
- slice.reverse();
- }
- assert!(xs == [1,2,0,4,3,0,0,6,5,0]);
- }
-
- #[test]
- fn test_mut_chunks() {
- let mut v = [0u8, 1, 2, 3, 4, 5, 6];
- for (i, chunk) in v.mut_chunks(3).enumerate() {
- for x in chunk.mut_iter() {
- *x = i as u8;
- }
- }
- let result = [0u8, 0, 0, 1, 1, 1, 2];
- assert!(v == result);
- }
-
- #[test]
- fn test_mut_chunks_rev() {
- let mut v = [0u8, 1, 2, 3, 4, 5, 6];
- for (i, chunk) in v.mut_chunks(3).rev().enumerate() {
- for x in chunk.mut_iter() {
- *x = i as u8;
- }
- }
- let result = [2u8, 2, 2, 1, 1, 1, 0];
- assert!(v == result);
- }
-
- #[test]
- #[should_fail]
- fn test_mut_chunks_0() {
- let mut v = [1, 2, 3, 4];
- let _it = v.mut_chunks(0);
- }
-
- #[test]
- fn test_mut_shift_ref() {
- let mut x: &mut [int] = [1, 2, 3, 4, 5];
- let h = x.mut_shift_ref();
- assert_eq!(*h.unwrap(), 1);
- assert_eq!(x.len(), 4);
- assert_eq!(x[0], 2);
- assert_eq!(x[3], 5);
-
- let mut y: &mut [int] = [];
- assert!(y.mut_shift_ref().is_none());
- }
-
- #[test]
- fn test_mut_pop_ref() {
- let mut x: &mut [int] = [1, 2, 3, 4, 5];
- let h = x.mut_pop_ref();
- assert_eq!(*h.unwrap(), 5);
- assert_eq!(x.len(), 4);
- assert_eq!(x[0], 1);
- assert_eq!(x[3], 4);
-
- let mut y: &mut [int] = [];
- assert!(y.mut_pop_ref().is_none());
- }
-
- #[test]
- fn test_mut_last() {
- let mut x = [1, 2, 3, 4, 5];
- let h = x.mut_last();
- assert_eq!(*h.unwrap(), 5);
-
- let y: &mut [int] = [];
- assert!(y.mut_last().is_none());
- }
-}
-
-#[cfg(test)]
-mod bench {
- extern crate test;
- use self::test::Bencher;
- use mem;
- use prelude::*;
- use ptr;
- use rand::{weak_rng, Rng};
-
- #[bench]
- fn iterator(b: &mut Bencher) {
- // peculiar numbers to stop LLVM from optimising the summation
- // out.
- let v = Vec::from_fn(100, |i| i ^ (i << 1) ^ (i >> 1));
-
- b.iter(|| {
- let mut sum = 0;
- for x in v.iter() {
- sum += *x;
- }
- // sum == 11806, to stop dead code elimination.
- if sum == 0 {fail!()}
- })
- }
-
- #[bench]
- fn mut_iterator(b: &mut Bencher) {
- let mut v = Vec::from_elem(100, 0);
-
- b.iter(|| {
- let mut i = 0;
- for x in v.mut_iter() {
- *x = i;
- i += 1;
- }
- })
- }
-
- #[bench]
- fn concat(b: &mut Bencher) {
- let xss: Vec<Vec<uint>> = Vec::from_fn(100, |i| range(0, i).collect());
- b.iter(|| {
- xss.as_slice().concat_vec()
- });
- }
-
- #[bench]
- fn connect(b: &mut Bencher) {
- let xss: Vec<Vec<uint>> = Vec::from_fn(100, |i| range(0, i).collect());
- b.iter(|| {
- xss.as_slice().connect_vec(&0)
- });
- }
-
- #[bench]
- fn push(b: &mut Bencher) {
- let mut vec: Vec<uint> = vec![];
- b.iter(|| {
- vec.push(0);
- &vec
- })
- }
-
- #[bench]
- fn starts_with_same_vector(b: &mut Bencher) {
- let vec: Vec<uint> = Vec::from_fn(100, |i| i);
- b.iter(|| {
- vec.as_slice().starts_with(vec.as_slice())
- })
- }
-
- #[bench]
- fn starts_with_single_element(b: &mut Bencher) {
- let vec: Vec<uint> = vec![0];
- b.iter(|| {
- vec.as_slice().starts_with(vec.as_slice())
- })
- }
-
- #[bench]
- fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
- let vec: Vec<uint> = Vec::from_fn(100, |i| i);
- let mut match_vec: Vec<uint> = Vec::from_fn(99, |i| i);
- match_vec.push(0);
- b.iter(|| {
- vec.as_slice().starts_with(match_vec.as_slice())
- })
- }
-
- #[bench]
- fn ends_with_same_vector(b: &mut Bencher) {
- let vec: Vec<uint> = Vec::from_fn(100, |i| i);
- b.iter(|| {
- vec.as_slice().ends_with(vec.as_slice())
- })
- }
-
- #[bench]
- fn ends_with_single_element(b: &mut Bencher) {
- let vec: Vec<uint> = vec![0];
- b.iter(|| {
- vec.as_slice().ends_with(vec.as_slice())
- })
- }
-
- #[bench]
- fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
- let vec: Vec<uint> = Vec::from_fn(100, |i| i);
- let mut match_vec: Vec<uint> = Vec::from_fn(100, |i| i);
- match_vec.as_mut_slice()[0] = 200;
- b.iter(|| {
- vec.as_slice().starts_with(match_vec.as_slice())
- })
- }
-
- #[bench]
- fn contains_last_element(b: &mut Bencher) {
- let vec: Vec<uint> = Vec::from_fn(100, |i| i);
- b.iter(|| {
- vec.contains(&99u)
- })
- }
-
- #[bench]
- fn zero_1kb_from_elem(b: &mut Bencher) {
- b.iter(|| {
- Vec::from_elem(1024, 0u8)
- });
- }
-
- #[bench]
- fn zero_1kb_set_memory(b: &mut Bencher) {
- b.iter(|| {
- let mut v: Vec<uint> = Vec::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_fixed_repeat(b: &mut Bencher) {
- b.iter(|| {
- box [0u8, ..1024]
- });
- }
-
- #[bench]
- fn zero_1kb_loop_set(b: &mut Bencher) {
- b.iter(|| {
- let mut v: Vec<uint> = Vec::with_capacity(1024);
- unsafe {
- v.set_len(1024);
- }
- for i in range(0u, 1024) {
- *v.get_mut(i) = 0;
- }
- });
- }
-
- #[bench]
- fn zero_1kb_mut_iter(b: &mut Bencher) {
- b.iter(|| {
- let mut v = Vec::with_capacity(1024);
- unsafe {
- v.set_len(1024);
- }
- for x in v.mut_iter() {
- *x = 0;
- }
- v
- });
- }
-
- #[bench]
- fn random_inserts(b: &mut Bencher) {
- let mut rng = weak_rng();
- b.iter(|| {
- let mut v = Vec::from_elem(30, (0u, 0u));
- for _ in range(0, 100) {
- let l = v.len();
- v.insert(rng.gen::<uint>() % (l + 1),
- (1, 1));
- }
- })
- }
- #[bench]
- fn random_removes(b: &mut Bencher) {
- let mut rng = weak_rng();
- b.iter(|| {
- let mut v = Vec::from_elem(130, (0u, 0u));
- for _ in range(0, 100) {
- let l = v.len();
- v.remove(rng.gen::<uint>() % l);
- }
- })
- }
-
- #[bench]
- fn sort_random_small(b: &mut Bencher) {
- let mut rng = weak_rng();
- b.iter(|| {
- let mut v = rng.gen_iter::<u64>().take(5).collect::<Vec<u64>>();
- v.as_mut_slice().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 = rng.gen_iter::<u64>().take(100).collect::<Vec<u64>>();
- v.as_mut_slice().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 = rng.gen_iter::<u64>().take(10000).collect::<Vec<u64>>();
- v.as_mut_slice().sort();
- });
- b.bytes = 10000 * mem::size_of::<u64>() as u64;
- }
-
- #[bench]
- fn sort_sorted(b: &mut Bencher) {
- let mut v = Vec::from_fn(10000, |i| i);
- b.iter(|| {
- v.sort();
- });
- b.bytes = (v.len() * mem::size_of_val(v.get(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::from_fn(10000u, |i| (i, i, i, i));
- b.iter(|| {
- v.sort();
- });
- b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64;
- }
-}
+++ /dev/null
-// 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.
-
-/*!
-
-Unicode string manipulation (`str` type)
-
-# Basic Usage
-
-Rust's string type is one of the core primitive types of the language. While
-represented by the name `str`, the name `str` is not actually a valid type in
-Rust. Each string must also be decorated with a pointer. `String` is used
-for an owned string, so there is only one commonly-used `str` type in Rust:
-`&str`.
-
-`&str` is the borrowed string type. This type of string can only be created
-from other strings, unless it is a static string (see below). As the word
-"borrowed" implies, this type of string is owned elsewhere, and this string
-cannot be moved out of.
-
-As an example, here's some code that uses a string.
-
-```rust
-fn main() {
- let borrowed_string = "This string is borrowed with the 'static lifetime";
-}
-```
-
-From the example above, you can see that Rust's string literals have the
-`'static` lifetime. This is akin to C's concept of a static string.
-
-String literals are allocated statically in the rodata of the
-executable/library. The string then has the type `&'static str` meaning that
-the string is valid for the `'static` lifetime, otherwise known as the
-lifetime of the entire program. As can be inferred from the type, these static
-strings are not mutable.
-
-# Mutability
-
-Many languages have immutable strings by default, and Rust has a particular
-flavor on this idea. As with the rest of Rust types, strings are immutable by
-default. If a string is declared as `mut`, however, it may be mutated. This
-works the same way as the rest of Rust's type system in the sense that if
-there's a mutable reference to a string, there may only be one mutable reference
-to that string. With these guarantees, strings can easily transition between
-being mutable/immutable with the same benefits of having mutable strings in
-other languages.
-
-# Representation
-
-Rust's string type, `str`, is a sequence of unicode codepoints encoded as a
-stream of UTF-8 bytes. All safely-created strings are guaranteed to be validly
-encoded UTF-8 sequences. Additionally, strings are not null-terminated
-and can contain null codepoints.
-
-The actual representation of strings have direct mappings to vectors: `&str`
-is the same as `&[u8]`.
-
-*/
-
-#![doc(primitive = "str")]
-
-use char::Char;
-use char;
-use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Equiv, Ordering};
-use container::Container;
-use default::Default;
-use fmt;
-use io::Writer;
-use iter::{Iterator, range, AdditiveIterator};
-use mem::transmute;
-use mem;
-use option::{None, Option, Some};
-use result::Result;
-use slice::Vector;
-use slice::{ImmutableVector, MutableVector};
-use string::String;
-use vec::Vec;
-
-pub use core::str::{from_utf8, CharEq, Chars, CharOffsets};
-pub use core::str::{Bytes, CharSplits};
-pub use core::str::{CharSplitsN, Words, AnyLines, MatchIndices, StrSplits};
-pub use core::str::{eq_slice, is_utf8, is_utf16, Utf16Items};
-pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items};
-pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange};
-pub use core::str::{Str, StrSlice};
-
-/*
-Section: Creating a string
-*/
-
-/// Consumes a vector of bytes to create a new utf-8 string.
-///
-/// Returns `Err` with the original vector if the vector contains invalid
-/// UTF-8.
-pub fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>> {
- String::from_utf8(vv)
-}
-
-/// Convert a byte to a UTF-8 string
-///
-/// # Failure
-///
-/// Fails if invalid UTF-8
-pub fn from_byte(b: u8) -> String {
- assert!(b < 128u8);
- String::from_char(1, b as char)
-}
-
-/// Convert a char to a string
-pub fn from_char(ch: char) -> String {
- let mut buf = String::new();
- buf.push_char(ch);
- buf
-}
-
-/// Convert a vector of chars to a string
-pub fn from_chars(chs: &[char]) -> String {
- chs.iter().map(|c| *c).collect()
-}
-
-/// Methods for vectors of strings
-pub trait StrVector {
- /// Concatenate a vector of strings.
- fn concat(&self) -> String;
-
- /// Concatenate a vector of strings, placing a given separator between each.
- fn connect(&self, sep: &str) -> String;
-}
-
-impl<'a, S: Str> StrVector for &'a [S] {
- fn concat(&self) -> String {
- if self.is_empty() {
- return String::new();
- }
-
- // `len` calculation may overflow but push_str but will check boundaries
- let len = self.iter().map(|s| s.as_slice().len()).sum();
-
- let mut result = String::with_capacity(len);
-
- for s in self.iter() {
- result.push_str(s.as_slice())
- }
-
- result
- }
-
- fn connect(&self, sep: &str) -> String {
- if self.is_empty() {
- return String::new();
- }
-
- // concat is faster
- if sep.is_empty() {
- return self.concat();
- }
-
- // this is wrong without the guarantee that `self` is non-empty
- // `len` calculation may overflow but push_str but will check boundaries
- let len = sep.len() * (self.len() - 1)
- + self.iter().map(|s| s.as_slice().len()).sum();
- let mut result = String::with_capacity(len);
- let mut first = true;
-
- for s in self.iter() {
- if first {
- first = false;
- } else {
- result.push_str(sep);
- }
- result.push_str(s.as_slice());
- }
- result
- }
-}
-
-impl<'a, S: Str> StrVector for Vec<S> {
- #[inline]
- fn concat(&self) -> String {
- self.as_slice().concat()
- }
-
- #[inline]
- fn connect(&self, sep: &str) -> String {
- self.as_slice().connect(sep)
- }
-}
-
-/*
-Section: Iterators
-*/
-
-// Helper functions used for Unicode normalization
-fn canonical_sort(comb: &mut [(char, u8)]) {
- use iter::range;
- use tuple::Tuple2;
-
- let len = comb.len();
- for i in range(0, len) {
- let mut swapped = false;
- for j in range(1, len-i) {
- let class_a = *comb[j-1].ref1();
- let class_b = *comb[j].ref1();
- if class_a != 0 && class_b != 0 && class_a > class_b {
- comb.swap(j-1, j);
- swapped = true;
- }
- }
- if !swapped { break; }
- }
-}
-
-#[deriving(Clone)]
-enum DecompositionType {
- Canonical,
- Compatible
-}
-
-/// External iterator for a string's decomposition's characters.
-/// Use with the `std::iter` module.
-#[deriving(Clone)]
-pub struct Decompositions<'a> {
- kind: DecompositionType,
- iter: Chars<'a>,
- buffer: Vec<(char, u8)>,
- sorted: bool
-}
-
-impl<'a> Iterator<char> for Decompositions<'a> {
- #[inline]
- fn next(&mut self) -> Option<char> {
- use unicode::normalization::canonical_combining_class;
-
- match self.buffer.as_slice().head() {
- Some(&(c, 0)) => {
- self.sorted = false;
- self.buffer.shift();
- return Some(c);
- }
- Some(&(c, _)) if self.sorted => {
- self.buffer.shift();
- return Some(c);
- }
- _ => self.sorted = false
- }
-
- let decomposer = match self.kind {
- Canonical => char::decompose_canonical,
- Compatible => char::decompose_compatible
- };
-
- if !self.sorted {
- for ch in self.iter {
- let buffer = &mut self.buffer;
- let sorted = &mut self.sorted;
- decomposer(ch, |d| {
- let class = canonical_combining_class(d);
- if class == 0 && !*sorted {
- canonical_sort(buffer.as_mut_slice());
- *sorted = true;
- }
- buffer.push((d, class));
- });
- if *sorted { break }
- }
- }
-
- if !self.sorted {
- canonical_sort(self.buffer.as_mut_slice());
- self.sorted = true;
- }
-
- match self.buffer.shift() {
- Some((c, 0)) => {
- self.sorted = false;
- Some(c)
- }
- Some((c, _)) => Some(c),
- None => None
- }
- }
-
- fn size_hint(&self) -> (uint, Option<uint>) {
- let (lower, _) = self.iter.size_hint();
- (lower, None)
- }
-}
-
-/// Replace all occurrences of one string with another
-///
-/// # Arguments
-///
-/// * s - The string containing substrings to replace
-/// * from - The string to replace
-/// * to - The replacement string
-///
-/// # Return value
-///
-/// The original string with all occurrences of `from` replaced with `to`
-pub fn replace(s: &str, from: &str, to: &str) -> String {
- let mut result = String::new();
- let mut last_end = 0;
- for (start, end) in s.match_indices(from) {
- result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
- result.push_str(to);
- last_end = end;
- }
- result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
- result
-}
-
-/*
-Section: Misc
-*/
-
-/// Decode a UTF-16 encoded vector `v` into a string, returning `None`
-/// if `v` contains any invalid data.
-///
-/// # Example
-///
-/// ```rust
-/// use std::str;
-///
-/// // 𝄞music
-/// let mut v = [0xD834, 0xDD1E, 0x006d, 0x0075,
-/// 0x0073, 0x0069, 0x0063];
-/// assert_eq!(str::from_utf16(v), Some("𝄞music".to_string()));
-///
-/// // 𝄞mu<invalid>ic
-/// v[4] = 0xD800;
-/// assert_eq!(str::from_utf16(v), None);
-/// ```
-pub fn from_utf16(v: &[u16]) -> Option<String> {
- let mut s = String::with_capacity(v.len() / 2);
- for c in utf16_items(v) {
- match c {
- ScalarValue(c) => s.push_char(c),
- LoneSurrogate(_) => return None
- }
- }
- Some(s)
-}
-
-/// Decode a UTF-16 encoded vector `v` into a string, replacing
-/// invalid data with the replacement character (U+FFFD).
-///
-/// # Example
-/// ```rust
-/// use std::str;
-///
-/// // 𝄞mus<invalid>ic<invalid>
-/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
-/// 0x0073, 0xDD1E, 0x0069, 0x0063,
-/// 0xD834];
-///
-/// assert_eq!(str::from_utf16_lossy(v),
-/// "𝄞mus\uFFFDic\uFFFD".to_string());
-/// ```
-pub fn from_utf16_lossy(v: &[u16]) -> String {
- utf16_items(v).map(|c| c.to_char_lossy()).collect()
-}
-
-// Return the initial codepoint accumulator for the first byte.
-// The first byte is special, only want bottom 5 bits for width 2, 4 bits
-// for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte(
- ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-)
-
-// return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte(
- ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
-)
-
-static TAG_CONT_U8: u8 = 128u8;
-
-/// Converts a vector of bytes to a new utf-8 string.
-/// Any invalid utf-8 sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
-///
-/// # Example
-///
-/// ```rust
-/// let input = bytes!("Hello ", 0xF0, 0x90, 0x80, "World");
-/// let output = std::str::from_utf8_lossy(input);
-/// assert_eq!(output.as_slice(), "Hello \uFFFDWorld");
-/// ```
-pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> {
- if is_utf8(v) {
- return Slice(unsafe { mem::transmute(v) })
- }
-
- static REPLACEMENT: &'static [u8] = bytes!(0xEF, 0xBF, 0xBD); // U+FFFD in UTF-8
- let mut i = 0;
- let total = v.len();
- fn unsafe_get(xs: &[u8], i: uint) -> u8 {
- unsafe { *xs.unsafe_ref(i) }
- }
- fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 {
- if i >= total {
- 0
- } else {
- unsafe_get(xs, i)
- }
- }
-
- let mut res = String::with_capacity(total);
-
- if i > 0 {
- unsafe {
- res.push_bytes(v.slice_to(i))
- };
- }
-
- // subseqidx is the index of the first byte of the subsequence we're looking at.
- // It's used to copy a bunch of contiguous good codepoints at once instead of copying
- // them one by one.
- let mut subseqidx = 0;
-
- while i < total {
- let i_ = i;
- let byte = unsafe_get(v, i);
- i += 1;
-
- macro_rules! error(() => ({
- unsafe {
- if subseqidx != i_ {
- res.push_bytes(v.slice(subseqidx, i_));
- }
- subseqidx = i;
- res.push_bytes(REPLACEMENT);
- }
- }))
-
- if byte < 128u8 {
- // subseqidx handles this
- } else {
- let w = utf8_char_width(byte);
-
- match w {
- 2 => {
- if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
- error!();
- continue;
- }
- i += 1;
- }
- 3 => {
- match (byte, safe_get(v, i, total)) {
- (0xE0 , 0xA0 .. 0xBF) => (),
- (0xE1 .. 0xEC, 0x80 .. 0xBF) => (),
- (0xED , 0x80 .. 0x9F) => (),
- (0xEE .. 0xEF, 0x80 .. 0xBF) => (),
- _ => {
- error!();
- continue;
- }
- }
- i += 1;
- if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
- error!();
- continue;
- }
- i += 1;
- }
- 4 => {
- match (byte, safe_get(v, i, total)) {
- (0xF0 , 0x90 .. 0xBF) => (),
- (0xF1 .. 0xF3, 0x80 .. 0xBF) => (),
- (0xF4 , 0x80 .. 0x8F) => (),
- _ => {
- error!();
- continue;
- }
- }
- i += 1;
- if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
- error!();
- continue;
- }
- i += 1;
- if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 {
- error!();
- continue;
- }
- i += 1;
- }
- _ => {
- error!();
- continue;
- }
- }
- }
- }
- if subseqidx < total {
- unsafe {
- res.push_bytes(v.slice(subseqidx, total))
- };
- }
- Owned(res.into_string())
-}
-
-/*
-Section: MaybeOwned
-*/
-
-/// A `MaybeOwned` is a string that can hold either a `String` or a `&str`.
-/// This can be useful as an optimization when an allocation is sometimes
-/// needed but not always.
-pub enum MaybeOwned<'a> {
- /// A borrowed string
- Slice(&'a str),
- /// An owned string
- Owned(String)
-}
-
-/// `SendStr` is a specialization of `MaybeOwned` to be sendable
-pub type SendStr = MaybeOwned<'static>;
-
-impl<'a> MaybeOwned<'a> {
- /// Returns `true` if this `MaybeOwned` wraps an owned string
- #[inline]
- pub fn is_owned(&self) -> bool {
- match *self {
- Slice(_) => false,
- Owned(_) => true
- }
- }
-
- /// Returns `true` if this `MaybeOwned` wraps a borrowed string
- #[inline]
- pub fn is_slice(&self) -> bool {
- match *self {
- Slice(_) => true,
- Owned(_) => false
- }
- }
-}
-
-/// Trait for moving into a `MaybeOwned`
-pub trait IntoMaybeOwned<'a> {
- /// Moves self into a `MaybeOwned`
- fn into_maybe_owned(self) -> MaybeOwned<'a>;
-}
-
-impl<'a> IntoMaybeOwned<'a> for String {
- #[inline]
- fn into_maybe_owned(self) -> MaybeOwned<'a> {
- Owned(self)
- }
-}
-
-impl<'a> IntoMaybeOwned<'a> for &'a str {
- #[inline]
- fn into_maybe_owned(self) -> MaybeOwned<'a> { Slice(self) }
-}
-
-impl<'a> IntoMaybeOwned<'a> for MaybeOwned<'a> {
- #[inline]
- fn into_maybe_owned(self) -> MaybeOwned<'a> { self }
-}
-
-impl<'a> PartialEq for MaybeOwned<'a> {
- #[inline]
- fn eq(&self, other: &MaybeOwned) -> bool {
- self.as_slice() == other.as_slice()
- }
-}
-
-impl<'a> Eq for MaybeOwned<'a> {}
-
-impl<'a> PartialOrd for MaybeOwned<'a> {
- #[inline]
- fn lt(&self, other: &MaybeOwned) -> bool {
- self.as_slice().lt(&other.as_slice())
- }
-}
-
-impl<'a> Ord for MaybeOwned<'a> {
- #[inline]
- fn cmp(&self, other: &MaybeOwned) -> Ordering {
- self.as_slice().cmp(&other.as_slice())
- }
-}
-
-impl<'a, S: Str> Equiv<S> for MaybeOwned<'a> {
- #[inline]
- fn equiv(&self, other: &S) -> bool {
- self.as_slice() == other.as_slice()
- }
-}
-
-impl<'a> Str for MaybeOwned<'a> {
- #[inline]
- fn as_slice<'b>(&'b self) -> &'b str {
- match *self {
- Slice(s) => s,
- Owned(ref s) => s.as_slice()
- }
- }
-}
-
-impl<'a> StrAllocating for MaybeOwned<'a> {
- #[inline]
- fn into_string(self) -> String {
- match self {
- Slice(s) => s.to_string(),
- Owned(s) => s
- }
- }
-}
-
-impl<'a> Container for MaybeOwned<'a> {
- #[inline]
- fn len(&self) -> uint { self.as_slice().len() }
-}
-
-impl<'a> Clone for MaybeOwned<'a> {
- #[inline]
- fn clone(&self) -> MaybeOwned<'a> {
- match *self {
- Slice(s) => Slice(s),
- Owned(ref s) => Owned(s.to_string())
- }
- }
-}
-
-impl<'a> Default for MaybeOwned<'a> {
- #[inline]
- fn default() -> MaybeOwned<'a> { Slice("") }
-}
-
-impl<'a, H: Writer> ::hash::Hash<H> for MaybeOwned<'a> {
- #[inline]
- fn hash(&self, hasher: &mut H) {
- match *self {
- Slice(s) => s.hash(hasher),
- Owned(ref s) => s.as_slice().hash(hasher),
- }
- }
-}
-
-impl<'a> fmt::Show for MaybeOwned<'a> {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Slice(ref s) => s.fmt(f),
- Owned(ref s) => s.fmt(f)
- }
- }
-}
-
-/// Unsafe operations
-pub mod raw {
- use c_str::CString;
- use libc;
- use mem;
- use raw::Slice;
- use string::String;
- use vec::Vec;
-
- pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
- pub use core::str::raw::{slice_unchecked};
-
- /// Create a Rust string from a *u8 buffer of the given length
- pub unsafe fn from_buf_len(buf: *u8, len: uint) -> String {
- let mut result = String::new();
- result.push_bytes(mem::transmute(Slice {
- data: buf,
- len: len,
- }));
- result
- }
-
- /// Create a Rust string from a null-terminated C string
- pub unsafe fn from_c_str(c_string: *libc::c_char) -> String {
- let mut buf = String::new();
- buf.push_bytes(CString::new(c_string, false).as_bytes_no_nul());
- buf
- }
-
- /// Converts an owned vector of bytes to a new owned string. This assumes
- /// that the utf-8-ness of the vector has already been validated
- #[inline]
- pub unsafe fn from_utf8_owned(v: Vec<u8>) -> String {
- mem::transmute(v)
- }
-
- /// Converts a byte to a string.
- pub unsafe fn from_byte(u: u8) -> String {
- from_utf8_owned(vec![u])
- }
-
- /// Sets the length of a string
- ///
- /// This will explicitly set the size of the string, without actually
- /// modifying its buffers, so it is up to the caller to ensure that
- /// the string is actually the specified size.
- #[test]
- fn test_from_buf_len() {
- use slice::ImmutableVector;
- use str::StrAllocating;
-
- unsafe {
- let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
- let b = a.as_ptr();
- let c = from_buf_len(b, 3u);
- assert_eq!(c, "AAA".to_string());
- }
- }
-}
-
-/*
-Section: Trait implementations
-*/
-
-/// Any string that can be represented as a slice
-pub trait StrAllocating: Str {
- /// Convert `self` into a `String`, not making a copy if possible.
- fn into_string(self) -> String;
-
- /// Convert `self` into a `String`.
- #[inline]
- fn to_string(&self) -> String {
- String::from_str(self.as_slice())
- }
-
- #[allow(missing_doc)]
- #[deprecated = "replaced by .into_string()"]
- fn into_owned(self) -> String {
- self.into_string()
- }
-
- /// Escape each char in `s` with `char::escape_default`.
- fn escape_default(&self) -> String {
- let me = self.as_slice();
- let mut out = String::with_capacity(me.len());
- for c in me.chars() {
- c.escape_default(|c| out.push_char(c));
- }
- out
- }
-
- /// Escape each char in `s` with `char::escape_unicode`.
- fn escape_unicode(&self) -> String {
- let me = self.as_slice();
- let mut out = String::with_capacity(me.len());
- for c in me.chars() {
- c.escape_unicode(|c| out.push_char(c));
- }
- out
- }
-
- /// Replace all occurrences of one string with another.
- ///
- /// # Arguments
- ///
- /// * `from` - The string to replace
- /// * `to` - The replacement string
- ///
- /// # Return value
- ///
- /// The original string with all occurrences of `from` replaced with `to`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let s = "Do you know the muffin man,
- /// The muffin man, the muffin man, ...".to_string();
- ///
- /// assert_eq!(s.replace("muffin man", "little lamb"),
- /// "Do you know the little lamb,
- /// The little lamb, the little lamb, ...".to_string());
- ///
- /// // not found, so no change.
- /// assert_eq!(s.replace("cookie monster", "little lamb"), s);
- /// ```
- fn replace(&self, from: &str, to: &str) -> String {
- let me = self.as_slice();
- let mut result = String::new();
- let mut last_end = 0;
- for (start, end) in me.match_indices(from) {
- result.push_str(unsafe{raw::slice_bytes(me, last_end, start)});
- result.push_str(to);
- last_end = end;
- }
- result.push_str(unsafe{raw::slice_bytes(me, last_end, me.len())});
- result
- }
-
- #[allow(missing_doc)]
- #[deprecated = "obsolete, use `to_string`"]
- #[inline]
- fn to_owned(&self) -> String {
- use slice::Vector;
-
- unsafe {
- ::mem::transmute(Vec::from_slice(self.as_slice().as_bytes()))
- }
- }
-
- /// Converts to a vector of `u16` encoded as UTF-16.
- fn to_utf16(&self) -> Vec<u16> {
- let me = self.as_slice();
- let mut u = Vec::new();
- for ch in me.chars() {
- let mut buf = [0u16, ..2];
- let n = ch.encode_utf16(buf /* as mut slice! */);
- u.push_all(buf.slice_to(n));
- }
- u
- }
-
- /// Given a string, make a new string with repeated copies of it.
- fn repeat(&self, nn: uint) -> String {
- let me = self.as_slice();
- let mut ret = String::with_capacity(nn * me.len());
- for _ in range(0, nn) {
- ret.push_str(me);
- }
- ret
- }
-
- /// Levenshtein Distance between two strings.
- fn lev_distance(&self, t: &str) -> uint {
- let me = self.as_slice();
- let slen = me.len();
- let tlen = t.len();
-
- if slen == 0 { return tlen; }
- if tlen == 0 { return slen; }
-
- let mut dcol = Vec::from_fn(tlen + 1, |x| x);
-
- for (i, sc) in me.chars().enumerate() {
-
- let mut current = i;
- *dcol.get_mut(0) = current + 1;
-
- for (j, tc) in t.chars().enumerate() {
-
- let next = *dcol.get(j + 1);
-
- if sc == tc {
- *dcol.get_mut(j + 1) = current;
- } else {
- *dcol.get_mut(j + 1) = ::cmp::min(current, next);
- *dcol.get_mut(j + 1) = ::cmp::min(*dcol.get(j + 1),
- *dcol.get(j)) + 1;
- }
-
- current = next;
- }
- }
-
- return *dcol.get(tlen);
- }
-
- /// An Iterator over the string in Unicode Normalization Form D
- /// (canonical decomposition).
- #[inline]
- fn nfd_chars<'a>(&'a self) -> Decompositions<'a> {
- Decompositions {
- iter: self.as_slice().chars(),
- buffer: Vec::new(),
- sorted: false,
- kind: Canonical
- }
- }
-
- /// An Iterator over the string in Unicode Normalization Form KD
- /// (compatibility decomposition).
- #[inline]
- fn nfkd_chars<'a>(&'a self) -> Decompositions<'a> {
- Decompositions {
- iter: self.as_slice().chars(),
- buffer: Vec::new(),
- sorted: false,
- kind: Compatible
- }
- }
-}
-
-impl<'a> StrAllocating for &'a str {
- #[inline]
- fn into_string(self) -> String {
- self.to_string()
- }
-}
-
-/// Methods for owned strings
-pub trait OwnedStr {
- /// Consumes the string, returning the underlying byte buffer.
- ///
- /// The buffer does not have a null terminator.
- fn into_bytes(self) -> Vec<u8>;
-
- /// Pushes the given string onto this string, returning the concatenation of the two strings.
- fn append(self, rhs: &str) -> String;
-}
-
-impl OwnedStr for String {
- #[inline]
- fn into_bytes(self) -> Vec<u8> {
- unsafe { mem::transmute(self) }
- }
-
- #[inline]
- fn append(mut self, rhs: &str) -> String {
- self.push_str(rhs);
- self
- }
-}
-
-#[cfg(test)]
-mod tests {
- use iter::AdditiveIterator;
- use default::Default;
- use prelude::*;
- use str::*;
- use string::String;
-
- #[test]
- fn test_eq_slice() {
- assert!((eq_slice("foobar".slice(0, 3), "foo")));
- assert!((eq_slice("barfoo".slice(3, 6), "foo")));
- assert!((!eq_slice("foo1", "foo2")));
- }
-
- #[test]
- fn test_le() {
- assert!("" <= "");
- assert!("" <= "foo");
- assert!("foo" <= "foo");
- assert!("foo" != "bar");
- }
-
- #[test]
- fn test_len() {
- assert_eq!("".len(), 0u);
- assert_eq!("hello world".len(), 11u);
- assert_eq!("\x63".len(), 1u);
- assert_eq!("\xa2".len(), 2u);
- assert_eq!("\u03c0".len(), 2u);
- assert_eq!("\u2620".len(), 3u);
- assert_eq!("\U0001d11e".len(), 4u);
-
- assert_eq!("".char_len(), 0u);
- assert_eq!("hello world".char_len(), 11u);
- assert_eq!("\x63".char_len(), 1u);
- assert_eq!("\xa2".char_len(), 1u);
- assert_eq!("\u03c0".char_len(), 1u);
- assert_eq!("\u2620".char_len(), 1u);
- assert_eq!("\U0001d11e".char_len(), 1u);
- assert_eq!("ประเทศไทย中华Việt Nam".char_len(), 19u);
- }
-
- #[test]
- fn test_find() {
- assert_eq!("hello".find('l'), Some(2u));
- assert_eq!("hello".find(|c:char| c == 'o'), Some(4u));
- assert!("hello".find('x').is_none());
- assert!("hello".find(|c:char| c == 'x').is_none());
- assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30u));
- assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30u));
- }
-
- #[test]
- fn test_rfind() {
- assert_eq!("hello".rfind('l'), Some(3u));
- assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4u));
- assert!("hello".rfind('x').is_none());
- assert!("hello".rfind(|c:char| c == 'x').is_none());
- assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30u));
- assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30u));
- }
-
- #[test]
- fn test_collect() {
- let empty = "".to_string();
- let s: String = empty.as_slice().chars().collect();
- assert_eq!(empty, s);
- let data = "ประเทศไทย中".to_string();
- let s: String = data.as_slice().chars().collect();
- assert_eq!(data, s);
- }
-
- #[test]
- fn test_into_bytes() {
- let data = "asdf".to_string();
- let buf = data.into_bytes();
- assert_eq!(bytes!("asdf"), buf.as_slice());
- }
-
- #[test]
- fn test_find_str() {
- // byte positions
- assert_eq!("".find_str(""), Some(0u));
- assert!("banana".find_str("apple pie").is_none());
-
- let data = "abcabc";
- assert_eq!(data.slice(0u, 6u).find_str("ab"), Some(0u));
- assert_eq!(data.slice(2u, 6u).find_str("ab"), Some(3u - 2u));
- assert!(data.slice(2u, 4u).find_str("ab").is_none());
-
- let string = "ประเทศไทย中华Việt Nam";
- let mut data = string.to_string();
- data.push_str(string);
- assert!(data.as_slice().find_str("ไท华").is_none());
- assert_eq!(data.as_slice().slice(0u, 43u).find_str(""), Some(0u));
- assert_eq!(data.as_slice().slice(6u, 43u).find_str(""), Some(6u - 6u));
-
- assert_eq!(data.as_slice().slice(0u, 43u).find_str("ประ"), Some( 0u));
- assert_eq!(data.as_slice().slice(0u, 43u).find_str("ทศไ"), Some(12u));
- assert_eq!(data.as_slice().slice(0u, 43u).find_str("ย中"), Some(24u));
- assert_eq!(data.as_slice().slice(0u, 43u).find_str("iệt"), Some(34u));
- assert_eq!(data.as_slice().slice(0u, 43u).find_str("Nam"), Some(40u));
-
- assert_eq!(data.as_slice().slice(43u, 86u).find_str("ประ"), Some(43u - 43u));
- assert_eq!(data.as_slice().slice(43u, 86u).find_str("ทศไ"), Some(55u - 43u));
- assert_eq!(data.as_slice().slice(43u, 86u).find_str("ย中"), Some(67u - 43u));
- assert_eq!(data.as_slice().slice(43u, 86u).find_str("iệt"), Some(77u - 43u));
- assert_eq!(data.as_slice().slice(43u, 86u).find_str("Nam"), Some(83u - 43u));
- }
-
- #[test]
- fn test_slice_chars() {
- fn t(a: &str, b: &str, start: uint) {
- assert_eq!(a.slice_chars(start, start + b.char_len()), b);
- }
- t("", "", 0);
- t("hello", "llo", 2);
- t("hello", "el", 1);
- t("αβλ", "β", 1);
- t("αβλ", "", 3);
- assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8));
- }
-
- #[test]
- fn test_concat() {
- fn t(v: &[String], s: &str) {
- assert_eq!(v.concat(), s.to_str().into_string());
- }
- t(["you".to_string(), "know".to_string(), "I'm".to_string(),
- "no".to_string(), "good".to_string()], "youknowI'mnogood");
- let v: &[String] = [];
- t(v, "");
- t(["hi".to_string()], "hi");
- }
-
- #[test]
- fn test_connect() {
- fn t(v: &[String], sep: &str, s: &str) {
- assert_eq!(v.connect(sep), s.to_str().into_string());
- }
- t(["you".to_string(), "know".to_string(), "I'm".to_string(),
- "no".to_string(), "good".to_string()],
- " ", "you know I'm no good");
- let v: &[String] = [];
- t(v, " ", "");
- t(["hi".to_string()], " ", "hi");
- }
-
- #[test]
- fn test_concat_slices() {
- fn t(v: &[&str], s: &str) {
- assert_eq!(v.concat(), s.to_str().into_string());
- }
- t(["you", "know", "I'm", "no", "good"], "youknowI'mnogood");
- let v: &[&str] = [];
- t(v, "");
- t(["hi"], "hi");
- }
-
- #[test]
- fn test_connect_slices() {
- fn t(v: &[&str], sep: &str, s: &str) {
- assert_eq!(v.connect(sep), s.to_str().into_string());
- }
- t(["you", "know", "I'm", "no", "good"],
- " ", "you know I'm no good");
- t([], " ", "");
- t(["hi"], " ", "hi");
- }
-
- #[test]
- fn test_repeat() {
- assert_eq!("x".repeat(4), "xxxx".to_string());
- assert_eq!("hi".repeat(4), "hihihihi".to_string());
- assert_eq!("ไท华".repeat(3), "ไท华ไท华ไท华".to_string());
- assert_eq!("".repeat(4), "".to_string());
- assert_eq!("hi".repeat(0), "".to_string());
- }
-
- #[test]
- fn test_unsafe_slice() {
- assert_eq!("ab", unsafe {raw::slice_bytes("abc", 0, 2)});
- assert_eq!("bc", unsafe {raw::slice_bytes("abc", 1, 3)});
- assert_eq!("", unsafe {raw::slice_bytes("abc", 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 {raw::slice_bytes(letters.as_slice(),
- 0u,
- 500000)}.to_owned());
- }
-
- #[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"), "".to_string());
- assert_eq!("a".replace(a, "b"), "b".to_string());
- assert_eq!("ab".replace(a, "b"), "bb".to_string());
- let test = "test";
- assert!(" test test ".replace(test, "toast") ==
- " toast toast ".to_string());
- assert_eq!(" test test ".replace(test, ""), " ".to_string());
- }
-
- #[test]
- fn test_replace_2a() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let a = "ประเ";
- let a2 = "دولة الكويتทศไทย中华";
- assert_eq!(data.replace(a, repl).as_slice(), a2);
- }
-
- #[test]
- fn test_replace_2b() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let b = "ะเ";
- let b2 = "ปรدولة الكويتทศไทย中华";
- assert_eq!(data.replace(b, repl).as_slice(), b2);
- }
-
- #[test]
- fn test_replace_2c() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let c = "中华";
- let c2 = "ประเทศไทยدولة الكويت";
- assert_eq!(data.replace(c, repl).as_slice(), c2);
- }
-
- #[test]
- fn test_replace_2d() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let d = "ไท华";
- assert_eq!(data.replace(d, repl).as_slice(), 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!("\u65e5", "\u65e5\u672c".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() ==
- letters.as_slice().slice(0u, 3u * 500000u).to_owned());
- }
-
- #[test]
- fn test_slice_2() {
- let ss = "中华Việt Nam";
-
- assert_eq!("华", ss.slice(3u, 6u));
- assert_eq!("Việt Nam", ss.slice(6u, 16u));
-
- assert_eq!("ab", "abc".slice(0u, 2u));
- assert_eq!("bc", "abc".slice(1u, 3u));
- assert_eq!("", "abc".slice(1u, 1u));
-
- assert_eq!("中", ss.slice(0u, 3u));
- assert_eq!("华V", ss.slice(3u, 7u));
- assert_eq!("", ss.slice(3u, 3u));
- /*0: 中
- 3: 华
- 6: V
- 7: i
- 8: ệ
- 11: t
- 12:
- 13: N
- 14: a
- 15: m */
- }
-
- #[test]
- #[should_fail]
- fn test_slice_fail() {
- "中华Việt Nam".slice(0u, 2u);
- }
-
- #[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_chars() {
- let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_left_chars(v), " *** foo *** ");
- assert_eq!(" *** foo *** ".trim_left_chars(&['*', ' ']), "foo *** ");
- assert_eq!(" *** *** ".trim_left_chars(&['*', ' ']), "");
- assert_eq!("foo *** ".trim_left_chars(&['*', ' ']), "foo *** ");
-
- assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11");
- assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12");
- assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123");
- }
-
- #[test]
- fn test_trim_right_chars() {
- let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_right_chars(v), " *** foo *** ");
- assert_eq!(" *** foo *** ".trim_right_chars(&['*', ' ']), " *** foo");
- assert_eq!(" *** *** ".trim_right_chars(&['*', ' ']), "");
- assert_eq!(" *** foo".trim_right_chars(&['*', ' ']), " *** foo");
-
- assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar");
- assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar");
- assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar");
- }
-
- #[test]
- fn test_trim_chars() {
- let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_chars(v), " *** foo *** ");
- assert_eq!(" *** foo *** ".trim_chars(&['*', ' ']), "foo");
- assert_eq!(" *** *** ".trim_chars(&['*', ' ']), "");
- assert_eq!("foo".trim_chars(&['*', ' ']), "foo");
-
- assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar");
- assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar");
- assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "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!(" \u3000 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 \u3000 ".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 \u3000 ".trim(), "wut");
- assert_eq!(" hey dude ".trim(), "hey dude");
- }
-
- #[test]
- fn test_is_whitespace() {
- assert!("".is_whitespace());
- assert!(" ".is_whitespace());
- assert!("\u2009".is_whitespace()); // Thin space
- assert!(" \n\t ".is_whitespace());
- assert!(!" _ ".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!(!is_utf8([0xc0, 0x80]));
- assert!(!is_utf8([0xc0, 0xae]));
- assert!(!is_utf8([0xe0, 0x80, 0x80]));
- assert!(!is_utf8([0xe0, 0x80, 0xaf]));
- assert!(!is_utf8([0xe0, 0x81, 0x81]));
- assert!(!is_utf8([0xf0, 0x82, 0x82, 0xac]));
- assert!(!is_utf8([0xf4, 0x90, 0x80, 0x80]));
-
- // deny surrogates
- assert!(!is_utf8([0xED, 0xA0, 0x80]));
- assert!(!is_utf8([0xED, 0xBF, 0xBF]));
-
- assert!(is_utf8([0xC2, 0x80]));
- assert!(is_utf8([0xDF, 0xBF]));
- assert!(is_utf8([0xE0, 0xA0, 0x80]));
- assert!(is_utf8([0xED, 0x9F, 0xBF]));
- assert!(is_utf8([0xEE, 0x80, 0x80]));
- assert!(is_utf8([0xEF, 0xBF, 0xBF]));
- assert!(is_utf8([0xF0, 0x90, 0x80, 0x80]));
- assert!(is_utf8([0xF4, 0x8F, 0xBF, 0xBF]));
- }
-
- #[test]
- fn test_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_raw_from_c_str() {
- unsafe {
- let a = box [65, 65, 65, 65, 65, 65, 65, 0];
- let b = a.as_ptr();
- let c = raw::from_c_str(b);
- assert_eq!(c, "AAAAAAA".to_string());
- }
- }
-
- #[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
- ];
- assert_eq!("".as_bytes(), &[]);
- assert_eq!("abc".as_bytes(), &['a' as u8, 'b' as u8, 'c' as u8]);
- assert_eq!("ศไทย中华Việt Nam".as_bytes(), v.as_slice());
- }
-
- #[test]
- #[should_fail]
- fn test_as_bytes_fail() {
- // Don't double free. (I'm not sure if this exercises the
- // original problem code path anymore.)
- let s = "".to_string();
- let _bytes = s.as_bytes();
- fail!();
- }
-
- #[test]
- fn test_as_ptr() {
- let buf = "hello".as_ptr();
- unsafe {
- assert_eq!(*buf.offset(0), 'h' as u8);
- assert_eq!(*buf.offset(1), 'e' as u8);
- assert_eq!(*buf.offset(2), 'l' as u8);
- assert_eq!(*buf.offset(3), 'l' as u8);
- assert_eq!(*buf.offset(4), 'o' as u8);
- }
- }
-
- #[test]
- fn test_subslice_offset() {
- let a = "kernelsprite";
- let b = a.slice(7, a.len());
- let c = a.slice(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();
- let lines = lines.as_slice();
- 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_fail]
- fn test_subslice_offset_2() {
- let a = "alchemiter";
- let b = "cruxtruder";
- a.subslice_offset(b);
- }
-
- #[test]
- fn vec_str_conversions() {
- let s1: String = "All mimsy were the borogoves".to_string();
-
- let v: Vec<u8> = Vec::from_slice(s1.as_bytes());
- let s2: String = from_utf8(v.as_slice()).unwrap().to_string();
- let mut i: uint = 0u;
- let n1: uint = s1.len();
- let n2: uint = v.len();
- assert_eq!(n1, n2);
- while i < n1 {
- let a: u8 = s1.as_slice()[i];
- let b: u8 = s2.as_slice()[i];
- debug!("{}", a);
- debug!("{}", b);
- assert_eq!(a, b);
- i += 1u;
- }
- }
-
- #[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_utf16() {
- let pairs =
- [("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n".to_string(),
- vec![0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
- 0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16,
- 0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16,
- 0xd800_u16, 0xdf30_u16, 0x000a_u16]),
-
- ("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n".to_string(),
- vec![0xd801_u16, 0xdc12_u16, 0xd801_u16,
- 0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16,
- 0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16,
- 0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16,
- 0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16,
- 0x000a_u16]),
-
- ("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n".to_string(),
- vec![0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
- 0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16,
- 0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16,
- 0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16,
- 0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16,
- 0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16,
- 0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]),
-
- ("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n".to_string(),
- vec![0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
- 0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16,
- 0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16,
- 0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16,
- 0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16,
- 0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16,
- 0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16,
- 0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16,
- 0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16,
- 0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
- 0x000a_u16 ]),
- // Issue #12318, even-numbered non-BMP planes
- ("\U00020000".to_string(),
- vec![0xD840, 0xDC00])];
-
- for p in pairs.iter() {
- let (s, u) = (*p).clone();
- assert!(is_utf16(u.as_slice()));
- assert_eq!(s.to_utf16(), u);
-
- assert_eq!(from_utf16(u.as_slice()).unwrap(), s);
- assert_eq!(from_utf16_lossy(u.as_slice()), s);
-
- assert_eq!(from_utf16(s.to_utf16().as_slice()).unwrap(), s);
- assert_eq!(from_utf16(u.as_slice()).unwrap().to_utf16(), u);
- }
- }
-
- #[test]
- fn test_utf16_invalid() {
- // completely positive cases tested above.
- // lead + eof
- assert_eq!(from_utf16([0xD800]), None);
- // lead + lead
- assert_eq!(from_utf16([0xD800, 0xD800]), None);
-
- // isolated trail
- assert_eq!(from_utf16([0x0061, 0xDC00]), None);
-
- // general
- assert_eq!(from_utf16([0xD800, 0xd801, 0xdc8b, 0xD800]), None);
- }
-
- #[test]
- fn test_utf16_lossy() {
- // completely positive cases tested above.
- // lead + eof
- assert_eq!(from_utf16_lossy([0xD800]), "\uFFFD".to_string());
- // lead + lead
- assert_eq!(from_utf16_lossy([0xD800, 0xD800]), "\uFFFD\uFFFD".to_string());
-
- // isolated trail
- assert_eq!(from_utf16_lossy([0x0061, 0xDC00]), "a\uFFFD".to_string());
-
- // general
- assert_eq!(from_utf16_lossy([0xD800, 0xd801, 0xdc8b, 0xD800]),
- "\uFFFD𐒋\uFFFD".to_string());
- }
-
- #[test]
- fn test_truncate_utf16_at_nul() {
- let v = [];
- assert_eq!(truncate_utf16_at_nul(v), &[]);
-
- let v = [0, 2, 3];
- assert_eq!(truncate_utf16_at_nul(v), &[]);
-
- let v = [1, 0, 3];
- assert_eq!(truncate_utf16_at_nul(v), &[1]);
-
- let v = [1, 2, 0];
- assert_eq!(truncate_utf16_at_nul(v), &[1, 2]);
-
- let v = [1, 2, 3];
- assert_eq!(truncate_utf16_at_nul(v), &[1, 2, 3]);
- }
-
- #[test]
- fn test_char_at() {
- let s = "ศไทย中华Việt Nam";
- let v = box ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
- let mut pos = 0;
- for ch in v.iter() {
- assert!(s.char_at(pos) == *ch);
- pos += from_char(*ch).len();
- }
- }
-
- #[test]
- fn test_char_at_reverse() {
- let s = "ศไทย中华Việt Nam";
- let v = box ['ศ','ไ','ท','ย','中','华','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 -= from_char(*ch).len();
- }
- }
-
- #[test]
- fn test_escape_unicode() {
- assert_eq!("abc".escape_unicode(), "\\x61\\x62\\x63".to_string());
- assert_eq!("a c".escape_unicode(), "\\x61\\x20\\x63".to_string());
- assert_eq!("\r\n\t".escape_unicode(), "\\x0d\\x0a\\x09".to_string());
- assert_eq!("'\"\\".escape_unicode(), "\\x27\\x22\\x5c".to_string());
- assert_eq!("\x00\x01\xfe\xff".escape_unicode(), "\\x00\\x01\\xfe\\xff".to_string());
- assert_eq!("\u0100\uffff".escape_unicode(), "\\u0100\\uffff".to_string());
- assert_eq!("\U00010000\U0010ffff".escape_unicode(), "\\U00010000\\U0010ffff".to_string());
- assert_eq!("ab\ufb00".escape_unicode(), "\\x61\\x62\\ufb00".to_string());
- assert_eq!("\U0001d4ea\r".escape_unicode(), "\\U0001d4ea\\x0d".to_string());
- }
-
- #[test]
- fn test_escape_default() {
- assert_eq!("abc".escape_default(), "abc".to_string());
- assert_eq!("a c".escape_default(), "a c".to_string());
- assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t".to_string());
- assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\".to_string());
- assert_eq!("\u0100\uffff".escape_default(), "\\u0100\\uffff".to_string());
- assert_eq!("\U00010000\U0010ffff".escape_default(), "\\U00010000\\U0010ffff".to_string());
- assert_eq!("ab\ufb00".escape_default(), "ab\\ufb00".to_string());
- assert_eq!("\U0001d4ea\r".escape_default(), "\\U0001d4ea\\r".to_string());
- }
-
- #[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() {
- use iter::*;
- let s = "ศไทย中华Việt Nam";
- let v = box ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
-
- let mut pos = 0;
- let mut it = s.chars();
-
- for c in it {
- assert_eq!(c, v[pos]);
- pos += 1;
- }
- assert_eq!(pos, v.len());
- }
-
- #[test]
- fn test_rev_iterator() {
- use iter::*;
- let s = "ศไทย中华Việt Nam";
- let v = box ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
-
- let mut pos = 0;
- let mut it = s.chars().rev();
-
- for c in it {
- assert_eq!(c, v[pos]);
- pos += 1;
- }
- assert_eq!(pos, v.len());
- }
-
- #[test]
- fn test_iterator_clone() {
- let s = "ศไทย中华Việt Nam";
- let mut it = s.chars();
- it.next();
- assert!(it.zip(it.clone()).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() {
- use iter::*;
- 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 mut 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() {
- use iter::*;
- 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 mut 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_split_char_iterator() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let split: Vec<&str> = data.split(' ').collect();
- assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
- assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- // Unicode
- let split: Vec<&str> = data.split('ä').collect();
- assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
-
- let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
-
- let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
- assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
-
- let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
- }
-
- #[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, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
-
- let split: Vec<&str> = data.splitn(|c: char| c == ' ', 3).collect();
- assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
-
- // Unicode
- let split: Vec<&str> = data.splitn('ä', 3).collect();
- assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
-
- let split: Vec<&str> = data.splitn(|c: char| c == 'ä', 3).collect();
- assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
- }
-
- #[test]
- fn test_rsplitn_char_iterator() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let mut split: Vec<&str> = data.rsplitn(' ', 3).collect();
- split.reverse();
- assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let mut split: Vec<&str> = data.rsplitn(|c: char| c == ' ', 3).collect();
- split.reverse();
- assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
-
- // Unicode
- let mut split: Vec<&str> = data.rsplitn('ä', 3).collect();
- split.reverse();
- assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
-
- let mut split: Vec<&str> = data.rsplitn(|c: char| c == 'ä', 3).collect();
- split.reverse();
- assert_eq!(split, vec!["\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, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
-
- let split: Vec<&str> = data.split_terminator('\n').collect();
- assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
- }
-
- #[test]
- fn test_rev_split_char_iterator_no_trailing() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let mut split: Vec<&str> = data.split('\n').rev().collect();
- split.reverse();
- assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
-
- let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
- split.reverse();
- assert_eq!(split, vec!["", "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, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
- }
-
- #[test]
- fn test_nfd_chars() {
- assert_eq!("abc".nfd_chars().collect::<String>(), "abc".to_string());
- assert_eq!("\u1e0b\u01c4".nfd_chars().collect::<String>(), "d\u0307\u01c4".to_string());
- assert_eq!("\u2026".nfd_chars().collect::<String>(), "\u2026".to_string());
- assert_eq!("\u2126".nfd_chars().collect::<String>(), "\u03a9".to_string());
- assert_eq!("\u1e0b\u0323".nfd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("\u1e0d\u0307".nfd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("a\u0301".nfd_chars().collect::<String>(), "a\u0301".to_string());
- assert_eq!("\u0301a".nfd_chars().collect::<String>(), "\u0301a".to_string());
- assert_eq!("\ud4db".nfd_chars().collect::<String>(), "\u1111\u1171\u11b6".to_string());
- assert_eq!("\uac1c".nfd_chars().collect::<String>(), "\u1100\u1162".to_string());
- }
-
- #[test]
- fn test_nfkd_chars() {
- assert_eq!("abc".nfkd_chars().collect::<String>(), "abc".to_string());
- assert_eq!("\u1e0b\u01c4".nfkd_chars().collect::<String>(), "d\u0307DZ\u030c".to_string());
- assert_eq!("\u2026".nfkd_chars().collect::<String>(), "...".to_string());
- assert_eq!("\u2126".nfkd_chars().collect::<String>(), "\u03a9".to_string());
- assert_eq!("\u1e0b\u0323".nfkd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("\u1e0d\u0307".nfkd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("a\u0301".nfkd_chars().collect::<String>(), "a\u0301".to_string());
- assert_eq!("\u0301a".nfkd_chars().collect::<String>(), "\u0301a".to_string());
- assert_eq!("\ud4db".nfkd_chars().collect::<String>(), "\u1111\u1171\u11b6".to_string());
- assert_eq!("\uac1c".nfkd_chars().collect::<String>(), "\u1100\u1162".to_string());
- }
-
- #[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, vec!["", "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, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
- }
-
- #[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.as_slice(), u.as_slice());
- }
- 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 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<S: Container>(v: &[S]) -> uint {
- v.iter().map(|x| x.len()).sum()
- }
-
- let s = "01234".to_string();
- assert_eq!(5, sum_len(["012", "", "34"]));
- assert_eq!(5, sum_len(["01".to_string(), "2".to_string(),
- "34".to_string(), "".to_string()]));
- assert_eq!(5, sum_len([s.as_slice()]));
- }
-
- #[test]
- fn test_str_from_utf8() {
- let xs = bytes!("hello");
- assert_eq!(from_utf8(xs), Some("hello"));
-
- let xs = bytes!("ศไทย中华Việt Nam");
- assert_eq!(from_utf8(xs), Some("ศไทย中华Việt Nam"));
-
- let xs = bytes!("hello", 0xff);
- assert_eq!(from_utf8(xs), None);
- }
-
- #[test]
- fn test_str_from_utf8_owned() {
- let xs = Vec::from_slice(bytes!("hello"));
- assert_eq!(from_utf8_owned(xs), Ok("hello".to_string()));
-
- let xs = Vec::from_slice(bytes!("ศไทย中华Việt Nam"));
- assert_eq!(from_utf8_owned(xs), Ok("ศไทย中华Việt Nam".to_string()));
-
- let xs = Vec::from_slice(bytes!("hello", 0xff));
- assert_eq!(from_utf8_owned(xs),
- Err(Vec::from_slice(bytes!("hello", 0xff))));
- }
-
- #[test]
- fn test_str_from_utf8_lossy() {
- let xs = bytes!("hello");
- assert_eq!(from_utf8_lossy(xs), Slice("hello"));
-
- let xs = bytes!("ศไทย中华Việt Nam");
- assert_eq!(from_utf8_lossy(xs), Slice("ศไทย中华Việt Nam"));
-
- let xs = bytes!("Hello", 0xC2, " There", 0xFF, " Goodbye");
- assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD There\uFFFD Goodbye".to_string()));
-
- let xs = bytes!("Hello", 0xC0, 0x80, " There", 0xE6, 0x83, " Goodbye");
- assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD\uFFFD There\uFFFD Goodbye".to_string()));
-
- let xs = bytes!(0xF5, "foo", 0xF5, 0x80, "bar");
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFD\uFFFDbar".to_string()));
-
- let xs = bytes!(0xF1, "foo", 0xF1, 0x80, "bar", 0xF1, 0x80, 0x80, "baz");
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFDbaz".to_string()));
-
- let xs = bytes!(0xF4, "foo", 0xF4, 0x80, "bar", 0xF4, 0xBF, "baz");
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz".to_string()));
-
- let xs = bytes!(0xF0, 0x80, 0x80, 0x80, "foo", 0xF0, 0x90, 0x80, 0x80, "bar");
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFD\uFFFD\
- foo\U00010000bar".to_string()));
-
- // surrogates
- let xs = bytes!(0xED, 0xA0, 0x80, "foo", 0xED, 0xBF, 0xBF, "bar");
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFDfoo\
- \uFFFD\uFFFD\uFFFDbar".to_string()));
- }
-
- #[test]
- fn test_from_str() {
- let owned: Option<String> = from_str("string");
- assert_eq!(owned, Some("string".to_string()));
- }
-
- #[test]
- fn test_maybe_owned_traits() {
- let s = Slice("abcde");
- assert_eq!(s.len(), 5);
- assert_eq!(s.as_slice(), "abcde");
- assert_eq!(s.to_str(), "abcde".to_string());
- assert_eq!(format!("{}", s), "abcde".to_string());
- assert!(s.lt(&Owned("bcdef".to_string())));
- assert_eq!(Slice(""), Default::default());
-
- let o = Owned("abcde".to_string());
- assert_eq!(o.len(), 5);
- assert_eq!(o.as_slice(), "abcde");
- assert_eq!(o.to_str(), "abcde".to_string());
- assert_eq!(format!("{}", o), "abcde".to_string());
- assert!(o.lt(&Slice("bcdef")));
- assert_eq!(Owned("".to_string()), Default::default());
-
- assert!(s.cmp(&o) == Equal);
- assert!(s.equiv(&o));
-
- assert!(o.cmp(&s) == Equal);
- assert!(o.equiv(&s));
- }
-
- #[test]
- fn test_maybe_owned_methods() {
- let s = Slice("abcde");
- assert!(s.is_slice());
- assert!(!s.is_owned());
-
- let o = Owned("abcde".to_string());
- assert!(!o.is_slice());
- assert!(o.is_owned());
- }
-
- #[test]
- fn test_maybe_owned_clone() {
- assert_eq!(Owned("abcde".to_string()), Slice("abcde").clone());
- assert_eq!(Owned("abcde".to_string()), Owned("abcde".to_string()).clone());
- assert_eq!(Slice("abcde"), Slice("abcde").clone());
- assert_eq!(Slice("abcde"), Owned("abcde".to_string()).clone());
- }
-
- #[test]
- fn test_maybe_owned_into_string() {
- assert_eq!(Slice("abcde").into_string(), "abcde".to_string());
- assert_eq!(Owned("abcde".to_string()).into_string(), "abcde".to_string());
- }
-
- #[test]
- fn test_into_maybe_owned() {
- assert_eq!("abcde".into_maybe_owned(), Slice("abcde"));
- assert_eq!(("abcde".to_string()).into_maybe_owned(), Slice("abcde"));
- assert_eq!("abcde".into_maybe_owned(), Owned("abcde".to_string()));
- assert_eq!(("abcde".to_string()).into_maybe_owned(), Owned("abcde".to_string()));
- }
-}
-
-#[cfg(test)]
-mod bench {
- extern crate test;
- use self::test::Bencher;
- use super::*;
- use prelude::*;
-
- #[bench]
- fn char_iterator(b: &mut Bencher) {
- let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
- let len = s.char_len();
-
- b.iter(|| assert_eq!(s.chars().len(), len));
- }
-
- #[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";
- let len = s.char_len();
-
- b.iter(|| assert_eq!(s.chars().len(), len));
- }
-
- #[bench]
- fn char_iterator_rev(b: &mut Bencher) {
- let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
- let len = s.char_len();
-
- b.iter(|| assert_eq!(s.chars().rev().len(), len));
- }
-
- #[bench]
- fn char_indicesator(b: &mut Bencher) {
- let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
- let len = s.char_len();
-
- b.iter(|| assert_eq!(s.char_indices().len(), len));
- }
-
- #[bench]
- fn char_indicesator_rev(b: &mut Bencher) {
- let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
- let len = s.char_len();
-
- b.iter(|| assert_eq!(s.char_indices().rev().len(), len));
- }
-
- #[bench]
- fn split_unicode_ascii(b: &mut Bencher) {
- let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
-
- b.iter(|| assert_eq!(s.split('V').len(), 3));
- }
-
- #[bench]
- fn split_unicode_not_ascii(b: &mut Bencher) {
- struct NotAscii(char);
- impl CharEq for NotAscii {
- fn matches(&mut self, c: char) -> bool {
- let NotAscii(cc) = *self;
- cc == c
- }
- fn only_ascii(&self) -> bool { false }
- }
- let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
-
- b.iter(|| assert_eq!(s.split(NotAscii('V')).len(), 3));
- }
-
-
- #[bench]
- fn split_ascii(b: &mut Bencher) {
- let s = "Mary had a little lamb, Little lamb, little-lamb.";
- let len = s.split(' ').len();
-
- b.iter(|| assert_eq!(s.split(' ').len(), len));
- }
-
- #[bench]
- fn split_not_ascii(b: &mut Bencher) {
- struct NotAscii(char);
- impl CharEq for NotAscii {
- #[inline]
- fn matches(&mut self, c: char) -> bool {
- let NotAscii(cc) = *self;
- cc == c
- }
- fn only_ascii(&self) -> bool { false }
- }
- let s = "Mary had a little lamb, Little lamb, little-lamb.";
- let len = s.split(' ').len();
-
- b.iter(|| assert_eq!(s.split(NotAscii(' ')).len(), len));
- }
-
- #[bench]
- fn split_extern_fn(b: &mut Bencher) {
- let s = "Mary had a little lamb, Little lamb, little-lamb.";
- let len = s.split(' ').len();
- fn pred(c: char) -> bool { c == ' ' }
-
- b.iter(|| assert_eq!(s.split(pred).len(), len));
- }
-
- #[bench]
- fn split_closure(b: &mut Bencher) {
- let s = "Mary had a little lamb, Little lamb, little-lamb.";
- let len = s.split(' ').len();
-
- b.iter(|| assert_eq!(s.split(|c: char| c == ' ').len(), len));
- }
-
- #[bench]
- fn split_slice(b: &mut Bencher) {
- let s = "Mary had a little lamb, Little lamb, little-lamb.";
- let len = s.split(' ').len();
-
- b.iter(|| assert_eq!(s.split(&[' ']).len(), len));
- }
-
- #[bench]
- fn is_utf8_100_ascii(b: &mut Bencher) {
-
- let s = bytes!("Hello there, the quick brown fox jumped over the lazy dog! \
- Lorem ipsum dolor sit amet, consectetur. ");
-
- assert_eq!(100, s.len());
- b.iter(|| {
- is_utf8(s)
- });
- }
-
- #[bench]
- fn is_utf8_100_multibyte(b: &mut Bencher) {
- let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰");
- assert_eq!(100, s.len());
- b.iter(|| {
- is_utf8(s)
- });
- }
-
- #[bench]
- fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
- let s = bytes!("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 _ = from_utf8_lossy(s);
- });
- }
-
- #[bench]
- fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
- let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰");
- assert_eq!(100, s.len());
- b.iter(|| {
- let _ = from_utf8_lossy(s);
- });
- }
-
- #[bench]
- fn from_utf8_lossy_invalid(b: &mut Bencher) {
- let s = bytes!("Hello", 0xC0, 0x80, " There", 0xE6, 0x83, " Goodbye");
- b.iter(|| {
- let _ = from_utf8_lossy(s);
- });
- }
-
- #[bench]
- fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
- let s = Vec::from_elem(100, 0xF5u8);
- b.iter(|| {
- let _ = from_utf8_lossy(s.as_slice());
- });
- }
-
- #[bench]
- fn bench_connect(b: &mut Bencher) {
- let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
- let sep = "→";
- let v = [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));
- })
- }
-}
+++ /dev/null
-// 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.
-
-//! An owned, growable string that enforces that its contents are valid UTF-8.
-
-use c_vec::CVec;
-use char::Char;
-use cmp::Equiv;
-use container::{Container, Mutable};
-use default::Default;
-use fmt;
-use from_str::FromStr;
-use io::Writer;
-use iter::{Extendable, FromIterator, Iterator, range};
-use mem;
-use option::{None, Option, Some};
-use ptr::RawPtr;
-use ptr;
-use result::{Result, Ok, Err};
-use slice::Vector;
-use str::{CharRange, Str, StrSlice, StrAllocating};
-use str;
-use vec::Vec;
-
-/// A growable string stored as a UTF-8 encoded buffer.
-#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)]
-pub struct String {
- vec: Vec<u8>,
-}
-
-impl String {
- /// Creates a new string buffer initialized with the empty string.
- #[inline]
- pub fn new() -> String {
- String {
- vec: Vec::new(),
- }
- }
-
- /// Creates a new string buffer with the given capacity.
- #[inline]
- pub fn with_capacity(capacity: uint) -> String {
- String {
- vec: Vec::with_capacity(capacity),
- }
- }
-
- /// Creates a new string buffer from length, capacity, and a pointer.
- #[inline]
- pub unsafe fn from_raw_parts(length: uint, capacity: uint, ptr: *mut u8) -> String {
- String {
- vec: Vec::from_raw_parts(length, capacity, ptr),
- }
- }
-
- /// Creates a new string buffer from the given string.
- #[inline]
- pub fn from_str(string: &str) -> String {
- String {
- vec: Vec::from_slice(string.as_bytes())
- }
- }
-
- #[allow(missing_doc)]
- #[deprecated = "obsoleted by the removal of ~str"]
- #[inline]
- pub fn from_owned_str(string: String) -> String {
- string
- }
-
- /// Returns the vector as a string buffer, if possible, taking care not to
- /// copy it.
- ///
- /// Returns `Err` with the original vector if the vector contains invalid
- /// UTF-8.
- #[inline]
- pub fn from_utf8(vec: Vec<u8>) -> Result<String, Vec<u8>> {
- if str::is_utf8(vec.as_slice()) {
- Ok(String { vec: vec })
- } else {
- Err(vec)
- }
- }
-
- /// Return the underlying byte buffer, encoded as UTF-8.
- #[inline]
- pub fn into_bytes(self) -> Vec<u8> {
- self.vec
- }
-
- /// Pushes the given string onto this buffer; then, returns `self` so that it can be used
- /// again.
- #[inline]
- pub fn append(mut self, second: &str) -> String {
- self.push_str(second);
- self
- }
-
- /// Creates a string buffer by repeating a character `length` times.
- #[inline]
- pub fn from_char(length: uint, ch: char) -> String {
- if length == 0 {
- return String::new()
- }
-
- let mut buf = String::new();
- buf.push_char(ch);
- let size = buf.len() * length;
- buf.reserve(size);
- for _ in range(1, length) {
- buf.push_char(ch)
- }
- buf
- }
-
- /// Pushes the given string onto this string buffer.
- #[inline]
- pub fn push_str(&mut self, string: &str) {
- self.vec.push_all(string.as_bytes())
- }
-
- /// Push `ch` onto the given string `count` times.
- #[inline]
- pub fn grow(&mut self, count: uint, ch: char) {
- for _ in range(0, count) {
- self.push_char(ch)
- }
- }
-
- /// Returns the number of bytes that this string buffer can hold without reallocating.
- #[inline]
- pub fn byte_capacity(&self) -> uint {
- self.vec.capacity()
- }
-
- /// Reserves capacity for at least `extra` additional bytes in this string buffer.
- #[inline]
- pub fn reserve_additional(&mut self, extra: uint) {
- self.vec.reserve_additional(extra)
- }
-
- /// Reserves capacity for at least `capacity` bytes in this string buffer.
- #[inline]
- pub fn reserve(&mut self, capacity: uint) {
- self.vec.reserve(capacity)
- }
-
- /// Reserves capacity for exactly `capacity` bytes in this string buffer.
- #[inline]
- pub fn reserve_exact(&mut self, capacity: uint) {
- self.vec.reserve_exact(capacity)
- }
-
- /// Shrinks the capacity of this string buffer to match its length.
- #[inline]
- pub fn shrink_to_fit(&mut self) {
- self.vec.shrink_to_fit()
- }
-
- /// Adds the given character to the end of the string.
- #[inline]
- pub fn push_char(&mut self, ch: char) {
- let cur_len = self.len();
- unsafe {
- // This may use up to 4 bytes.
- self.vec.reserve_additional(4);
-
- // Attempt to not use an intermediate buffer by just pushing bytes
- // directly onto this string.
- let mut c_vector = CVec::new(self.vec.as_mut_ptr().offset(cur_len as int), 4);
- let used = ch.encode_utf8(c_vector.as_mut_slice());
- self.vec.set_len(cur_len + used);
- }
- }
-
- /// Pushes the given bytes onto this string buffer. This is unsafe because it does not check
- /// to ensure that the resulting string will be valid UTF-8.
- #[inline]
- pub unsafe fn push_bytes(&mut self, bytes: &[u8]) {
- self.vec.push_all(bytes)
- }
-
- /// Works with the underlying buffer as a byte slice.
- #[inline]
- pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
- self.vec.as_slice()
- }
-
- /// Works with the underlying buffer as a mutable byte slice. Unsafe
- /// because this can be used to violate the UTF-8 property.
- #[inline]
- pub unsafe fn as_mut_bytes<'a>(&'a mut self) -> &'a mut [u8] {
- self.vec.as_mut_slice()
- }
-
- /// Shorten a string to the specified length (which must be <= the current length)
- #[inline]
- pub fn truncate(&mut self, len: uint) {
- assert!(self.as_slice().is_char_boundary(len));
- self.vec.truncate(len)
- }
-
- /// Appends a byte to this string buffer. The caller must preserve the valid UTF-8 property.
- #[inline]
- pub unsafe fn push_byte(&mut self, byte: u8) {
- self.push_bytes([byte])
- }
-
- /// Removes the last byte from the string buffer and returns it. Returns `None` if this string
- /// buffer is empty.
- ///
- /// The caller must preserve the valid UTF-8 property.
- #[inline]
- pub unsafe fn pop_byte(&mut self) -> Option<u8> {
- let len = self.len();
- if len == 0 {
- return None
- }
-
- let byte = self.as_slice()[len - 1];
- self.vec.set_len(len - 1);
- Some(byte)
- }
-
- /// Removes the last character from the string buffer and returns it. Returns `None` if this
- /// string buffer is empty.
- #[inline]
- pub fn pop_char(&mut self) -> Option<char> {
- let len = self.len();
- if len == 0 {
- return None
- }
-
- let CharRange {ch, next} = self.as_slice().char_range_at_reverse(len);
- unsafe {
- self.vec.set_len(next);
- }
- Some(ch)
- }
-
- /// Removes the first byte from the string buffer and returns it. Returns `None` if this string
- /// buffer is empty.
- ///
- /// The caller must preserve the valid UTF-8 property.
- pub unsafe fn shift_byte(&mut self) -> Option<u8> {
- self.vec.shift()
- }
-
- /// Removes the first character from the string buffer and returns it. Returns `None` if this
- /// string buffer is empty.
- ///
- /// # Warning
- ///
- /// This is a O(n) operation as it requires copying every element in the buffer.
- pub fn shift_char (&mut self) -> Option<char> {
- let len = self.len();
- if len == 0 {
- return None
- }
-
- let CharRange {ch, next} = self.as_slice().char_range_at(0);
- let new_len = len - next;
- unsafe {
- ptr::copy_memory(self.vec.as_mut_ptr(), self.vec.as_ptr().offset(next as int), new_len);
- self.vec.set_len(new_len);
- }
- Some(ch)
- }
-
- /// Views the string buffer as a mutable sequence of bytes.
- ///
- /// Callers must preserve the valid UTF-8 property.
- pub unsafe fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec<u8> {
- &mut self.vec
- }
-}
-
-impl Container for String {
- #[inline]
- fn len(&self) -> uint {
- self.vec.len()
- }
-}
-
-impl Mutable for String {
- #[inline]
- fn clear(&mut self) {
- self.vec.clear()
- }
-}
-
-impl FromIterator<char> for String {
- fn from_iter<I:Iterator<char>>(iterator: I) -> String {
- let mut buf = String::new();
- buf.extend(iterator);
- buf
- }
-}
-
-impl Extendable<char> for String {
- fn extend<I:Iterator<char>>(&mut self, mut iterator: I) {
- for ch in iterator {
- self.push_char(ch)
- }
- }
-}
-
-impl Str for String {
- #[inline]
- fn as_slice<'a>(&'a self) -> &'a str {
- unsafe {
- mem::transmute(self.vec.as_slice())
- }
- }
-}
-
-impl StrAllocating for String {
- #[inline]
- fn into_string(self) -> String {
- self
- }
-}
-
-impl Default for String {
- fn default() -> String {
- String::new()
- }
-}
-
-impl fmt::Show for String {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.as_slice().fmt(f)
- }
-}
-
-impl<H:Writer> ::hash::Hash<H> for String {
- #[inline]
- fn hash(&self, hasher: &mut H) {
- self.as_slice().hash(hasher)
- }
-}
-
-impl<'a, S: Str> Equiv<S> for String {
- #[inline]
- fn equiv(&self, other: &S) -> bool {
- self.as_slice() == other.as_slice()
- }
-}
-
-impl FromStr for String {
- #[inline]
- fn from_str(s: &str) -> Option<String> {
- Some(s.to_string())
- }
-}
-
-#[cfg(test)]
-mod tests {
- extern crate test;
- use container::{Container, Mutable};
- use self::test::Bencher;
- use str::{Str, StrSlice};
- use super::String;
-
- #[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);
- });
- }
-
- #[test]
- fn test_push_bytes() {
- let mut s = String::from_str("ABC");
- unsafe {
- s.push_bytes([ 'D' as u8 ]);
- }
- assert_eq!(s.as_slice(), "ABCD");
- }
-
- #[test]
- fn test_push_str() {
- let mut s = String::new();
- s.push_str("");
- assert_eq!(s.as_slice().slice_from(0), "");
- s.push_str("abc");
- assert_eq!(s.as_slice().slice_from(0), "abc");
- s.push_str("ประเทศไทย中华Việt Nam");
- assert_eq!(s.as_slice().slice_from(0), "abcประเทศไทย中华Việt Nam");
- }
-
- #[test]
- fn test_push_char() {
- let mut data = String::from_str("ประเทศไทย中");
- data.push_char('华');
- data.push_char('b'); // 1 byte
- data.push_char('¢'); // 2 byte
- data.push_char('€'); // 3 byte
- data.push_char('𤭢'); // 4 byte
- assert_eq!(data.as_slice(), "ประเทศไทย中华b¢€𤭢");
- }
-
- #[test]
- fn test_pop_char() {
- let mut data = String::from_str("ประเทศไทย中华b¢€𤭢");
- assert_eq!(data.pop_char().unwrap(), '𤭢'); // 4 bytes
- assert_eq!(data.pop_char().unwrap(), '€'); // 3 bytes
- assert_eq!(data.pop_char().unwrap(), '¢'); // 2 bytes
- assert_eq!(data.pop_char().unwrap(), 'b'); // 1 bytes
- assert_eq!(data.pop_char().unwrap(), '华');
- assert_eq!(data.as_slice(), "ประเทศไทย中");
- }
-
- #[test]
- fn test_shift_char() {
- let mut data = String::from_str("𤭢€¢b华ประเทศไทย中");
- assert_eq!(data.shift_char().unwrap(), '𤭢'); // 4 bytes
- assert_eq!(data.shift_char().unwrap(), '€'); // 3 bytes
- assert_eq!(data.shift_char().unwrap(), '¢'); // 2 bytes
- assert_eq!(data.shift_char().unwrap(), 'b'); // 1 bytes
- assert_eq!(data.shift_char().unwrap(), '华');
- assert_eq!(data.as_slice(), "ประเทศไทย中");
- }
-
- #[test]
- fn test_str_truncate() {
- let mut s = String::from_str("12345");
- s.truncate(5);
- assert_eq!(s.as_slice(), "12345");
- s.truncate(3);
- assert_eq!(s.as_slice(), "123");
- s.truncate(0);
- assert_eq!(s.as_slice(), "");
-
- let mut s = String::from_str("12345");
- let p = s.as_slice().as_ptr();
- s.truncate(3);
- s.push_str("6");
- let p_ = s.as_slice().as_ptr();
- assert_eq!(p_, p);
- }
-
- #[test]
- #[should_fail]
- fn test_str_truncate_invalid_len() {
- let mut s = String::from_str("12345");
- s.truncate(6);
- }
-
- #[test]
- #[should_fail]
- fn test_str_truncate_split_codepoint() {
- let mut s = String::from_str("\u00FC"); // ü
- 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.as_slice(), "");
- }
-}
+++ /dev/null
-// 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.
-
-// NOTE: The following code was generated by "src/etc/unicode.py", do not edit directly
-
-#![allow(missing_doc, non_uppercase_statics)]
-
-pub mod normalization {
- use option::{Some, None};
- use slice::ImmutableVector;
-
- fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
- use cmp::{Equal, Less, Greater};
- match r.bsearch(|&(lo, hi, _)| {
- if lo <= c && c <= hi { Equal }
- else if hi < c { Less }
- else { Greater }
- }) {
- Some(idx) => {
- let (_, _, result) = r[idx];
- result
- }
- None => 0
- }
- }
-
-
- static combining_class_table : &'static [(char, char, u8)] = &[
- ('\u0300', '\u0314', 230), ('\u0315', '\u0315', 232),
- ('\u0316', '\u0319', 220), ('\u031a', '\u031a', 232),
- ('\u031b', '\u031b', 216), ('\u031c', '\u0320', 220),
- ('\u0321', '\u0322', 202), ('\u0323', '\u0326', 220),
- ('\u0327', '\u0328', 202), ('\u0329', '\u0333', 220),
- ('\u0334', '\u0338', 1), ('\u0339', '\u033c', 220),
- ('\u033d', '\u0344', 230), ('\u0345', '\u0345', 240),
- ('\u0346', '\u0346', 230), ('\u0347', '\u0349', 220),
- ('\u034a', '\u034c', 230), ('\u034d', '\u034e', 220),
- ('\u0350', '\u0352', 230), ('\u0353', '\u0356', 220),
- ('\u0357', '\u0357', 230), ('\u0358', '\u0358', 232),
- ('\u0359', '\u035a', 220), ('\u035b', '\u035b', 230),
- ('\u035c', '\u035c', 233), ('\u035d', '\u035e', 234),
- ('\u035f', '\u035f', 233), ('\u0360', '\u0361', 234),
- ('\u0362', '\u0362', 233), ('\u0363', '\u036f', 230),
- ('\u0483', '\u0487', 230), ('\u0591', '\u0591', 220),
- ('\u0592', '\u0595', 230), ('\u0596', '\u0596', 220),
- ('\u0597', '\u0599', 230), ('\u059a', '\u059a', 222),
- ('\u059b', '\u059b', 220), ('\u059c', '\u05a1', 230),
- ('\u05a2', '\u05a7', 220), ('\u05a8', '\u05a9', 230),
- ('\u05aa', '\u05aa', 220), ('\u05ab', '\u05ac', 230),
- ('\u05ad', '\u05ad', 222), ('\u05ae', '\u05ae', 228),
- ('\u05af', '\u05af', 230), ('\u05b0', '\u05b0', 10),
- ('\u05b1', '\u05b1', 11), ('\u05b2', '\u05b2', 12),
- ('\u05b3', '\u05b3', 13), ('\u05b4', '\u05b4', 14),
- ('\u05b5', '\u05b5', 15), ('\u05b6', '\u05b6', 16),
- ('\u05b7', '\u05b7', 17), ('\u05b8', '\u05b8', 18),
- ('\u05b9', '\u05ba', 19), ('\u05bb', '\u05bb', 20),
- ('\u05bc', '\u05bc', 21), ('\u05bd', '\u05bd', 22),
- ('\u05bf', '\u05bf', 23), ('\u05c1', '\u05c1', 24),
- ('\u05c2', '\u05c2', 25), ('\u05c4', '\u05c4', 230),
- ('\u05c5', '\u05c5', 220), ('\u05c7', '\u05c7', 18),
- ('\u0610', '\u0617', 230), ('\u0618', '\u0618', 30),
- ('\u0619', '\u0619', 31), ('\u061a', '\u061a', 32),
- ('\u064b', '\u064b', 27), ('\u064c', '\u064c', 28),
- ('\u064d', '\u064d', 29), ('\u064e', '\u064e', 30),
- ('\u064f', '\u064f', 31), ('\u0650', '\u0650', 32),
- ('\u0651', '\u0651', 33), ('\u0652', '\u0652', 34),
- ('\u0653', '\u0654', 230), ('\u0655', '\u0656', 220),
- ('\u0657', '\u065b', 230), ('\u065c', '\u065c', 220),
- ('\u065d', '\u065e', 230), ('\u065f', '\u065f', 220),
- ('\u0670', '\u0670', 35), ('\u06d6', '\u06dc', 230),
- ('\u06df', '\u06e2', 230), ('\u06e3', '\u06e3', 220),
- ('\u06e4', '\u06e4', 230), ('\u06e7', '\u06e8', 230),
- ('\u06ea', '\u06ea', 220), ('\u06eb', '\u06ec', 230),
- ('\u06ed', '\u06ed', 220), ('\u0711', '\u0711', 36),
- ('\u0730', '\u0730', 230), ('\u0731', '\u0731', 220),
- ('\u0732', '\u0733', 230), ('\u0734', '\u0734', 220),
- ('\u0735', '\u0736', 230), ('\u0737', '\u0739', 220),
- ('\u073a', '\u073a', 230), ('\u073b', '\u073c', 220),
- ('\u073d', '\u073d', 230), ('\u073e', '\u073e', 220),
- ('\u073f', '\u0741', 230), ('\u0742', '\u0742', 220),
- ('\u0743', '\u0743', 230), ('\u0744', '\u0744', 220),
- ('\u0745', '\u0745', 230), ('\u0746', '\u0746', 220),
- ('\u0747', '\u0747', 230), ('\u0748', '\u0748', 220),
- ('\u0749', '\u074a', 230), ('\u07eb', '\u07f1', 230),
- ('\u07f2', '\u07f2', 220), ('\u07f3', '\u07f3', 230),
- ('\u0816', '\u0819', 230), ('\u081b', '\u0823', 230),
- ('\u0825', '\u0827', 230), ('\u0829', '\u082d', 230),
- ('\u0859', '\u085b', 220), ('\u08e4', '\u08e5', 230),
- ('\u08e6', '\u08e6', 220), ('\u08e7', '\u08e8', 230),
- ('\u08e9', '\u08e9', 220), ('\u08ea', '\u08ec', 230),
- ('\u08ed', '\u08ef', 220), ('\u08f0', '\u08f0', 27),
- ('\u08f1', '\u08f1', 28), ('\u08f2', '\u08f2', 29),
- ('\u08f3', '\u08f5', 230), ('\u08f6', '\u08f6', 220),
- ('\u08f7', '\u08f8', 230), ('\u08f9', '\u08fa', 220),
- ('\u08fb', '\u08fe', 230), ('\u093c', '\u093c', 7),
- ('\u094d', '\u094d', 9), ('\u0951', '\u0951', 230),
- ('\u0952', '\u0952', 220), ('\u0953', '\u0954', 230),
- ('\u09bc', '\u09bc', 7), ('\u09cd', '\u09cd', 9),
- ('\u0a3c', '\u0a3c', 7), ('\u0a4d', '\u0a4d', 9),
- ('\u0abc', '\u0abc', 7), ('\u0acd', '\u0acd', 9),
- ('\u0b3c', '\u0b3c', 7), ('\u0b4d', '\u0b4d', 9),
- ('\u0bcd', '\u0bcd', 9), ('\u0c4d', '\u0c4d', 9),
- ('\u0c55', '\u0c55', 84), ('\u0c56', '\u0c56', 91),
- ('\u0cbc', '\u0cbc', 7), ('\u0ccd', '\u0ccd', 9),
- ('\u0d4d', '\u0d4d', 9), ('\u0dca', '\u0dca', 9),
- ('\u0e38', '\u0e39', 103), ('\u0e3a', '\u0e3a', 9),
- ('\u0e48', '\u0e4b', 107), ('\u0eb8', '\u0eb9', 118),
- ('\u0ec8', '\u0ecb', 122), ('\u0f18', '\u0f19', 220),
- ('\u0f35', '\u0f35', 220), ('\u0f37', '\u0f37', 220),
- ('\u0f39', '\u0f39', 216), ('\u0f71', '\u0f71', 129),
- ('\u0f72', '\u0f72', 130), ('\u0f74', '\u0f74', 132),
- ('\u0f7a', '\u0f7d', 130), ('\u0f80', '\u0f80', 130),
- ('\u0f82', '\u0f83', 230), ('\u0f84', '\u0f84', 9),
- ('\u0f86', '\u0f87', 230), ('\u0fc6', '\u0fc6', 220),
- ('\u1037', '\u1037', 7), ('\u1039', '\u103a', 9),
- ('\u108d', '\u108d', 220), ('\u135d', '\u135f', 230),
- ('\u1714', '\u1714', 9), ('\u1734', '\u1734', 9),
- ('\u17d2', '\u17d2', 9), ('\u17dd', '\u17dd', 230),
- ('\u18a9', '\u18a9', 228), ('\u1939', '\u1939', 222),
- ('\u193a', '\u193a', 230), ('\u193b', '\u193b', 220),
- ('\u1a17', '\u1a17', 230), ('\u1a18', '\u1a18', 220),
- ('\u1a60', '\u1a60', 9), ('\u1a75', '\u1a7c', 230),
- ('\u1a7f', '\u1a7f', 220), ('\u1b34', '\u1b34', 7),
- ('\u1b44', '\u1b44', 9), ('\u1b6b', '\u1b6b', 230),
- ('\u1b6c', '\u1b6c', 220), ('\u1b6d', '\u1b73', 230),
- ('\u1baa', '\u1bab', 9), ('\u1be6', '\u1be6', 7),
- ('\u1bf2', '\u1bf3', 9), ('\u1c37', '\u1c37', 7),
- ('\u1cd0', '\u1cd2', 230), ('\u1cd4', '\u1cd4', 1),
- ('\u1cd5', '\u1cd9', 220), ('\u1cda', '\u1cdb', 230),
- ('\u1cdc', '\u1cdf', 220), ('\u1ce0', '\u1ce0', 230),
- ('\u1ce2', '\u1ce8', 1), ('\u1ced', '\u1ced', 220),
- ('\u1cf4', '\u1cf4', 230), ('\u1dc0', '\u1dc1', 230),
- ('\u1dc2', '\u1dc2', 220), ('\u1dc3', '\u1dc9', 230),
- ('\u1dca', '\u1dca', 220), ('\u1dcb', '\u1dcc', 230),
- ('\u1dcd', '\u1dcd', 234), ('\u1dce', '\u1dce', 214),
- ('\u1dcf', '\u1dcf', 220), ('\u1dd0', '\u1dd0', 202),
- ('\u1dd1', '\u1de6', 230), ('\u1dfc', '\u1dfc', 233),
- ('\u1dfd', '\u1dfd', 220), ('\u1dfe', '\u1dfe', 230),
- ('\u1dff', '\u1dff', 220), ('\u20d0', '\u20d1', 230),
- ('\u20d2', '\u20d3', 1), ('\u20d4', '\u20d7', 230),
- ('\u20d8', '\u20da', 1), ('\u20db', '\u20dc', 230),
- ('\u20e1', '\u20e1', 230), ('\u20e5', '\u20e6', 1),
- ('\u20e7', '\u20e7', 230), ('\u20e8', '\u20e8', 220),
- ('\u20e9', '\u20e9', 230), ('\u20ea', '\u20eb', 1),
- ('\u20ec', '\u20ef', 220), ('\u20f0', '\u20f0', 230),
- ('\u2cef', '\u2cf1', 230), ('\u2d7f', '\u2d7f', 9),
- ('\u2de0', '\u2dff', 230), ('\u302a', '\u302a', 218),
- ('\u302b', '\u302b', 228), ('\u302c', '\u302c', 232),
- ('\u302d', '\u302d', 222), ('\u302e', '\u302f', 224),
- ('\u3099', '\u309a', 8), ('\ua66f', '\ua66f', 230),
- ('\ua674', '\ua67d', 230), ('\ua69f', '\ua69f', 230),
- ('\ua6f0', '\ua6f1', 230), ('\ua806', '\ua806', 9),
- ('\ua8c4', '\ua8c4', 9), ('\ua8e0', '\ua8f1', 230),
- ('\ua92b', '\ua92d', 220), ('\ua953', '\ua953', 9),
- ('\ua9b3', '\ua9b3', 7), ('\ua9c0', '\ua9c0', 9),
- ('\uaab0', '\uaab0', 230), ('\uaab2', '\uaab3', 230),
- ('\uaab4', '\uaab4', 220), ('\uaab7', '\uaab8', 230),
- ('\uaabe', '\uaabf', 230), ('\uaac1', '\uaac1', 230),
- ('\uaaf6', '\uaaf6', 9), ('\uabed', '\uabed', 9),
- ('\ufb1e', '\ufb1e', 26), ('\ufe20', '\ufe26', 230),
- ('\U000101fd', '\U000101fd', 220), ('\U00010a0d', '\U00010a0d', 220),
- ('\U00010a0f', '\U00010a0f', 230), ('\U00010a38', '\U00010a38', 230),
- ('\U00010a39', '\U00010a39', 1), ('\U00010a3a', '\U00010a3a', 220),
- ('\U00010a3f', '\U00010a3f', 9), ('\U00011046', '\U00011046', 9),
- ('\U000110b9', '\U000110b9', 9), ('\U000110ba', '\U000110ba', 7),
- ('\U00011100', '\U00011102', 230), ('\U00011133', '\U00011134', 9),
- ('\U000111c0', '\U000111c0', 9), ('\U000116b6', '\U000116b6', 9),
- ('\U000116b7', '\U000116b7', 7), ('\U0001d165', '\U0001d166', 216),
- ('\U0001d167', '\U0001d169', 1), ('\U0001d16d', '\U0001d16d', 226),
- ('\U0001d16e', '\U0001d172', 216), ('\U0001d17b', '\U0001d182', 220),
- ('\U0001d185', '\U0001d189', 230), ('\U0001d18a', '\U0001d18b', 220),
- ('\U0001d1aa', '\U0001d1ad', 230), ('\U0001d242', '\U0001d244', 230)
- ];
-
- pub fn canonical_combining_class(c: char) -> u8 {
- bsearch_range_value_table(c, combining_class_table)
- }
-}
+++ /dev/null
-// 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.
-
-//! An owned, growable vector.
-
-use RawVec = raw::Vec;
-use clone::Clone;
-use cmp::{PartialOrd, PartialEq, Ordering, Eq, Ord, max};
-use container::{Container, Mutable};
-use default::Default;
-use fmt;
-use iter::{DoubleEndedIterator, FromIterator, Extendable, Iterator, range};
-use mem;
-use num::{CheckedMul, CheckedAdd};
-use num;
-use ops::{Add, Drop};
-use option::{None, Option, Some};
-use ptr::RawPtr;
-use ptr;
-use raw::Slice;
-use rt::heap::{allocate, reallocate, deallocate};
-use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector};
-use slice::{MutableOrdVector, OwnedVector, Vector};
-use slice::{MutableVectorAllocating};
-
-/// An owned, growable vector.
-///
-/// # Examples
-///
-/// ```rust
-/// # use std::vec::Vec;
-/// let mut vec = Vec::new();
-/// vec.push(1);
-/// vec.push(2);
-///
-/// assert_eq!(vec.len(), 2);
-/// assert_eq!(vec.get(0), &1);
-///
-/// assert_eq!(vec.pop(), Some(2));
-/// assert_eq!(vec.len(), 1);
-/// ```
-///
-/// The `vec!` macro is provided to make initialization more convenient:
-///
-/// ```rust
-/// let mut vec = vec!(1, 2, 3);
-/// vec.push(4);
-/// assert_eq!(vec, vec!(1, 2, 3, 4));
-/// ```
-#[unsafe_no_drop_flag]
-pub struct Vec<T> {
- len: uint,
- cap: uint,
- ptr: *mut T
-}
-
-impl<T> Vec<T> {
- /// Constructs a new, empty `Vec`.
- ///
- /// The vector will not allocate until elements are pushed onto it.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::vec::Vec;
- /// let mut vec: Vec<int> = Vec::new();
- /// ```
- #[inline]
- pub fn new() -> Vec<T> {
- Vec { len: 0, cap: 0, ptr: 0 as *mut T }
- }
-
- /// Constructs a new, empty `Vec` with the specified capacity.
- ///
- /// The vector will be able to hold exactly `capacity` elements without
- /// reallocating. If `capacity` is 0, the vector will not allocate.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::vec::Vec;
- /// let vec: Vec<int> = Vec::with_capacity(10);
- /// ```
- pub fn with_capacity(capacity: uint) -> Vec<T> {
- if mem::size_of::<T>() == 0 {
- Vec { len: 0, cap: ::uint::MAX, ptr: 0 as *mut T }
- } else if capacity == 0 {
- Vec::new()
- } else {
- let size = capacity.checked_mul(&mem::size_of::<T>())
- .expect("capacity overflow");
- let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
- Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
- }
- }
-
- /// Creates and initializes a `Vec`.
- ///
- /// Creates a `Vec` of size `length` and initializes the elements to the
- /// value returned by the closure `op`.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::vec::Vec;
- /// let vec = Vec::from_fn(3, |idx| idx * 2);
- /// assert_eq!(vec, vec!(0, 2, 4));
- /// ```
- pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> {
- unsafe {
- let mut xs = Vec::with_capacity(length);
- while xs.len < length {
- mem::overwrite(xs.as_mut_slice().unsafe_mut_ref(xs.len),
- op(xs.len));
- xs.len += 1;
- }
- xs
- }
- }
-
- /// Create a `Vec<T>` directly from the raw constituents.
- ///
- /// This is highly unsafe:
- ///
- /// - if `ptr` is null, then `length` and `capacity` should be 0
- /// - `ptr` must point to an allocation of size `capacity`
- /// - there must be `length` valid instances of type `T` at the
- /// beginning of that allocation
- /// - `ptr` must be allocated by the default `Vec` allocator
- pub unsafe fn from_raw_parts(length: uint, capacity: uint,
- ptr: *mut T) -> Vec<T> {
- Vec { len: length, cap: capacity, ptr: ptr }
- }
-
- /// Consumes the `Vec`, partitioning it based on a predicate.
- ///
- /// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A`
- /// satisfy `f` and all elements of `B` do not. The order of elements is
- /// preserved.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3, 4);
- /// let (even, odd) = vec.partition(|&n| n % 2 == 0);
- /// assert_eq!(even, vec!(2, 4));
- /// assert_eq!(odd, vec!(1, 3));
- /// ```
- #[inline]
- pub fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
- let mut lefts = Vec::new();
- let mut rights = Vec::new();
-
- for elt in self.move_iter() {
- if f(&elt) {
- lefts.push(elt);
- } else {
- rights.push(elt);
- }
- }
-
- (lefts, rights)
- }
-}
-
-impl<T: Clone> Vec<T> {
- /// Iterates over the `second` vector, copying each element and appending it to
- /// the `first`. Afterwards, the `first` is then returned for use again.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2);
- /// let vec = vec.append([3, 4]);
- /// assert_eq!(vec, vec!(1, 2, 3, 4));
- /// ```
- #[inline]
- pub fn append(mut self, second: &[T]) -> Vec<T> {
- self.push_all(second);
- self
- }
-
- /// Constructs a `Vec` by cloning elements of a slice.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::vec::Vec;
- /// let slice = [1, 2, 3];
- /// let vec = Vec::from_slice(slice);
- /// ```
- pub fn from_slice(values: &[T]) -> Vec<T> {
- values.iter().map(|x| x.clone()).collect()
- }
-
- /// Constructs a `Vec` with copies of a value.
- ///
- /// Creates a `Vec` with `length` copies of `value`.
- ///
- /// # Example
- /// ```rust
- /// # use std::vec::Vec;
- /// let vec = Vec::from_elem(3, "hi");
- /// println!("{}", vec); // prints [hi, hi, hi]
- /// ```
- pub fn from_elem(length: uint, value: T) -> Vec<T> {
- unsafe {
- let mut xs = Vec::with_capacity(length);
- while xs.len < length {
- mem::overwrite(xs.as_mut_slice().unsafe_mut_ref(xs.len),
- value.clone());
- xs.len += 1;
- }
- xs
- }
- }
-
- /// Appends all elements in a slice to the `Vec`.
- ///
- /// Iterates over the slice `other`, clones each element, and then appends
- /// it to this `Vec`. The `other` vector is traversed in-order.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1);
- /// vec.push_all([2, 3, 4]);
- /// assert_eq!(vec, vec!(1, 2, 3, 4));
- /// ```
- #[inline]
- pub fn push_all(&mut self, other: &[T]) {
- self.extend(other.iter().map(|e| e.clone()));
- }
-
- /// Grows the `Vec` in-place.
- ///
- /// Adds `n` copies of `value` to the `Vec`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!("hello");
- /// vec.grow(2, &("world"));
- /// assert_eq!(vec, vec!("hello", "world", "world"));
- /// ```
- pub fn grow(&mut self, n: uint, value: &T) {
- let new_len = self.len() + n;
- self.reserve(new_len);
- let mut i: uint = 0u;
-
- while i < n {
- self.push((*value).clone());
- i += 1u;
- }
- }
-
- /// Sets the value of a vector element at a given index, growing the vector
- /// as needed.
- ///
- /// Sets the element at position `index` to `value`. If `index` is past the
- /// end of the vector, expands the vector by replicating `initval` to fill
- /// the intervening space.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!("a", "b", "c");
- /// vec.grow_set(1, &("fill"), "d");
- /// vec.grow_set(4, &("fill"), "e");
- /// assert_eq!(vec, vec!("a", "d", "c", "fill", "e"));
- /// ```
- pub fn grow_set(&mut self, index: uint, initval: &T, value: T) {
- let l = self.len();
- if index >= l {
- self.grow(index - l + 1u, initval);
- }
- *self.get_mut(index) = value;
- }
-
- /// Partitions a vector based on a predicate.
- ///
- /// Clones the elements of the vector, partitioning them into two `Vec`s
- /// `(A,B)`, where all elements of `A` satisfy `f` and all elements of `B`
- /// do not. The order of elements is preserved.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3, 4);
- /// let (even, odd) = vec.partitioned(|&n| n % 2 == 0);
- /// assert_eq!(even, vec!(2, 4));
- /// assert_eq!(odd, vec!(1, 3));
- /// ```
- pub fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
- let mut lefts = Vec::new();
- let mut rights = Vec::new();
-
- for elt in self.iter() {
- if f(elt) {
- lefts.push(elt.clone());
- } else {
- rights.push(elt.clone());
- }
- }
-
- (lefts, rights)
- }
-}
-
-impl<T:Clone> Clone for Vec<T> {
- fn clone(&self) -> Vec<T> {
- let len = self.len;
- let mut vector = Vec::with_capacity(len);
- // Unsafe code so this can be optimised to a memcpy (or something
- // similarly fast) when T is Copy. LLVM is easily confused, so any
- // extra operations during the loop can prevent this optimisation
- {
- let this_slice = self.as_slice();
- while vector.len < len {
- unsafe {
- mem::overwrite(
- vector.as_mut_slice().unsafe_mut_ref(vector.len),
- this_slice.unsafe_ref(vector.len).clone());
- }
- vector.len += 1;
- }
- }
- vector
- }
-
- fn clone_from(&mut self, other: &Vec<T>) {
- // drop anything in self that will not be overwritten
- if self.len() > other.len() {
- self.truncate(other.len())
- }
-
- // reuse the contained values' allocations/resources.
- for (place, thing) in self.mut_iter().zip(other.iter()) {
- place.clone_from(thing)
- }
-
- // self.len <= other.len due to the truncate above, so the
- // slice here is always in-bounds.
- let len = self.len();
- self.extend(other.slice_from(len).iter().map(|x| x.clone()));
- }
-}
-
-impl<T> FromIterator<T> for Vec<T> {
- fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
- let (lower, _) = iterator.size_hint();
- let mut vector = Vec::with_capacity(lower);
- for element in iterator {
- vector.push(element)
- }
- vector
- }
-}
-
-impl<T> Extendable<T> for Vec<T> {
- fn extend<I: Iterator<T>>(&mut self, mut iterator: I) {
- let (lower, _) = iterator.size_hint();
- self.reserve_additional(lower);
- for element in iterator {
- self.push(element)
- }
- }
-}
-
-impl<T: PartialEq> PartialEq for Vec<T> {
- #[inline]
- fn eq(&self, other: &Vec<T>) -> bool {
- self.as_slice() == other.as_slice()
- }
-}
-
-impl<T: PartialOrd> PartialOrd for Vec<T> {
- #[inline]
- fn lt(&self, other: &Vec<T>) -> bool {
- self.as_slice() < other.as_slice()
- }
-}
-
-impl<T: Eq> Eq for Vec<T> {}
-
-impl<T: Ord> Ord for Vec<T> {
- #[inline]
- fn cmp(&self, other: &Vec<T>) -> Ordering {
- self.as_slice().cmp(&other.as_slice())
- }
-}
-
-impl<T> Container for Vec<T> {
- #[inline]
- fn len(&self) -> uint {
- self.len
- }
-}
-
-// FIXME: #13996: need a way to mark the return value as `noalias`
-#[inline(never)]
-unsafe fn alloc_or_realloc<T>(ptr: *mut T, size: uint, old_size: uint) -> *mut T {
- if old_size == 0 {
- allocate(size, mem::min_align_of::<T>()) as *mut T
- } else {
- reallocate(ptr as *mut u8, size,
- mem::min_align_of::<T>(), old_size) as *mut T
- }
-}
-
-#[inline]
-unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
- if mem::size_of::<T>() != 0 {
- deallocate(ptr as *mut u8,
- len * mem::size_of::<T>(),
- mem::min_align_of::<T>())
- }
-}
-
-impl<T> Vec<T> {
- /// Returns the number of elements the vector can hold without
- /// reallocating.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::vec::Vec;
- /// let vec: Vec<int> = Vec::with_capacity(10);
- /// assert_eq!(vec.capacity(), 10);
- /// ```
- #[inline]
- pub fn capacity(&self) -> uint {
- self.cap
- }
-
- /// Reserves capacity for at least `n` additional elements in the given
- /// vector.
- ///
- /// # Failure
- ///
- /// Fails if the new capacity overflows `uint`.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::vec::Vec;
- /// let mut vec: Vec<int> = vec!(1);
- /// vec.reserve_additional(10);
- /// assert!(vec.capacity() >= 11);
- /// ```
- pub fn reserve_additional(&mut self, extra: uint) {
- if self.cap - self.len < extra {
- match self.len.checked_add(&extra) {
- None => fail!("Vec::reserve_additional: `uint` overflow"),
- Some(new_cap) => self.reserve(new_cap)
- }
- }
- }
-
- /// Reserves capacity for at least `n` elements in the given vector.
- ///
- /// This function will over-allocate in order to amortize the allocation
- /// costs in scenarios where the caller may need to repeatedly reserve
- /// additional space.
- ///
- /// If the capacity for `self` is already equal to or greater than the
- /// requested capacity, then no action is taken.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// vec.reserve(10);
- /// assert!(vec.capacity() >= 10);
- /// ```
- pub fn reserve(&mut self, capacity: uint) {
- if capacity >= self.len {
- self.reserve_exact(num::next_power_of_two(capacity))
- }
- }
-
- /// Reserves capacity for exactly `capacity` elements in the given vector.
- ///
- /// If the capacity for `self` is already equal to or greater than the
- /// requested capacity, then no action is taken.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::vec::Vec;
- /// let mut vec: Vec<int> = Vec::with_capacity(10);
- /// vec.reserve_exact(11);
- /// assert_eq!(vec.capacity(), 11);
- /// ```
- pub fn reserve_exact(&mut self, capacity: uint) {
- if mem::size_of::<T>() == 0 { return }
-
- if capacity > self.cap {
- let size = capacity.checked_mul(&mem::size_of::<T>())
- .expect("capacity overflow");
- unsafe {
- self.ptr = alloc_or_realloc(self.ptr, size,
- self.cap * mem::size_of::<T>());
- }
- self.cap = capacity;
- }
- }
-
- /// Shrink the capacity of the vector as much as possible
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// vec.shrink_to_fit();
- /// ```
- pub fn shrink_to_fit(&mut self) {
- if mem::size_of::<T>() == 0 { return }
-
- if self.len == 0 {
- if self.cap != 0 {
- unsafe {
- dealloc(self.ptr, self.cap)
- }
- self.cap = 0;
- }
- } else {
- unsafe {
- // Overflow check is unnecessary as the vector is already at
- // least this large.
- self.ptr = reallocate(self.ptr as *mut u8,
- self.len * mem::size_of::<T>(),
- mem::min_align_of::<T>(),
- self.cap * mem::size_of::<T>()) as *mut T;
- }
- self.cap = self.len;
- }
- }
-
- /// Remove the last element from a vector and return it, or `None` if it is
- /// empty.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// assert_eq!(vec.pop(), Some(3));
- /// assert_eq!(vec, vec!(1, 2));
- /// ```
- #[inline]
- pub fn pop(&mut self) -> Option<T> {
- if self.len == 0 {
- None
- } else {
- unsafe {
- self.len -= 1;
- Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
- }
- }
- }
-
- /// Append an element to a vector.
- ///
- /// # Failure
- ///
- /// Fails if the number of elements in the vector overflows a `uint`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2);
- /// vec.push(3);
- /// assert_eq!(vec, vec!(1, 2, 3));
- /// ```
- #[inline]
- pub fn push(&mut self, value: T) {
- if mem::size_of::<T>() == 0 {
- // zero-size types consume no memory, so we can't rely on the address space running out
- self.len = self.len.checked_add(&1).expect("length overflow");
- unsafe { mem::forget(value); }
- return
- }
- if self.len == self.cap {
- let old_size = self.cap * mem::size_of::<T>();
- let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
- if old_size > size { fail!("capacity overflow") }
- unsafe {
- self.ptr = alloc_or_realloc(self.ptr, size,
- self.cap * mem::size_of::<T>());
- }
- self.cap = max(self.cap, 2) * 2;
- }
-
- unsafe {
- let end = (self.ptr as *T).offset(self.len as int) as *mut T;
- mem::overwrite(&mut *end, value);
- self.len += 1;
- }
- }
-
- /// Appends one element to the vector provided. The vector itself is then
- /// returned for use again.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2);
- /// let vec = vec.append_one(3);
- /// assert_eq!(vec, vec!(1, 2, 3));
- /// ```
- #[inline]
- pub fn append_one(mut self, x: T) -> Vec<T> {
- self.push(x);
- self
- }
-
- /// Shorten a vector, dropping excess elements.
- ///
- /// If `len` is greater than the vector's current length, this has no
- /// effect.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3, 4);
- /// vec.truncate(2);
- /// assert_eq!(vec, vec!(1, 2));
- /// ```
- pub fn truncate(&mut self, len: uint) {
- unsafe {
- // drop any extra elements
- while len < self.len {
- // decrement len before the read(), so a failure on Drop doesn't
- // re-drop the just-failed value.
- self.len -= 1;
- ptr::read(self.as_slice().unsafe_ref(self.len));
- }
- }
- }
-
- /// Work with `self` as a mutable slice.
- ///
- /// # Example
- ///
- /// ```rust
- /// fn foo(slice: &mut [int]) {}
- ///
- /// let mut vec = vec!(1, 2);
- /// foo(vec.as_mut_slice());
- /// ```
- #[inline]
- pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
- unsafe {
- mem::transmute(Slice { data: self.as_mut_ptr() as *T, len: self.len })
- }
- }
-
- /// Creates a consuming iterator, that is, one that moves each
- /// value out of the vector (from start to end). The vector cannot
- /// be used after calling this.
- ///
- /// # Example
- ///
- /// ```rust
- /// let v = vec!("a".to_string(), "b".to_string());
- /// for s in v.move_iter() {
- /// // s has type String, not &String
- /// println!("{}", s);
- /// }
- /// ```
- #[inline]
- pub fn move_iter(self) -> MoveItems<T> {
- unsafe {
- let iter = mem::transmute(self.as_slice().iter());
- let ptr = self.ptr;
- let cap = self.cap;
- mem::forget(self);
- MoveItems { allocation: ptr, cap: cap, iter: iter }
- }
- }
-
-
- /// Sets the length of a vector.
- ///
- /// This will explicitly set the size of the vector, without actually
- /// modifying its buffers, so it is up to the caller to ensure that the
- /// vector is actually the specified size.
- #[inline]
- pub unsafe fn set_len(&mut self, len: uint) {
- self.len = len;
- }
-
- /// Returns a reference to the value at index `index`.
- ///
- /// # Failure
- ///
- /// Fails if `index` is out of bounds
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3);
- /// assert!(vec.get(1) == &2);
- /// ```
- #[inline]
- pub fn get<'a>(&'a self, index: uint) -> &'a T {
- &self.as_slice()[index]
- }
-
- /// Returns a mutable reference to the value at index `index`.
- ///
- /// # Failure
- ///
- /// Fails if `index` is out of bounds
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// *vec.get_mut(1) = 4;
- /// assert_eq!(vec, vec!(1, 4, 3));
- /// ```
- #[inline]
- pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
- &mut self.as_mut_slice()[index]
- }
-
- /// Returns an iterator over references to the elements of the vector in
- /// order.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3);
- /// for num in vec.iter() {
- /// println!("{}", *num);
- /// }
- /// ```
- #[inline]
- pub fn iter<'a>(&'a self) -> Items<'a,T> {
- self.as_slice().iter()
- }
-
-
- /// Returns an iterator over mutable references to the elements of the
- /// vector in order.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// for num in vec.mut_iter() {
- /// *num = 0;
- /// }
- /// ```
- #[inline]
- pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a,T> {
- self.as_mut_slice().mut_iter()
- }
-
- /// Sort the vector, 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`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut v = vec!(5i, 4, 1, 3, 2);
- /// v.sort_by(|a, b| a.cmp(b));
- /// assert_eq!(v, vec!(1, 2, 3, 4, 5));
- ///
- /// // reverse sorting
- /// v.sort_by(|a, b| b.cmp(a));
- /// assert_eq!(v, vec!(5, 4, 3, 2, 1));
- /// ```
- #[inline]
- pub fn sort_by(&mut self, compare: |&T, &T| -> Ordering) {
- self.as_mut_slice().sort_by(compare)
- }
-
- /// Returns a slice of `self` between `start` and `end`.
- ///
- /// # Failure
- ///
- /// Fails when `start` or `end` point outside the bounds of `self`, or when
- /// `start` > `end`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3, 4);
- /// assert!(vec.slice(0, 2) == [1, 2]);
- /// ```
- #[inline]
- pub fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] {
- self.as_slice().slice(start, end)
- }
-
- /// Returns a slice containing all but the first element of the vector.
- ///
- /// # Failure
- ///
- /// Fails when the vector is empty.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3);
- /// assert!(vec.tail() == [2, 3]);
- /// ```
- #[inline]
- pub fn tail<'a>(&'a self) -> &'a [T] {
- self.as_slice().tail()
- }
-
- /// Returns all but the first `n' elements of a vector.
- ///
- /// # Failure
- ///
- /// Fails when there are fewer than `n` elements in the vector.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3, 4);
- /// assert!(vec.tailn(2) == [3, 4]);
- /// ```
- #[inline]
- pub fn tailn<'a>(&'a self, n: uint) -> &'a [T] {
- self.as_slice().tailn(n)
- }
-
- /// Returns a reference to the last element of a vector, or `None` if it is
- /// empty.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3);
- /// assert!(vec.last() == Some(&3));
- /// ```
- #[inline]
- pub fn last<'a>(&'a self) -> Option<&'a T> {
- self.as_slice().last()
- }
-
- /// Returns a mutable reference to the last element of a vector, or `None`
- /// if it is empty.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// *vec.mut_last().unwrap() = 4;
- /// assert_eq!(vec, vec!(1, 2, 4));
- /// ```
- #[inline]
- pub fn mut_last<'a>(&'a mut self) -> Option<&'a mut T> {
- self.as_mut_slice().mut_last()
- }
-
- /// Remove an element from anywhere in the vector and return it, replacing
- /// it with the last element. This does not preserve ordering, but is O(1).
- ///
- /// Returns `None` if `index` is out of bounds.
- ///
- /// # Example
- /// ```rust
- /// let mut v = vec!("foo".to_string(), "bar".to_string(),
- /// "baz".to_string(), "qux".to_string());
- ///
- /// assert_eq!(v.swap_remove(1), Some("bar".to_string()));
- /// assert_eq!(v, vec!("foo".to_string(), "qux".to_string(), "baz".to_string()));
- ///
- /// assert_eq!(v.swap_remove(0), Some("foo".to_string()));
- /// assert_eq!(v, vec!("baz".to_string(), "qux".to_string()));
- ///
- /// assert_eq!(v.swap_remove(2), None);
- /// ```
- #[inline]
- pub fn swap_remove(&mut self, index: uint) -> Option<T> {
- let length = self.len();
- if index < length - 1 {
- self.as_mut_slice().swap(index, length - 1);
- } else if index >= length {
- return None
- }
- self.pop()
- }
-
- /// Prepend an element to the vector.
- ///
- /// # Warning
- ///
- /// This is an O(n) operation as it requires copying every element in the
- /// vector.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// vec.unshift(4);
- /// assert_eq!(vec, vec!(4, 1, 2, 3));
- /// ```
- #[inline]
- pub fn unshift(&mut self, element: T) {
- self.insert(0, element)
- }
-
- /// Removes the first element from a vector and returns it, or `None` if
- /// the vector is empty.
- ///
- /// # Warning
- ///
- /// This is an O(n) operation as it requires copying every element in the
- /// vector.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// assert!(vec.shift() == Some(1));
- /// assert_eq!(vec, vec!(2, 3));
- /// ```
- #[inline]
- pub fn shift(&mut self) -> Option<T> {
- self.remove(0)
- }
-
- /// Insert an element at position `index` within the vector, shifting all
- /// elements after position i one position to the right.
- ///
- /// # Failure
- ///
- /// Fails if `index` is out of bounds of the vector.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3);
- /// vec.insert(1, 4);
- /// assert_eq!(vec, vec!(1, 4, 2, 3));
- /// ```
- pub fn insert(&mut self, index: uint, element: T) {
- let len = self.len();
- assert!(index <= len);
- // space for the new element
- self.reserve(len + 1);
-
- unsafe { // infallible
- // The spot to put the new value
- {
- let p = self.as_mut_ptr().offset(index as int);
- // Shift everything over to make space. (Duplicating the
- // `index`th element into two consecutive places.)
- ptr::copy_memory(p.offset(1), &*p, len - index);
- // Write it in, overwriting the first copy of the `index`th
- // element.
- mem::overwrite(&mut *p, element);
- }
- self.set_len(len + 1);
- }
- }
-
- /// Remove and return the element at position `index` within the vector,
- /// shifting all elements after position `index` one position to the left.
- /// Returns `None` if `i` is out of bounds.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut v = vec!(1, 2, 3);
- /// assert_eq!(v.remove(1), Some(2));
- /// assert_eq!(v, vec!(1, 3));
- ///
- /// assert_eq!(v.remove(4), None);
- /// // v is unchanged:
- /// assert_eq!(v, vec!(1, 3));
- /// ```
- pub fn remove(&mut self, index: uint) -> Option<T> {
- let len = self.len();
- if index < len {
- unsafe { // infallible
- let ret;
- {
- // the place we are taking from.
- let ptr = self.as_mut_ptr().offset(index as int);
- // copy it out, unsafely having a copy of the value on
- // the stack and in the vector at the same time.
- ret = Some(ptr::read(ptr as *T));
-
- // Shift everything down to fill in that spot.
- ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
- }
- self.set_len(len - 1);
- ret
- }
- } else {
- None
- }
- }
-
- /// Takes ownership of the vector `other`, moving all elements into
- /// the current vector. This does not copy any elements, and it is
- /// illegal to use the `other` vector after calling this method
- /// (because it is moved here).
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(box 1);
- /// vec.push_all_move(vec!(box 2, box 3, box 4));
- /// assert_eq!(vec, vec!(box 1, box 2, box 3, box 4));
- /// ```
- pub fn push_all_move(&mut self, other: Vec<T>) {
- self.extend(other.move_iter());
- }
-
- /// Returns a mutable slice of `self` between `start` and `end`.
- ///
- /// # Failure
- ///
- /// Fails when `start` or `end` point outside the bounds of `self`, or when
- /// `start` > `end`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3, 4);
- /// assert!(vec.mut_slice(0, 2) == [1, 2]);
- /// ```
- #[inline]
- pub fn mut_slice<'a>(&'a mut self, start: uint, end: uint)
- -> &'a mut [T] {
- self.as_mut_slice().mut_slice(start, end)
- }
-
- /// Returns a mutable slice of self from `start` to the end of the vec.
- ///
- /// # Failure
- ///
- /// Fails when `start` points outside the bounds of self.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3, 4);
- /// assert!(vec.mut_slice_from(2) == [3, 4]);
- /// ```
- #[inline]
- pub fn mut_slice_from<'a>(&'a mut self, start: uint) -> &'a mut [T] {
- self.as_mut_slice().mut_slice_from(start)
- }
-
- /// Returns a mutable slice of self from the start of the vec to `end`.
- ///
- /// # Failure
- ///
- /// Fails when `end` points outside the bounds of self.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3, 4);
- /// assert!(vec.mut_slice_to(2) == [1, 2]);
- /// ```
- #[inline]
- pub fn mut_slice_to<'a>(&'a mut self, end: uint) -> &'a mut [T] {
- self.as_mut_slice().mut_slice_to(end)
- }
-
- /// Returns a pair of mutable slices that divides the vec 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).
- ///
- /// # Failure
- ///
- /// Fails if `mid > len`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 3, 4, 5, 6);
- ///
- /// // scoped to restrict the lifetime of the borrows
- /// {
- /// let (left, right) = vec.mut_split_at(0);
- /// assert!(left == &mut []);
- /// assert!(right == &mut [1, 2, 3, 4, 5, 6]);
- /// }
- ///
- /// {
- /// let (left, right) = vec.mut_split_at(2);
- /// assert!(left == &mut [1, 2]);
- /// assert!(right == &mut [3, 4, 5, 6]);
- /// }
- ///
- /// {
- /// let (left, right) = vec.mut_split_at(6);
- /// assert!(left == &mut [1, 2, 3, 4, 5, 6]);
- /// assert!(right == &mut []);
- /// }
- /// ```
- #[inline]
- pub fn mut_split_at<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]) {
- self.as_mut_slice().mut_split_at(mid)
- }
-
- /// Reverse the order of elements in a vector, in place.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut v = vec!(1, 2, 3);
- /// v.reverse();
- /// assert_eq!(v, vec!(3, 2, 1));
- /// ```
- #[inline]
- pub fn reverse(&mut self) {
- self.as_mut_slice().reverse()
- }
-
- /// Returns a slice of `self` from `start` to the end of the vec.
- ///
- /// # Failure
- ///
- /// Fails when `start` points outside the bounds of self.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3);
- /// assert!(vec.slice_from(1) == [2, 3]);
- /// ```
- #[inline]
- pub fn slice_from<'a>(&'a self, start: uint) -> &'a [T] {
- self.as_slice().slice_from(start)
- }
-
- /// Returns a slice of self from the start of the vec to `end`.
- ///
- /// # Failure
- ///
- /// Fails when `end` points outside the bounds of self.
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3);
- /// assert!(vec.slice_to(2) == [1, 2]);
- /// ```
- #[inline]
- pub fn slice_to<'a>(&'a self, end: uint) -> &'a [T] {
- self.as_slice().slice_to(end)
- }
-
- /// Returns a slice containing all but the last element of the vector.
- ///
- /// # Failure
- ///
- /// Fails if the vector is empty
- #[inline]
- pub fn init<'a>(&'a self) -> &'a [T] {
- self.slice(0, self.len() - 1)
- }
-
-
- /// Returns an unsafe pointer to the vector's buffer.
- ///
- /// The caller must ensure that the vector outlives the pointer this
- /// function returns, or else it will end up pointing to garbage.
- ///
- /// Modifying the vector may cause its buffer to be reallocated, which
- /// would also make any pointers to it invalid.
- #[inline]
- pub fn as_ptr(&self) -> *T {
- // If we have a 0-sized vector, then the base pointer should not be NULL
- // because an iterator over the slice will attempt to yield the base
- // pointer as the first element in the vector, but this will end up
- // being Some(NULL) which is optimized to None.
- if mem::size_of::<T>() == 0 {
- 1 as *T
- } else {
- self.ptr as *T
- }
- }
-
- /// Returns a mutable unsafe pointer to the vector's buffer.
- ///
- /// The caller must ensure that the vector outlives the pointer this
- /// function returns, or else it will end up pointing to garbage.
- ///
- /// Modifying the vector may cause its buffer to be reallocated, which
- /// would also make any pointers to it invalid.
- #[inline]
- pub fn as_mut_ptr(&mut self) -> *mut T {
- // see above for the 0-size check
- if mem::size_of::<T>() == 0 {
- 1 as *mut T
- } else {
- self.ptr
- }
- }
-
- /// Retains only the elements specified by the predicate.
- ///
- /// In other words, remove all elements `e` such that `f(&e)` returns false.
- /// This method operates in place and preserves the order the retained elements.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1i, 2, 3, 4);
- /// vec.retain(|x| x%2 == 0);
- /// assert_eq!(vec, vec!(2, 4));
- /// ```
- pub fn retain(&mut self, f: |&T| -> bool) {
- let len = self.len();
- let mut del = 0u;
- {
- let v = self.as_mut_slice();
-
- for i in range(0u, len) {
- if !f(&v[i]) {
- del += 1;
- } else if del > 0 {
- v.swap(i-del, i);
- }
- }
- }
- if del > 0 {
- self.truncate(len - del);
- }
- }
-
- /// Expands a vector in place, initializing the new elements to the result of a function.
- ///
- /// The vector is grown by `n` elements. The i-th new element are initialized to the value
- /// returned by `f(i)` where `i` is in the range [0, n).
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(0u, 1);
- /// vec.grow_fn(3, |i| i);
- /// assert_eq!(vec, vec!(0, 1, 0, 1, 2));
- /// ```
- pub fn grow_fn(&mut self, n: uint, f: |uint| -> T) {
- self.reserve_additional(n);
- for i in range(0u, n) {
- self.push(f(i));
- }
- }
-}
-
-impl<T:Ord> Vec<T> {
- /// Sorts the vector in place.
- ///
- /// This sort is `O(n log n)` worst-case and stable, but allocates
- /// approximately `2 * n`, where `n` is the length of `self`.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(3i, 1, 2);
- /// vec.sort();
- /// assert_eq!(vec, vec!(1, 2, 3));
- /// ```
- pub fn sort(&mut self) {
- self.as_mut_slice().sort()
- }
-}
-
-impl<T> Mutable for Vec<T> {
- #[inline]
- fn clear(&mut self) {
- self.truncate(0)
- }
-}
-
-impl<T:PartialEq> Vec<T> {
- /// Return true if a vector contains an element with the given value
- ///
- /// # Example
- ///
- /// ```rust
- /// let vec = vec!(1, 2, 3);
- /// assert!(vec.contains(&1));
- /// ```
- pub fn contains(&self, x: &T) -> bool {
- self.as_slice().contains(x)
- }
-
- /// Remove consecutive repeated elements in the vector.
- ///
- /// If the vector is sorted, this removes all duplicates.
- ///
- /// # Example
- ///
- /// ```rust
- /// let mut vec = vec!(1, 2, 2, 3, 2);
- /// vec.dedup();
- /// assert_eq!(vec, vec!(1, 2, 3, 2));
- /// ```
- pub fn dedup(&mut self) {
- unsafe {
- // Although we have a mutable reference to `self`, we cannot make
- // *arbitrary* changes. The `PartialEq` comparisons could fail, so we
- // must ensure that the vector is in a valid state at all time.
- //
- // The way that we handle this is by using swaps; we iterate
- // over all the elements, swapping as we go so that at the end
- // the elements we wish to keep are in the front, and those we
- // wish to reject are at the back. We can then truncate the
- // vector. This operation is still O(n).
- //
- // Example: We start in this state, where `r` represents "next
- // read" and `w` represents "next_write`.
- //
- // r
- // +---+---+---+---+---+---+
- // | 0 | 1 | 1 | 2 | 3 | 3 |
- // +---+---+---+---+---+---+
- // w
- //
- // Comparing self[r] against self[w-1], this is not a duplicate, so
- // we swap self[r] and self[w] (no effect as r==w) and then increment both
- // r and w, leaving us with:
- //
- // r
- // +---+---+---+---+---+---+
- // | 0 | 1 | 1 | 2 | 3 | 3 |
- // +---+---+---+---+---+---+
- // w
- //
- // Comparing self[r] against self[w-1], this value is a duplicate,
- // so we increment `r` but leave everything else unchanged:
- //
- // r
- // +---+---+---+---+---+---+
- // | 0 | 1 | 1 | 2 | 3 | 3 |
- // +---+---+---+---+---+---+
- // w
- //
- // Comparing self[r] against self[w-1], this is not a duplicate,
- // so swap self[r] and self[w] and advance r and w:
- //
- // r
- // +---+---+---+---+---+---+
- // | 0 | 1 | 2 | 1 | 3 | 3 |
- // +---+---+---+---+---+---+
- // w
- //
- // Not a duplicate, repeat:
- //
- // r
- // +---+---+---+---+---+---+
- // | 0 | 1 | 2 | 3 | 1 | 3 |
- // +---+---+---+---+---+---+
- // w
- //
- // Duplicate, advance r. End of vec. Truncate to w.
-
- let ln = self.len();
- if ln < 1 { return; }
-
- // Avoid bounds checks by using unsafe pointers.
- let p = self.as_mut_slice().as_mut_ptr();
- let mut r = 1;
- let mut w = 1;
-
- while r < ln {
- let p_r = p.offset(r as int);
- let p_wm1 = p.offset((w - 1) as int);
- if *p_r != *p_wm1 {
- if r != w {
- let p_w = p_wm1.offset(1);
- mem::swap(&mut *p_r, &mut *p_w);
- }
- w += 1;
- }
- r += 1;
- }
-
- self.truncate(w);
- }
- }
-}
-
-impl<T> Vector<T> for Vec<T> {
- /// Work with `self` as a slice.
- ///
- /// # Example
- ///
- /// ```rust
- /// fn foo(slice: &[int]) {}
- ///
- /// let vec = vec!(1, 2);
- /// foo(vec.as_slice());
- /// ```
- #[inline]
- fn as_slice<'a>(&'a self) -> &'a [T] {
- unsafe { mem::transmute(Slice { data: self.as_ptr(), len: self.len }) }
- }
-}
-
-impl<T: Clone, V: Vector<T>> Add<V, Vec<T>> for Vec<T> {
- #[inline]
- fn add(&self, rhs: &V) -> Vec<T> {
- let mut res = Vec::with_capacity(self.len() + rhs.as_slice().len());
- res.push_all(self.as_slice());
- res.push_all(rhs.as_slice());
- res
- }
-}
-
-#[unsafe_destructor]
-impl<T> Drop for Vec<T> {
- fn drop(&mut self) {
- // This is (and should always remain) a no-op if the fields are
- // zeroed (when moving out, because of #[unsafe_no_drop_flag]).
- if self.cap != 0 {
- unsafe {
- for x in self.as_mut_slice().iter() {
- ptr::read(x);
- }
- dealloc(self.ptr, self.cap)
- }
- }
- }
-}
-
-impl<T> Default for Vec<T> {
- fn default() -> Vec<T> {
- Vec::new()
- }
-}
-
-impl<T:fmt::Show> fmt::Show for Vec<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.as_slice().fmt(f)
- }
-}
-
-/// An iterator that moves out of a vector.
-pub struct MoveItems<T> {
- allocation: *mut T, // the block of memory allocated for the vector
- cap: uint, // the capacity of the vector
- iter: Items<'static, T>
-}
-
-impl<T> Iterator<T> for MoveItems<T> {
- #[inline]
- fn next(&mut self) -> Option<T> {
- unsafe {
- self.iter.next().map(|x| ptr::read(x))
- }
- }
-
- #[inline]
- fn size_hint(&self) -> (uint, Option<uint>) {
- self.iter.size_hint()
- }
-}
-
-impl<T> DoubleEndedIterator<T> for MoveItems<T> {
- #[inline]
- fn next_back(&mut self) -> Option<T> {
- unsafe {
- self.iter.next_back().map(|x| ptr::read(x))
- }
- }
-}
-
-#[unsafe_destructor]
-impl<T> Drop for MoveItems<T> {
- fn drop(&mut self) {
- // destroy the remaining elements
- if self.cap != 0 {
- for _x in *self {}
- unsafe {
- dealloc(self.allocation, self.cap);
- }
- }
- }
-}
-
-/**
- * Convert an iterator of pairs into a pair of vectors.
- *
- * Returns a tuple containing two vectors where the i-th element of the first
- * vector contains the first element of the i-th tuple of the input iterator,
- * and the i-th element of the second vector contains the second element
- * of the i-th tuple of the input iterator.
- */
-pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
- let (lo, _) = iter.size_hint();
- let mut ts = Vec::with_capacity(lo);
- let mut us = Vec::with_capacity(lo);
- for (t, u) in iter {
- ts.push(t);
- us.push(u);
- }
- (ts, us)
-}
-
-/// Mechanism to convert from a `Vec<T>` to a `[T]`.
-///
-/// In a post-DST world this will be used to convert to any `Ptr<[T]>`.
-///
-/// This could be implemented on more types than just pointers to vectors, but
-/// the recommended approach for those types is to implement `FromIterator`.
-// FIXME(#12938): Update doc comment when DST lands
-pub trait FromVec<T> {
- /// Convert a `Vec<T>` into the receiver type.
- fn from_vec(v: Vec<T>) -> Self;
-}
-
-impl<T> FromVec<T> for ~[T] {
- fn from_vec(mut v: Vec<T>) -> ~[T] {
- let len = v.len();
- let data_size = len.checked_mul(&mem::size_of::<T>());
- let data_size = data_size.expect("overflow in from_vec()");
- let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
- let size = size.expect("overflow in from_vec()");
-
- // In a post-DST world, we can attempt to reuse the Vec allocation by calling
- // shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
- // diffrent than what we're doing manually here.
-
- let vp = v.as_mut_ptr();
-
- unsafe {
- let ret = allocate(size, 8) as *mut RawVec<()>;
-
- let a_size = mem::size_of::<T>();
- let a_size = if a_size == 0 {1} else {a_size};
- (*ret).fill = len * a_size;
- (*ret).alloc = len * a_size;
-
- ptr::copy_nonoverlapping_memory(&mut (*ret).data as *mut _ as *mut u8,
- vp as *u8, data_size);
-
- // we've transferred ownership of the contents from v, but we can't drop it
- // as it still needs to free its own allocation.
- v.set_len(0);
-
- mem::transmute(ret)
- }
- }
-}
-
-/// Unsafe operations
-pub mod raw {
- use super::Vec;
- use ptr;
-
- /// Constructs a vector from an unsafe pointer to a buffer.
- ///
- /// The elements of the buffer are copied into the vector without cloning,
- /// as if `ptr::read()` were called on them.
- #[inline]
- pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> Vec<T> {
- let mut dst = Vec::with_capacity(elts);
- dst.set_len(elts);
- ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
- dst
- }
-}
-
-
-#[cfg(test)]
-mod tests {
- use prelude::*;
- use mem::size_of;
- use kinds::marker;
- use super::{unzip, raw, FromVec};
-
- #[test]
- fn test_small_vec_struct() {
- assert!(size_of::<Vec<u8>>() == size_of::<uint>() * 3);
- }
-
- #[test]
- fn test_double_drop() {
- struct TwoVec<T> {
- x: Vec<T>,
- y: Vec<T>
- }
-
- struct DropCounter<'a> {
- count: &'a mut int
- }
-
- #[unsafe_destructor]
- impl<'a> Drop for DropCounter<'a> {
- fn drop(&mut self) {
- *self.count += 1;
- }
- }
-
- let mut count_x @ mut count_y = 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_additional() {
- let mut v = Vec::new();
- assert_eq!(v.capacity(), 0);
-
- v.reserve_additional(2);
- assert!(v.capacity() >= 2);
-
- for i in range(0, 16) {
- v.push(i);
- }
-
- assert!(v.capacity() >= 16);
- v.reserve_additional(16);
- assert!(v.capacity() >= 32);
-
- v.push(16);
-
- v.reserve_additional(16);
- assert!(v.capacity() >= 33)
- }
-
- #[test]
- fn test_extend() {
- let mut v = Vec::new();
- let mut w = Vec::new();
-
- v.extend(range(0, 3));
- for i in range(0, 3) { w.push(i) }
-
- assert_eq!(v, w);
-
- v.extend(range(3, 10));
- for i in range(3, 10) { w.push(i) }
-
- assert_eq!(v, w);
- }
-
- #[test]
- fn test_mut_slice_from() {
- let mut values = Vec::from_slice([1u8,2,3,4,5]);
- {
- let slice = values.mut_slice_from(2);
- assert!(slice == [3, 4, 5]);
- for p in slice.mut_iter() {
- *p += 2;
- }
- }
-
- assert!(values.as_slice() == [1, 2, 5, 6, 7]);
- }
-
- #[test]
- fn test_mut_slice_to() {
- let mut values = Vec::from_slice([1u8,2,3,4,5]);
- {
- let slice = values.mut_slice_to(2);
- assert!(slice == [1, 2]);
- for p in slice.mut_iter() {
- *p += 1;
- }
- }
-
- assert!(values.as_slice() == [2, 3, 3, 4, 5]);
- }
-
- #[test]
- fn test_mut_split_at() {
- let mut values = Vec::from_slice([1u8,2,3,4,5]);
- {
- let (left, right) = values.mut_split_at(2);
- assert!(left.slice(0, left.len()) == [1, 2]);
- for p in left.mut_iter() {
- *p += 1;
- }
-
- assert!(right.slice(0, right.len()) == [3, 4, 5]);
- for p in right.mut_iter() {
- *p += 2;
- }
- }
-
- assert!(values == Vec::from_slice([2u8, 3, 5, 6, 7]));
- }
-
- #[test]
- fn test_clone() {
- let v: Vec<int> = 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 1, box 2, box 3);
- let two = 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_grow_fn() {
- let mut v = Vec::from_slice([0u, 1]);
- v.grow_fn(3, |i| i);
- assert!(v == Vec::from_slice([0u, 1, 0, 1, 2]));
- }
-
- #[test]
- fn test_retain() {
- let mut vec = Vec::from_slice([1u, 2, 3, 4]);
- vec.retain(|x| x%2 == 0);
- assert!(vec == Vec::from_slice([2u, 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().len(), 0);
- v.push(());
- assert_eq!(v.iter().len(), 1);
- v.push(());
- assert_eq!(v.iter().len(), 2);
-
- for &() in v.iter() {}
-
- assert_eq!(v.mut_iter().len(), 2);
- v.push(());
- assert_eq!(v.mut_iter().len(), 3);
- v.push(());
- assert_eq!(v.mut_iter().len(), 4);
-
- for &() in v.mut_iter() {}
- unsafe { v.set_len(0); }
- assert_eq!(v.mut_iter().len(), 0);
- }
-
- #[test]
- fn test_partition() {
- assert_eq!(vec![].partition(|x: &int| *x < 3), (vec![], vec![]));
- assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
- assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
- assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
- }
-
- #[test]
- fn test_partitioned() {
- assert_eq!(vec![].partitioned(|x: &int| *x < 3), (vec![], vec![]))
- assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
- assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
- assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
- }
-
- #[test]
- fn test_zip_unzip() {
- let z1 = vec![(1, 4), (2, 5), (3, 6)];
-
- let (left, right) = unzip(z1.iter().map(|&x| x));
-
- let (left, right) = (left.as_slice(), right.as_slice());
- 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 = raw::from_buf(ptr, 3u);
- assert_eq!(b, vec![1, 2, 3]);
-
- // Test on-heap copy-from-buf.
- let c = box [1, 2, 3, 4, 5];
- let ptr = c.as_ptr();
- let d = raw::from_buf(ptr, 5u);
- assert_eq!(d, vec![1, 2, 3, 4, 5]);
- }
- }
-
- #[test]
- fn test_from_vec() {
- let a = vec![1u, 2, 3];
- let b: ~[uint] = FromVec::from_vec(a);
- assert_eq!(b.as_slice(), &[1u, 2, 3]);
-
- let a = vec![];
- let b: ~[u8] = FromVec::from_vec(a);
- assert_eq!(b.as_slice(), &[]);
-
- let a = vec!["one".to_string(), "two".to_string()];
- let b: ~[String] = FromVec::from_vec(a);
- assert_eq!(b.as_slice(), &["one".to_string(), "two".to_string()]);
-
- struct Foo {
- x: uint,
- nocopy: marker::NoCopy
- }
-
- let a = vec![Foo{x: 42, nocopy: marker::NoCopy}, Foo{x: 84, nocopy: marker::NoCopy}];
- let b: ~[Foo] = FromVec::from_vec(a);
- assert_eq!(b.len(), 2);
- assert_eq!(b[0].x, 42);
- assert_eq!(b[1].x, 84);
- }
-
- #[test]
- fn test_vec_truncate_drop() {
- static mut drops: uint = 0;
- struct Elem(int);
- 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_fail]
- fn test_vec_truncate_fail() {
- struct BadElem(int);
- impl Drop for BadElem {
- fn drop(&mut self) {
- let BadElem(ref mut x) = *self;
- if *x == 0xbadbeef {
- fail!("BadElem failure: 0xbadbeef")
- }
- }
- }
-
- let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
- v.truncate(0);
- }
-}