diff options
| author | bors <bors@rust-lang.org> | 2014-05-08 21:01:42 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-05-08 21:01:42 -0700 |
| commit | a990920c6fff9b762c3d0968ff0a5fdcce6d2b39 (patch) | |
| tree | 8b4cb2edb2e48660ca6e6c0f6a660951f00c1e02 /src/libstd | |
| parent | c0a25e4fdc1fcdde8378b4177a6f06c58001a3be (diff) | |
| parent | dc30c483810ca0ee3641f4bab8e6f2a44a883fee (diff) | |
| download | rust-a990920c6fff9b762c3d0968ff0a5fdcce6d2b39.tar.gz rust-a990920c6fff9b762c3d0968ff0a5fdcce6d2b39.zip | |
auto merge of #13963 : kballard/rust/remove_owned_vec_from_iterator, r=pcwalton
With `~[T]` no longer growable, the `FromIterator` impl for `~[T]` doesn't make much sense. Not only that, but nearly everywhere it is used is to convert from a `Vec<T>` into a `~[T]`, for the sake of maintaining existing APIs. This turns out to be a performance loss, as it means every API that returns `~[T]`, even a supposedly non-copying one, is in fact doing extra allocations and memcpy's. Even `&[T].to_owned()` is going through `Vec<T>` first. Remove the `FromIterator` impl for `~[T]`, and adjust all the APIs that relied on it to start using `Vec<T>` instead. This includes rewriting `&[T].to_owned()` to be more efficient, among other performance wins. Also add a new mechanism to go from `Vec<T>` -> `~[T]`, just in case anyone truly needs that, using the new trait `FromVec`. [breaking-change]
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/ascii.rs | 87 | ||||
| -rw-r--r-- | src/libstd/io/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/io/net/addrinfo.rs | 6 | ||||
| -rw-r--r-- | src/libstd/io/process.rs | 4 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/i16.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/i32.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/i64.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/i8.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/int.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/int_macros.rs | 5 | ||||
| -rw-r--r-- | src/libstd/num/strconv.rs | 21 | ||||
| -rw-r--r-- | src/libstd/num/u16.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/u32.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/u64.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/u8.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/uint.rs | 3 | ||||
| -rw-r--r-- | src/libstd/num/uint_macros.rs | 5 | ||||
| -rw-r--r-- | src/libstd/os.rs | 48 | ||||
| -rw-r--r-- | src/libstd/rt/args.rs | 43 | ||||
| -rw-r--r-- | src/libstd/rt/rtio.rs | 4 | ||||
| -rw-r--r-- | src/libstd/slice.rs | 287 | ||||
| -rw-r--r-- | src/libstd/str.rs | 189 | ||||
| -rw-r--r-- | src/libstd/strbuf.rs | 7 | ||||
| -rw-r--r-- | src/libstd/sync/arc.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sync/deque.rs | 4 | ||||
| -rw-r--r-- | src/libstd/unstable/dynamic_lib.rs | 9 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 168 |
28 files changed, 510 insertions, 418 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 5b4400593b4..f45ec8a6742 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -13,7 +13,7 @@ use to_str::{IntoStr}; use str; use str::Str; -use str::StrSlice; +use str::{StrAllocating, StrSlice}; use str::OwnedStr; use container::Container; use cast; @@ -217,14 +217,14 @@ pub trait OwnedAsciiCast { /// Take ownership and cast to an ascii vector. Fail on non-ASCII input. #[inline] - fn into_ascii(self) -> ~[Ascii] { + fn into_ascii(self) -> Vec<Ascii> { assert!(self.is_ascii()); unsafe {self.into_ascii_nocheck()} } /// Take ownership and cast to an ascii vector. Return None on non-ASCII input. #[inline] - fn into_ascii_opt(self) -> Option<~[Ascii]> { + fn into_ascii_opt(self) -> Option<Vec<Ascii>> { if self.is_ascii() { Some(unsafe { self.into_ascii_nocheck() }) } else { @@ -234,7 +234,7 @@ pub trait OwnedAsciiCast { /// Take ownership and cast to an ascii vector. /// Does not perform validation checks. - unsafe fn into_ascii_nocheck(self) -> ~[Ascii]; + unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>; } impl OwnedAsciiCast for ~[u8] { @@ -244,8 +244,8 @@ impl OwnedAsciiCast for ~[u8] { } #[inline] - unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { - cast::transmute(self) + unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> { + cast::transmute(Vec::from_slice(self.as_slice())) } } @@ -256,7 +256,20 @@ impl OwnedAsciiCast for ~str { } #[inline] - unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { + unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> { + let v: ~[u8] = cast::transmute(self); + v.into_ascii_nocheck() + } +} + +impl OwnedAsciiCast for Vec<u8> { + #[inline] + fn is_ascii(&self) -> bool { + self.as_slice().is_ascii() + } + + #[inline] + unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> { cast::transmute(self) } } @@ -268,10 +281,10 @@ pub trait AsciiStr { fn as_str_ascii<'a>(&'a self) -> &'a str; /// Convert to vector representing a lower cased ascii string. - fn to_lower(&self) -> ~[Ascii]; + fn to_lower(&self) -> Vec<Ascii>; /// Convert to vector representing a upper cased ascii string. - fn to_upper(&self) -> ~[Ascii]; + fn to_upper(&self) -> Vec<Ascii>; /// Compares two Ascii strings ignoring case. fn eq_ignore_case(self, other: &[Ascii]) -> bool; @@ -284,12 +297,12 @@ impl<'a> AsciiStr for &'a [Ascii] { } #[inline] - fn to_lower(&self) -> ~[Ascii] { + fn to_lower(&self) -> Vec<Ascii> { self.iter().map(|a| a.to_lower()).collect() } #[inline] - fn to_upper(&self) -> ~[Ascii] { + fn to_upper(&self) -> Vec<Ascii> { self.iter().map(|a| a.to_upper()).collect() } @@ -309,19 +322,21 @@ impl IntoStr for ~[Ascii] { impl IntoStr for Vec<Ascii> { #[inline] fn into_str(self) -> ~str { - let v: ~[Ascii] = self.move_iter().collect(); - unsafe { cast::transmute(v) } + unsafe { + let s: &str = cast::transmute(self.as_slice()); + s.to_owned() + } } } -/// Trait to convert to an owned byte array by consuming self +/// Trait to convert to an owned byte vector by consuming self pub trait IntoBytes { - /// Converts to an owned byte array by consuming self - fn into_bytes(self) -> ~[u8]; + /// Converts to an owned byte vector by consuming self + fn into_bytes(self) -> Vec<u8>; } -impl IntoBytes for ~[Ascii] { - fn into_bytes(self) -> ~[u8] { +impl IntoBytes for Vec<Ascii> { + fn into_bytes(self) -> Vec<u8> { unsafe { cast::transmute(self) } } } @@ -404,9 +419,11 @@ unsafe fn str_map_bytes(string: ~str, map: &'static [u8]) -> ~str { #[inline] unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> ~str { - let bytes = string.bytes().map(|b| map[b as uint]).collect::<~[_]>(); - - str::raw::from_utf8_owned(bytes) + let mut s = string.to_owned(); + for b in str::raw::as_owned_vec(&mut s).mut_iter() { + *b = map[*b as uint]; + } + s } static ASCII_LOWER_MAP: &'static [u8] = &[ @@ -492,7 +509,6 @@ mod tests { macro_rules! v2ascii ( ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]); (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]); - (~[$($e:expr),*]) => (box [$(Ascii{chr:$e}),*]); ) macro_rules! vec2ascii ( @@ -556,20 +572,17 @@ mod tests { #[test] fn test_ascii_vec_ng() { - assert_eq!(Vec::from_slice("abCDef&?#".to_ascii().to_lower()).into_str(), - "abcdef&?#".to_owned()); - assert_eq!(Vec::from_slice("abCDef&?#".to_ascii().to_upper()).into_str(), - "ABCDEF&?#".to_owned()); - assert_eq!(Vec::from_slice("".to_ascii().to_lower()).into_str(), "".to_owned()); - assert_eq!(Vec::from_slice("YMCA".to_ascii().to_lower()).into_str(), "ymca".to_owned()); - assert_eq!(Vec::from_slice("abcDEFxyz:.;".to_ascii().to_upper()).into_str(), - "ABCDEFXYZ:.;".to_owned()); + assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), "abcdef&?#".to_owned()); + assert_eq!("abCDef&?#".to_ascii().to_upper().into_str(), "ABCDEF&?#".to_owned()); + assert_eq!("".to_ascii().to_lower().into_str(), "".to_owned()); + assert_eq!("YMCA".to_ascii().to_lower().into_str(), "ymca".to_owned()); + assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_str(), "ABCDEFXYZ:.;".to_owned()); } #[test] fn test_owned_ascii_vec() { - assert_eq!(("( ;".to_owned()).into_ascii(), v2ascii!(~[40, 32, 59])); - assert_eq!((box [40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59])); + assert_eq!(("( ;".to_owned()).into_ascii(), vec2ascii![40, 32, 59]); + assert_eq!((box [40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]); } #[test] @@ -580,13 +593,13 @@ mod tests { #[test] fn test_ascii_into_str() { - assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), "( ;".to_owned()); + assert_eq!(vec2ascii![40, 32, 59].into_str(), "( ;".to_owned()); assert_eq!(vec2ascii!(40, 32, 59).into_str(), "( ;".to_owned()); } #[test] fn test_ascii_to_bytes() { - assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), box [40u8, 32u8, 59u8]); + assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]); } #[test] #[should_fail] @@ -625,10 +638,10 @@ mod tests { assert_eq!(v.to_ascii_opt(), Some(v2)); assert_eq!("zoä华".to_ascii_opt(), None); - assert_eq!((box [40u8, 32u8, 59u8]).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59]))); - assert_eq!((box [127u8, 128u8, 255u8]).into_ascii_opt(), None); + assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii_opt(), Some(vec2ascii![40, 32, 59])); + assert_eq!((vec![127u8, 128u8, 255u8]).into_ascii_opt(), None); - assert_eq!(("( ;".to_owned()).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59]))); + assert_eq!(("( ;".to_owned()).into_ascii_opt(), Some(vec2ascii![40, 32, 59])); assert_eq!(("zoä华".to_owned()).into_ascii_opt(), None); } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index a89af05c50a..4a53a064610 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -76,7 +76,7 @@ Some examples of obvious things you might want to do let path = Path::new("message.txt"); let mut file = BufferedReader::new(File::open(&path)); - let lines: ~[~str] = file.lines().map(|x| x.unwrap()).collect(); + let lines: Vec<~str> = file.lines().map(|x| x.unwrap()).collect(); ``` * Make a simple TCP client connection and request diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 4006665e886..879c66e0769 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -24,7 +24,7 @@ use io::IoResult; use io::net::ip::{SocketAddr, IpAddr}; use option::{Option, Some, None}; use rt::rtio::{IoFactory, LocalIo}; -use slice::OwnedVector; +use vec::Vec; /// Hints to the types of sockets that are desired when looking up hosts pub enum SocketType { @@ -73,7 +73,7 @@ pub struct Info { /// Easy name resolution. Given a hostname, returns the list of IP addresses for /// that hostname. -pub fn get_host_addresses(host: &str) -> IoResult<~[IpAddr]> { +pub fn get_host_addresses(host: &str) -> IoResult<Vec<IpAddr>> { lookup(Some(host), None, None).map(|a| a.move_iter().map(|i| i.address.ip).collect()) } @@ -90,7 +90,7 @@ pub fn get_host_addresses(host: &str) -> IoResult<~[IpAddr]> { /// FIXME: this is not public because the `Hint` structure is not ready for public /// consumption just yet. fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>) - -> IoResult<~[Info]> { + -> IoResult<Vec<Info>> { LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint)) } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 74f6944f102..3babef6126e 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -69,7 +69,7 @@ pub struct Process { /// Extra I/O handles as configured by the original `ProcessConfig` when /// this process was created. This is by default empty. - pub extra_io: ~[Option<io::PipeStream>], + pub extra_io: Vec<Option<io::PipeStream>>, } /// This configuration describes how a new process should be spawned. A blank @@ -418,7 +418,7 @@ impl Drop for Process { drop(self.stdin.take()); drop(self.stdout.take()); drop(self.stderr.take()); - drop(mem::replace(&mut self.extra_io, box [])); + drop(mem::replace(&mut self.extra_io, Vec::new())); self.wait(); } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 72d41ae1dd2..8a783b6f378 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -278,4 +278,7 @@ mod std { pub use ty; pub use unstable; pub use vec; + + // The test runner requires std::slice::Vector, so re-export std::slice just for it. + #[cfg(test)] pub use slice; } diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index 4bd2ba07634..d8f1c108b74 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -11,11 +11,10 @@ //! Operations and constants for signed 16-bits integers (`i16` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::i16::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 3c3acfae3c0..9cc8981fc13 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -11,11 +11,10 @@ //! Operations and constants for signed 32-bits integers (`i32` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::i32::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index ad0fe1c08ef..4f7fe32cc70 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -11,11 +11,10 @@ //! Operations and constants for signed 64-bits integers (`i64` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::i64::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index bd40a2c53b6..bea315d8683 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -11,11 +11,10 @@ //! Operations and constants for signed 8-bits integers (`i8` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::i8::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index d9552ee3340..d6a7fd1660b 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -11,11 +11,10 @@ //! Operations and constants for architecture-sized signed integers (`int` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::int::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 8a7bea46585..fcdb63f5ad5 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -77,13 +77,16 @@ impl ToStrRadix for $T { /// Convert to a string in a given base. #[inline] fn to_str_radix(&self, radix: uint) -> ~str { + use slice::Vector; + use str::StrAllocating; + let mut buf = ::vec::Vec::new(); strconv::int_to_str_bytes_common(*self, radix, strconv::SignNeg, |i| { buf.push(i); }); // We know we generated valid utf-8, so we don't need to go through that // check. - unsafe { str::raw::from_utf8_owned(buf.move_iter().collect()) } + unsafe { str::raw::from_utf8(buf.as_slice()).to_owned() } } } diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 8861597bb4c..4769b17fb2b 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -19,11 +19,10 @@ use num::{Float, FPNaN, FPInfinite, ToPrimitive}; use num; use ops::{Add, Sub, Mul, Div, Rem, Neg}; use option::{None, Option, Some}; -use slice::OwnedVector; use slice::{CloneableVector, ImmutableVector, MutableVector}; use std::cmp::{Ord, Eq}; -use str::{StrSlice}; -use str; +use str::{StrAllocating, StrSlice}; +use strbuf::StrBuf; use vec::Vec; /// A flag that specifies whether to use exponential (scientific) notation. @@ -262,7 +261,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+ Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>( num: T, radix: uint, negative_zero: bool, sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool - ) -> (~[u8], bool) { + ) -> (Vec<u8>, bool) { assert!(2 <= radix && radix <= 36); match exp_format { ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' @@ -278,17 +277,17 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+ let _1: T = One::one(); match num.classify() { - FPNaN => { return ("NaN".as_bytes().to_owned(), true); } + FPNaN => { return (Vec::from_slice("NaN".as_bytes()), true); } FPInfinite if num > _0 => { return match sign { - SignAll => ("+inf".as_bytes().to_owned(), true), - _ => ("inf".as_bytes().to_owned(), true) + SignAll => (Vec::from_slice("+inf".as_bytes()), true), + _ => (Vec::from_slice("inf".as_bytes()), true) }; } FPInfinite if num < _0 => { return match sign { - SignNone => ("inf".as_bytes().to_owned(), true), - _ => ("-inf".as_bytes().to_owned(), true), + SignNone => (Vec::from_slice("inf".as_bytes()), true), + _ => (Vec::from_slice("-inf".as_bytes()), true), }; } _ => {} @@ -483,7 +482,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+ } } - (buf.move_iter().collect(), false) + (buf, false) } /** @@ -498,7 +497,7 @@ pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+ ) -> (~str, bool) { let (bytes, special) = float_to_str_bytes_common(num, radix, negative_zero, sign, digits, exp_format, exp_capital); - (str::from_utf8_owned(bytes).unwrap(), special) + (StrBuf::from_utf8(bytes).unwrap().into_owned(), special) } // Some constants for from_str_bytes_common's input validation, diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index dd6a838df9b..5c93ca6c36b 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -11,11 +11,10 @@ //! Operations and constants for unsigned 16-bits integers (`u16` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::u16::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index bb05938969d..436eae7cd14 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -11,11 +11,10 @@ //! Operations and constants for unsigned 32-bits integers (`u32` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::u32::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index f38806e1527..c654d6fbe31 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -11,11 +11,10 @@ //! Operations and constants for unsigned 64-bits integer (`u64` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::u64::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index 87fed563a15..7051b9191be 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -11,11 +11,10 @@ //! Operations and constants for unsigned 8-bits integers (`u8` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::u8::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 61ab97e86b8..d1c3e96b2c9 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -11,11 +11,10 @@ //! Operations and constants for architecture-sized unsigned integers (`uint` type) use from_str::FromStr; -use iter::Iterator; use num::{ToStrRadix, FromStrRadix}; use num::strconv; use option::Option; -use slice::{ImmutableVector, OwnedVector}; +use slice::ImmutableVector; use str; pub use core::uint::{BITS, BYTES, MIN, MAX}; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 3e64c171613..0795238a49c 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -78,13 +78,16 @@ impl ToStrRadix for $T { /// Convert to a string in a given base. #[inline] fn to_str_radix(&self, radix: uint) -> ~str { + use slice::Vector; + use str::StrAllocating; + let mut buf = ::vec::Vec::new(); strconv::int_to_str_bytes_common(*self, radix, strconv::SignNone, |i| { buf.push(i); }); // We know we generated valid utf-8, so we don't need to go through that // check. - unsafe { str::raw::from_utf8_owned(buf.move_iter().collect()) } + unsafe { str::raw::from_utf8(buf.as_slice()).to_owned() } } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 809757aaf4d..66143b40d52 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -169,7 +169,7 @@ fn with_env_lock<T>(f: || -> T) -> T { /// /// Invalid UTF-8 bytes are replaced with \uFFFD. See `str::from_utf8_lossy()` /// for details. -pub fn env() -> ~[(~str,~str)] { +pub fn env() -> Vec<(~str,~str)> { env_as_bytes().move_iter().map(|(k,v)| { let k = str::from_utf8_lossy(k).into_owned(); let v = str::from_utf8_lossy(v).into_owned(); @@ -179,7 +179,7 @@ pub fn env() -> ~[(~str,~str)] { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. -pub fn env_as_bytes() -> ~[(~[u8],~[u8])] { +pub fn env_as_bytes() -> Vec<(~[u8],~[u8])> { unsafe { #[cfg(windows)] unsafe fn get_env_pairs() -> Vec<~[u8]> { @@ -224,16 +224,16 @@ pub fn env_as_bytes() -> ~[(~[u8],~[u8])] { fn env_convert(input: Vec<~[u8]>) -> Vec<(~[u8], ~[u8])> { let mut pairs = Vec::new(); for p in input.iter() { - let vs: ~[&[u8]] = p.splitn(1, |b| *b == '=' as u8).collect(); - let key = vs[0].to_owned(); - let val = if vs.len() < 2 { box [] } else { vs[1].to_owned() }; + let mut it = p.splitn(1, |b| *b == '=' as u8); + let key = it.next().unwrap().to_owned(); + let val = it.next().unwrap_or(&[]).to_owned(); pairs.push((key, val)); } pairs } with_env_lock(|| { let unparsed_environ = get_env_pairs(); - env_convert(unparsed_environ).move_iter().collect() + env_convert(unparsed_environ) }) } } @@ -416,7 +416,7 @@ pub fn dll_filename(base: &str) -> ~str { pub fn self_exe_name() -> Option<Path> { #[cfg(target_os = "freebsd")] - fn load_self() -> Option<~[u8]> { + fn load_self() -> Option<Vec<u8>> { unsafe { use libc::funcs::bsd44::*; use libc::consts::os::extra::*; @@ -436,23 +436,23 @@ pub fn self_exe_name() -> Option<Path> { if err != 0 { return None; } if sz == 0 { return None; } v.set_len(sz as uint - 1); // chop off trailing NUL - Some(v.move_iter().collect()) + Some(v) } } #[cfg(target_os = "linux")] #[cfg(target_os = "android")] - fn load_self() -> Option<~[u8]> { + fn load_self() -> Option<Vec<u8>> { use std::io; match io::fs::readlink(&Path::new("/proc/self/exe")) { - Ok(path) => Some(path.as_vec().to_owned()), + Ok(path) => Some(path.into_vec()), Err(..) => None } } #[cfg(target_os = "macos")] - fn load_self() -> Option<~[u8]> { + fn load_self() -> Option<Vec<u8>> { unsafe { use libc::funcs::extra::_NSGetExecutablePath; let mut sz: u32 = 0; @@ -462,19 +462,19 @@ pub fn self_exe_name() -> Option<Path> { let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); if err != 0 { return None; } v.set_len(sz as uint - 1); // chop off trailing NUL - Some(v.move_iter().collect()) + Some(v) } } #[cfg(windows)] - fn load_self() -> Option<~[u8]> { + fn load_self() -> Option<Vec<u8>> { use str::OwnedStr; unsafe { use os::win32::fill_utf16_buf_and_decode; fill_utf16_buf_and_decode(|buf, sz| { libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz) - }).map(|s| s.into_bytes()) + }).map(|s| s.into_strbuf().into_bytes()) } } @@ -789,12 +789,12 @@ pub fn get_exit_status() -> int { } #[cfg(target_os = "macos")] -unsafe fn load_argc_and_argv(argc: int, argv: **c_char) -> ~[~[u8]] { +unsafe fn load_argc_and_argv(argc: int, argv: **c_char) -> Vec<~[u8]> { use c_str::CString; Vec::from_fn(argc as uint, |i| { CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_owned() - }).move_iter().collect() + }) } /** @@ -803,7 +803,7 @@ unsafe fn load_argc_and_argv(argc: int, argv: **c_char) -> ~[~[u8]] { * Returns a list of the command line arguments. */ #[cfg(target_os = "macos")] -fn real_args_as_bytes() -> ~[~[u8]] { +fn real_args_as_bytes() -> Vec<~[u8]> { unsafe { let (argc, argv) = (*_NSGetArgc() as int, *_NSGetArgv() as **c_char); @@ -814,7 +814,7 @@ fn real_args_as_bytes() -> ~[~[u8]] { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] -fn real_args_as_bytes() -> ~[~[u8]] { +fn real_args_as_bytes() -> Vec<~[u8]> { use rt; match rt::args::clone() { @@ -824,12 +824,12 @@ fn real_args_as_bytes() -> ~[~[u8]] { } #[cfg(not(windows))] -fn real_args() -> ~[~str] { +fn real_args() -> Vec<~str> { real_args_as_bytes().move_iter().map(|v| str::from_utf8_lossy(v).into_owned()).collect() } #[cfg(windows)] -fn real_args() -> ~[~str] { +fn real_args() -> Vec<~str> { use slice; use option::Expect; @@ -855,11 +855,11 @@ fn real_args() -> ~[~str] { LocalFree(szArgList as *c_void); } - return args.move_iter().collect(); + return args } #[cfg(windows)] -fn real_args_as_bytes() -> ~[~[u8]] { +fn real_args_as_bytes() -> Vec<~[u8]> { real_args().move_iter().map(|s| s.into_bytes()).collect() } @@ -883,13 +883,13 @@ extern "system" { /// /// The arguments are interpreted as utf-8, with invalid bytes replaced with \uFFFD. /// See `str::from_utf8_lossy` for details. -pub fn args() -> ~[~str] { +pub fn args() -> Vec<~str> { real_args() } /// Returns the arguments which this program was started with (normally passed /// via the command line) as byte vectors. -pub fn args_as_bytes() -> ~[~[u8]] { +pub fn args_as_bytes() -> Vec<~[u8]> { real_args_as_bytes() } diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index ac1692e6bb3..df0f1d8d449 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -21,6 +21,7 @@ //! FIXME #7756: This has a lot of C glue for lack of globals. use option::Option; +use vec::Vec; #[cfg(test)] use option::{Some, None}; #[cfg(test)] use realstd; #[cfg(test)] use realargs = realstd::rt::args; @@ -36,10 +37,10 @@ pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) } #[cfg(test)] pub unsafe fn cleanup() { realargs::cleanup() } /// Take the global arguments from global storage. -#[cfg(not(test))] pub fn take() -> Option<~[~[u8]]> { imp::take() } -#[cfg(test)] pub fn take() -> Option<~[~[u8]]> { +#[cfg(not(test))] pub fn take() -> Option<Vec<~[u8]>> { imp::take() } +#[cfg(test)] pub fn take() -> Option<Vec<~[u8]>> { match realargs::take() { - realstd::option::Some(a) => Some(a), + realstd::option::Some(v) => Some(unsafe{ ::cast::transmute(v) }), realstd::option::None => None, } } @@ -47,14 +48,14 @@ pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) } /// Give the global arguments to global storage. /// /// It is an error if the arguments already exist. -#[cfg(not(test))] pub fn put(args: ~[~[u8]]) { imp::put(args) } -#[cfg(test)] pub fn put(args: ~[~[u8]]) { realargs::put(args) } +#[cfg(not(test))] pub fn put(args: Vec<~[u8]>) { imp::put(args) } +#[cfg(test)] pub fn put(args: Vec<~[u8]>) { realargs::put(unsafe { ::cast::transmute(args) }) } /// Make a clone of the global arguments. -#[cfg(not(test))] pub fn clone() -> Option<~[~[u8]]> { imp::clone() } -#[cfg(test)] pub fn clone() -> Option<~[~[u8]]> { +#[cfg(not(test))] pub fn clone() -> Option<Vec<~[u8]>> { imp::clone() } +#[cfg(test)] pub fn clone() -> Option<Vec<~[u8]>> { match realargs::clone() { - realstd::option::Some(a) => Some(a), + realstd::option::Some(v) => Some(unsafe { ::cast::transmute(v) }), realstd::option::None => None, } } @@ -70,6 +71,7 @@ mod imp { use owned::Box; use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; use mem; + use vec::Vec; #[cfg(not(test))] use ptr::RawPtr; static mut global_args_ptr: uint = 0; @@ -87,15 +89,15 @@ mod imp { lock.destroy(); } - pub fn take() -> Option<~[~[u8]]> { + pub fn take() -> Option<Vec<~[u8]>> { with_lock(|| unsafe { let ptr = get_global_ptr(); let val = mem::replace(&mut *ptr, None); - val.as_ref().map(|s: &Box<~[~[u8]]>| (**s).clone()) + val.as_ref().map(|s: &Box<Vec<~[u8]>>| (**s).clone()) }) } - pub fn put(args: ~[~[u8]]) { + pub fn put(args: Vec<~[u8]>) { with_lock(|| unsafe { let ptr = get_global_ptr(); rtassert!((*ptr).is_none()); @@ -103,10 +105,10 @@ mod imp { }) } - pub fn clone() -> Option<~[~[u8]]> { + pub fn clone() -> Option<Vec<~[u8]>> { with_lock(|| unsafe { let ptr = get_global_ptr(); - (*ptr).as_ref().map(|s: &Box<~[~[u8]]>| (**s).clone()) + (*ptr).as_ref().map(|s: &Box<Vec<~[u8]>>| (**s).clone()) }) } @@ -117,13 +119,13 @@ mod imp { } } - fn get_global_ptr() -> *mut Option<Box<~[~[u8]]>> { + fn get_global_ptr() -> *mut Option<Box<Vec<~[u8]>>> { unsafe { cast::transmute(&global_args_ptr) } } // Copied from `os`. #[cfg(not(test))] - unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> ~[~[u8]] { + unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> Vec<~[u8]> { use c_str::CString; use ptr::RawPtr; use libc; @@ -133,7 +135,7 @@ mod imp { Vec::from_fn(argc as uint, |i| { let cs = CString::new(*(argv as **libc::c_char).offset(i as int), false); cs.as_bytes_no_nul().to_owned() - }).move_iter().collect() + }) } #[cfg(test)] @@ -147,7 +149,7 @@ mod imp { // Preserve the actual global state. let saved_value = take(); - let expected = box [bytes!("happy").to_owned(), bytes!("today?").to_owned()]; + let expected = vec![bytes!("happy").to_owned(), bytes!("today?").to_owned()]; put(expected.clone()); assert!(clone() == Some(expected.clone())); @@ -170,6 +172,7 @@ mod imp { #[cfg(target_os = "win32", not(test))] mod imp { use option::Option; + use vec::Vec; pub unsafe fn init(_argc: int, _argv: **u8) { } @@ -177,15 +180,15 @@ mod imp { pub fn cleanup() { } - pub fn take() -> Option<~[~[u8]]> { + pub fn take() -> Option<Vec<~[u8]>> { fail!() } - pub fn put(_args: ~[~[u8]]) { + pub fn put(_args: Vec<~[u8]>) { fail!() } - pub fn clone() -> Option<~[~[u8]]> { + pub fn clone() -> Option<Vec<~[u8]>> { fail!() } } diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 16882624ab7..ccde8d9c96a 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -161,7 +161,7 @@ pub trait IoFactory { fn unix_connect(&mut self, path: &CString, timeout: Option<u64>) -> IoResult<Box<RtioPipe:Send>>; fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>, - hint: Option<ai::Hint>) -> IoResult<~[ai::Info]>; + hint: Option<ai::Hint>) -> IoResult<Vec<ai::Info>>; // filesystem operations fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) @@ -191,7 +191,7 @@ pub trait IoFactory { fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>>; fn spawn(&mut self, config: ProcessConfig) -> IoResult<(Box<RtioProcess:Send>, - ~[Option<Box<RtioPipe:Send>>])>; + Vec<Option<Box<RtioPipe:Send>>>)>; fn kill(&mut self, pid: libc::pid_t, signal: int) -> IoResult<()>; fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<RtioPipe:Send>>; fn tty_open(&mut self, fd: c_int, readable: bool) diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index c7cefbb28ee..21084407b8d 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -127,23 +127,23 @@ 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) -> ~[T]; + fn concat_vec(&self) -> Vec<T>; /// Concatenate a vector of vectors, placing a given separator between each. - fn connect_vec(&self, sep: &T) -> ~[T]; + fn connect_vec(&self, sep: &T) -> Vec<T>; } impl<'a, T: Clone, V: Vector<T>> VectorVector<T> for &'a [V] { - fn concat_vec(&self) -> ~[T] { + 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.move_iter().collect() + result } - fn connect_vec(&self, sep: &T) -> ~[T] { + 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; @@ -151,29 +151,10 @@ impl<'a, T: Clone, V: Vector<T>> VectorVector<T> for &'a [V] { if first { first = false } else { result.push(sep.clone()) } result.push_all(v.as_slice()) } - result.move_iter().collect() + result } } -/** - * 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) -> (~[T], ~[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.move_iter().collect(), us.move_iter().collect()) -} - /// 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. @@ -185,7 +166,7 @@ pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (~[T], ~[U]) { /// The last generated swap is always (0, 1), and it returns the /// sequence to its initial order. pub struct ElementSwaps { - sdir: ~[SizeDirection], + sdir: Vec<SizeDirection>, /// If true, emit the last swap that returns the sequence to initial state emit_reset: bool, swaps_made : uint, @@ -199,9 +180,7 @@ impl ElementSwaps { // element (equal to the original index). ElementSwaps{ emit_reset: true, - sdir: range(0, length) - .map(|i| SizeDirection{ size: i, dir: Neg }) - .collect::<~[_]>(), + sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(), swaps_made: 0 } } @@ -228,12 +207,12 @@ impl Iterator<(uint, uint)> for ElementSwaps { let max = self.sdir.iter().map(|&x| x).enumerate() .filter(|&(i, sd)| new_pos(i, sd.dir) < self.sdir.len() && - self.sdir[new_pos(i, sd.dir)].size < sd.size) + 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.swap(i, j); + self.sdir.as_mut_slice().swap(i, j); // Swap the direction of each larger SizeDirection for x in self.sdir.mut_iter() { @@ -314,16 +293,29 @@ 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 rt::global_heap::{malloc_raw, exchange_free}; + use num::{CheckedAdd, CheckedMul}; + use option::Expect; + let len = self.len(); - let mut result = 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 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 { + let ret = malloc_raw(size) as *mut RawVec<()>; + + (*ret).fill = len * mem::nonzero_size_of::<T>(); + (*ret).alloc = len * mem::nonzero_size_of::<T>(); + + // 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 = result.as_mut_ptr(); - // Use try_finally here otherwise the write to length - // inside the loop stops LLVM from optimising this. + let p = &mut (*ret).data as *mut _ as *mut T; try_finally( &mut i, (), |i, ()| while *i < len { @@ -332,9 +324,15 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] { self.unsafe_ref(*i).clone()); *i += 1; }, - |i| result.set_len(*i)); + |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)); + } + exchange_free(ret as *u8); + }); + cast::transmute(ret) } - result.move_iter().collect() } #[inline(always)] @@ -354,7 +352,7 @@ impl<T: Clone> CloneableVector<T> for ~[T] { 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) -> (~[T], ~[T]); + fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>); /// Create an iterator that yields every possible permutation of the /// vector in succession. @@ -363,7 +361,7 @@ pub trait ImmutableCloneableVector<T> { impl<'a,T:Clone> ImmutableCloneableVector<T> for &'a [T] { #[inline] - fn partitioned(&self, f: |&T| -> bool) -> (~[T], ~[T]) { + fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) { let mut lefts = Vec::new(); let mut rights = Vec::new(); @@ -375,7 +373,7 @@ impl<'a,T:Clone> ImmutableCloneableVector<T> for &'a [T] { } } - (lefts.move_iter().collect(), rights.move_iter().collect()) + (lefts, rights) } fn permutations(self) -> Permutations<T> { @@ -412,7 +410,7 @@ pub trait OwnedVector<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) -> (~[T], ~[T]); + fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>); } impl<T> OwnedVector<T> for ~[T] { @@ -432,7 +430,7 @@ impl<T> OwnedVector<T> for ~[T] { } #[inline] - fn partition(self, f: |&T| -> bool) -> (~[T], ~[T]) { + fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) { let mut lefts = Vec::new(); let mut rights = Vec::new(); @@ -444,7 +442,7 @@ impl<T> OwnedVector<T> for ~[T] { } } - (lefts.move_iter().collect(), rights.move_iter().collect()) + (lefts, rights) } } @@ -729,45 +727,10 @@ impl<'a, T: TotalOrd> MutableTotalOrdVector<T> for &'a mut [T] { } } -/** -* Constructs a vector from an unsafe pointer to a buffer -* -* # Arguments -* -* * ptr - An unsafe pointer to a buffer of `T` -* * elts - The number of elements in the buffer -*/ -// Wrapper for fn in raw: needs to be called by net_tcp::on_tcp_read_cb -pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> ~[T] { - raw::from_buf_raw(ptr, elts) -} - /// Unsafe operations pub mod raw { - use iter::Iterator; - use ptr; - use slice::{MutableVector, OwnedVector}; - use vec::Vec; - pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice}; pub use core::slice::raw::{shift_ptr, pop_ptr}; - - /** - * Constructs a vector from an unsafe pointer to a buffer - * - * # Arguments - * - * * ptr - An unsafe pointer to a buffer of `T` - * * elts - The number of elements in the buffer - */ - // Was in raw, but needs to be called by net_tcp::on_tcp_read_cb - #[inline] - pub unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] { - let mut dst = Vec::with_capacity(elts); - dst.set_len(elts); - ptr::copy_memory(dst.as_mut_ptr(), ptr, elts); - dst.move_iter().collect() - } } /// An iterator that moves out of a vector. @@ -828,31 +791,6 @@ mod tests { fn is_odd(n: &uint) -> bool { *n % 2u == 1u } #[test] - fn test_unsafe_ptrs() { - unsafe { - // Test on-stack copy-from-buf. - let a = box [1, 2, 3]; - let mut ptr = a.as_ptr(); - let b = from_buf(ptr, 3u); - assert_eq!(b.len(), 3u); - assert_eq!(b[0], 1); - assert_eq!(b[1], 2); - assert_eq!(b[2], 3); - - // Test on-heap copy-from-buf. - let c = box [1, 2, 3, 4, 5]; - ptr = c.as_ptr(); - let d = from_buf(ptr, 5u); - assert_eq!(d.len(), 5u); - assert_eq!(d[0], 1); - assert_eq!(d[1], 2); - assert_eq!(d[2], 3); - assert_eq!(d[3], 4); - assert_eq!(d[4], 5); - } - } - - #[test] fn test_from_fn() { // Test on-stack from_fn. let mut v = Vec::from_fn(3u, square); @@ -1231,17 +1169,6 @@ mod tests { } #[test] - fn test_zip_unzip() { - let z1 = vec![(1, 4), (2, 5), (3, 6)]; - - let (left, right) = unzip(z1.iter().map(|&x| x)); - - 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_element_swaps() { let mut v = [1, 2, 3]; for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { @@ -1425,7 +1352,7 @@ mod tests { let n = task_rng().gen::<uint>() % 10; counts[n] += 1; (n, counts[n]) - }).collect::<~[(uint, int)]>(); + }).collect::<Vec<(uint, int)>>(); // only sort on the first element, so an unstable sort // may mix up the counts. @@ -1436,46 +1363,45 @@ mod tests { // will need to be ordered with increasing // counts... i.e. exactly asserting that this sort is // stable. - assert!(v.windows(2).all(|w| w[0] <= w[1])); + assert!(v.as_slice().windows(2).all(|w| w[0] <= w[1])); } } } #[test] fn test_partition() { - assert_eq!((box []).partition(|x: &int| *x < 3), (box [], box [])); - assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 4), (box [1, 2, 3], box [])); - assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 2), (box [1], box [2, 3])); - assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 0), (box [], box [1, 2, 3])); + 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), (box [], box [])) - assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 4), (box [1, 2, 3], box [])); - assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 2), (box [1], box [2, 3])); - assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 0), (box [], box [1, 2, 3])); + 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(), box []); - assert_eq!([box [1], box [2,3]].concat_vec(), box [1, 2, 3]); + 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(), box [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), box []); - assert_eq!([box [1], box [2, 3]].connect_vec(&0), box [1, 0, 2, 3]); - assert_eq!([box [1], box [2], box [3]].connect_vec(&0), box [1, 0, 2, 0, 3]); + 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!(v.connect_vec(&0), box []); - assert_eq!([&[1], &[2, 3]].connect_vec(&0), box [1, 0, 2, 3]); - assert_eq!([&[1], &[2], &[3]].connect_vec(&0), box [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] @@ -1773,74 +1699,74 @@ mod tests { fn test_splitator() { let xs = &[1i,2,3,4,5]; - assert_eq!(xs.split(|x| *x % 2 == 0).collect::<~[&[int]]>(), - box [&[1], &[3], &[5]]); - assert_eq!(xs.split(|x| *x == 1).collect::<~[&[int]]>(), - box [&[], &[2,3,4,5]]); - assert_eq!(xs.split(|x| *x == 5).collect::<~[&[int]]>(), - box [&[1,2,3,4], &[]]); - assert_eq!(xs.split(|x| *x == 10).collect::<~[&[int]]>(), - box [&[1,2,3,4,5]]); - assert_eq!(xs.split(|_| true).collect::<~[&[int]]>(), - box [&[], &[], &[], &[], &[], &[]]); + 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::<~[&[int]]>(), box [&[]]); + 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::<~[&[int]]>(), - box [&[1,2,3,4,5]]); - assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<~[&[int]]>(), - box [&[1], &[3,4,5]]); - assert_eq!(xs.splitn(3, |_| true).collect::<~[&[int]]>(), - box [&[], &[], &[], &[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::<~[&[int]]>(), box [&[]]); + 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::<~[&[int]]>(), - box [&[5], &[3], &[1]]); - assert_eq!(xs.split(|x| *x == 1).rev().collect::<~[&[int]]>(), - box [&[2,3,4,5], &[]]); - assert_eq!(xs.split(|x| *x == 5).rev().collect::<~[&[int]]>(), - box [&[], &[1,2,3,4]]); - assert_eq!(xs.split(|x| *x == 10).rev().collect::<~[&[int]]>(), - box [&[1,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::<~[&[int]]>(), box [&[]]); + 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::<~[&[int]]>(), - box [&[1,2,3,4,5]]); - assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<~[&[int]]>(), - box [&[5], &[1,2,3]]); - assert_eq!(xs.rsplitn(3, |_| true).collect::<~[&[int]]>(), - box [&[], &[], &[], &[1,2]]); + 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::<~[&[int]]>(), box [&[]]); + 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::<~[&[int]]>(), box [&[1,2], &[2,3], &[3,4]]); - assert_eq!(v.windows(3).collect::<~[&[int]]>(), box [&[1i,2,3], &[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()); } @@ -1855,11 +1781,11 @@ mod tests { fn test_chunksator() { let v = &[1i,2,3,4,5]; - assert_eq!(v.chunks(2).collect::<~[&[int]]>(), box [&[1i,2], &[3,4], &[5]]); - assert_eq!(v.chunks(3).collect::<~[&[int]]>(), box [&[1i,2,3], &[4,5]]); - assert_eq!(v.chunks(6).collect::<~[&[int]]>(), box [&[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::<~[&[int]]>(), box [&[5i], &[3,4], &[1,2]]); + 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]); @@ -2238,15 +2164,6 @@ mod bench { } #[bench] - fn add(b: &mut Bencher) { - let xs: &[int] = [5, ..10]; - let ys: &[int] = [5, ..10]; - b.iter(|| { - xs + ys; - }); - } - - #[bench] fn concat(b: &mut Bencher) { let xss: Vec<Vec<uint>> = Vec::from_fn(100, |i| range(0, i).collect()); b.iter(|| { diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 666c0a58b33..fb3dcc97287 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -85,10 +85,9 @@ use fmt; use io::Writer; use iter::{Iterator, range, AdditiveIterator}; use option::{None, Option, Some}; -use ptr; use from_str::FromStr; -use slice::{OwnedVector, ImmutableVector, MutableVector}; -use slice::{Vector}; +use slice::{ImmutableVector, MutableVector, CloneableVector}; +use slice::Vector; use vec::Vec; use default::Default; use strbuf::StrBuf; @@ -668,25 +667,22 @@ impl<'a> fmt::Show for MaybeOwned<'a> { /// Unsafe operations pub mod raw { use cast; - use iter::Iterator; use libc; use ptr::RawPtr; - use ptr; - use slice::{MutableVector, OwnedVector, Vector}; - use str::{is_utf8}; - use vec::Vec; + use raw::Slice; + use slice::CloneableVector; + use str::{is_utf8, StrAllocating}; 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) -> ~str { - let mut v = Vec::with_capacity(len); - ptr::copy_memory(v.as_mut_ptr(), buf, len); - v.set_len(len); - - assert!(is_utf8(v.as_slice())); - ::cast::transmute(v.move_iter().collect::<~[u8]>()) + let v = Slice { data: buf, len: len }; + let bytes: &[u8] = ::cast::transmute(v); + assert!(is_utf8(bytes)); + let s: &str = ::cast::transmute(bytes); + s.to_owned() } #[lang="strdup_uniq"] @@ -824,27 +820,23 @@ pub trait StrAllocating: Str { /// Copy a slice into a new owned str. #[inline] fn to_owned(&self) -> ~str { - let me = self.as_slice(); - let len = me.len(); - unsafe { - let mut v = Vec::with_capacity(len); + use slice::Vector; - ptr::copy_memory(v.as_mut_ptr(), me.as_ptr(), len); - v.set_len(len); - ::cast::transmute(v.move_iter().collect::<~[u8]>()) + unsafe { + ::cast::transmute(self.as_slice().as_bytes().to_owned()) } } /// Converts to a vector of `u16` encoded as UTF-16. - fn to_utf16(&self) -> ~[u16] { + fn to_utf16(&self) -> Vec<u16> { let me = self.as_slice(); - let mut u = Vec::new();; + 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.move_iter().collect() + u } /// Given a string, make a new string with repeated copies of it. @@ -1554,7 +1546,8 @@ mod tests { assert_eq!(a.subslice_offset(c), 0); let string = "a\nb\nc"; - let lines: ~[&str] = string.lines().collect(); + 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); @@ -1617,13 +1610,13 @@ mod tests { fn test_utf16() { let pairs = [("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n".to_owned(), - box [0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16, + 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_owned(), - box [0xd801_u16, 0xdc12_u16, 0xd801_u16, + 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, @@ -1631,7 +1624,7 @@ mod tests { 0x000a_u16]), ("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n".to_owned(), - box [0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16, + 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, @@ -1640,7 +1633,7 @@ mod tests { 0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]), ("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n".to_owned(), - box [0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16, + 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, @@ -1653,18 +1646,18 @@ mod tests { 0x000a_u16 ]), // Issue #12318, even-numbered non-BMP planes ("\U00020000".to_owned(), - box [0xD840, 0xDC00])]; + vec![0xD840, 0xDC00])]; for p in pairs.iter() { let (s, u) = (*p).clone(); - assert!(is_utf16(u)); + assert!(is_utf16(u.as_slice())); assert_eq!(s.to_utf16(), u); - assert_eq!(from_utf16(u).unwrap(), s); - assert_eq!(from_utf16_lossy(u), s); + 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()).unwrap(), s); - assert_eq!(from_utf16(u).unwrap().to_utf16(), u); + assert_eq!(from_utf16(s.to_utf16().as_slice()).unwrap(), s); + assert_eq!(from_utf16(u.as_slice()).unwrap().to_utf16(), u); } } @@ -1921,105 +1914,105 @@ mod tests { fn test_split_char_iterator() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - let split: ~[&str] = data.split(' ').collect(); - assert_eq!( split, box ["\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: ~[&str] = data.split(' ').rev().collect(); + let mut rsplit: Vec<&str> = data.split(' ').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, box ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); - let split: ~[&str] = data.split(|c: char| c == ' ').collect(); - assert_eq!( split, box ["\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: ~[&str] = data.split(|c: char| c == ' ').rev().collect(); + let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, box ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); // Unicode - let split: ~[&str] = data.split('ä').collect(); - assert_eq!( split, box ["\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: ~[&str] = data.split('ä').rev().collect(); + let mut rsplit: Vec<&str> = data.split('ä').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, box ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); - let split: ~[&str] = data.split(|c: char| c == 'ä').collect(); - assert_eq!( split, box ["\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: ~[&str] = data.split(|c: char| c == 'ä').rev().collect(); + let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, box ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + 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: ~[&str] = data.splitn(' ', 3).collect(); - assert_eq!(split, box ["\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: ~[&str] = data.splitn(|c: char| c == ' ', 3).collect(); - assert_eq!(split, box ["\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: ~[&str] = data.splitn('ä', 3).collect(); - assert_eq!(split, box ["\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: ~[&str] = data.splitn(|c: char| c == 'ä', 3).collect(); - assert_eq!(split, box ["\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: ~[&str] = data.rsplitn(' ', 3).collect(); + let mut split: Vec<&str> = data.rsplitn(' ', 3).collect(); split.reverse(); - assert_eq!(split, box ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); - let mut split: ~[&str] = data.rsplitn(|c: char| c == ' ', 3).collect(); + let mut split: Vec<&str> = data.rsplitn(|c: char| c == ' ', 3).collect(); split.reverse(); - assert_eq!(split, box ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); // Unicode - let mut split: ~[&str] = data.rsplitn('ä', 3).collect(); + let mut split: Vec<&str> = data.rsplitn('ä', 3).collect(); split.reverse(); - assert_eq!(split, box ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); - let mut split: ~[&str] = data.rsplitn(|c: char| c == 'ä', 3).collect(); + let mut split: Vec<&str> = data.rsplitn(|c: char| c == 'ä', 3).collect(); split.reverse(); - assert_eq!(split, box ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); + 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: ~[&str] = data.split('\n').collect(); - assert_eq!(split, box ["", "Märy häd ä little lämb", "Little lämb", ""]); + let split: Vec<&str> = data.split('\n').collect(); + assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]); - let split: ~[&str] = data.split_terminator('\n').collect(); - assert_eq!(split, box ["", "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: ~[&str] = data.split('\n').rev().collect(); + let mut split: Vec<&str> = data.split('\n').rev().collect(); split.reverse(); - assert_eq!(split, box ["", "Märy häd ä little lämb", "Little lämb", ""]); + assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]); - let mut split: ~[&str] = data.split_terminator('\n').rev().collect(); + let mut split: Vec<&str> = data.split_terminator('\n').rev().collect(); split.reverse(); - assert_eq!(split, box ["", "Märy häd ä little lämb", "Little lämb"]); + 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: ~[&str] = data.words().collect(); - assert_eq!(words, box ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) + let words: Vec<&str> = data.words().collect(); + assert_eq!(words, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) } #[test] @@ -2053,34 +2046,34 @@ mod tests { #[test] fn test_lines() { let data = "\nMäry häd ä little lämb\n\nLittle lämb\n"; - let lines: ~[&str] = data.lines().collect(); - assert_eq!(lines, box ["", "Märy häd ä little lämb", "", "Little lämb"]); + 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: ~[&str] = data.lines().collect(); - assert_eq!(lines, box ["", "Märy häd ä little lämb", "", "Little lämb"]); + 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<'a>(s: &str, sep: &'a str, u: ~[&str]) { - let v: ~[&str] = s.split_str(sep).collect(); - assert_eq!(v, u); + 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", box ["--1233345--"]); - t("abc::hello::there", "::", box ["abc", "hello", "there"]); - t("::hello::there", "::", box ["", "hello", "there"]); - t("hello::there::", "::", box ["hello", "there", ""]); - t("::hello::there::", "::", box ["", "hello", "there", ""]); - t("ประเทศไทย中华Việt Nam", "中华", box ["ประเทศไทย", "Việt Nam"]); - t("zzXXXzzYYYzz", "zz", box ["", "XXX", "YYY", ""]); - t("zzXXXzYYYz", "XXX", box ["zz", "zYYYz"]); - t(".XXX.YYY.", ".", box ["", "XXX", "YYY", ""]); - t("", ".", box [""]); - t("zz", "zz", box ["",""]); - t("ok", "z", box ["ok"]); - t("zzz", "zz", box ["","z"]); - t("zzzzz", "zz", box ["","","z"]); + 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] diff --git a/src/libstd/strbuf.rs b/src/libstd/strbuf.rs index ad703b8054b..8e05b2f527d 100644 --- a/src/libstd/strbuf.rs +++ b/src/libstd/strbuf.rs @@ -19,7 +19,7 @@ use io::Writer; use iter::{Extendable, FromIterator, Iterator, range}; use option::{None, Option, Some}; use ptr::RawPtr; -use slice::{OwnedVector, Vector}; +use slice::{OwnedVector, Vector, CloneableVector}; use str::{OwnedStr, Str, StrSlice, StrAllocating}; use str; use vec::Vec; @@ -273,11 +273,8 @@ impl Str for StrBuf { impl StrAllocating for StrBuf { #[inline] fn into_owned(self) -> ~str { - let StrBuf { - vec: vec - } = self; unsafe { - cast::transmute::<~[u8],~str>(vec.move_iter().collect()) + cast::transmute(self.vec.as_slice().to_owned()) } } diff --git a/src/libstd/sync/arc.rs b/src/libstd/sync/arc.rs index d277c514e44..676c836c459 100644 --- a/src/libstd/sync/arc.rs +++ b/src/libstd/sync/arc.rs @@ -69,14 +69,14 @@ impl<T: Send> UnsafeArc<T> { /// As new(), but returns a vector of as many pre-cloned handles as /// requested. - pub fn newN(data: T, num_handles: uint) -> ~[UnsafeArc<T>] { + pub fn newN(data: T, num_handles: uint) -> Vec<UnsafeArc<T>> { unsafe { if num_handles == 0 { - box [] // need to free data here + vec![] // need to free data here } else { let ptr = new_inner(data, num_handles); let v = Vec::from_fn(num_handles, |_| UnsafeArc { data: ptr }); - v.move_iter().collect() + v } } } diff --git a/src/libstd/sync/deque.rs b/src/libstd/sync/deque.rs index d06062f02ac..8dfd691e6ff 100644 --- a/src/libstd/sync/deque.rs +++ b/src/libstd/sync/deque.rs @@ -407,7 +407,7 @@ mod tests { use rand::Rng; use sync::atomics::{AtomicBool, INIT_ATOMIC_BOOL, SeqCst, AtomicUint, INIT_ATOMIC_UINT}; - use slice; + use vec; #[test] fn smoke() { @@ -603,7 +603,7 @@ mod tests { let mut pool = BufferPool::<(int, uint)>::new(); let (mut w, s) = pool.deque(); - let (threads, hits) = slice::unzip(range(0, NTHREADS).map(|_| { + let (threads, hits) = vec::unzip(range(0, NTHREADS).map(|_| { let s = s.clone(); let unique_box = box AtomicUint::new(0); let thread_box = unsafe { diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 68f0aaab05b..e2a9f6a5c48 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -18,13 +18,16 @@ A simple wrapper over the platform's dynamic library facilities use c_str::ToCStr; use cast; +use iter::Iterator; use ops::*; use option::*; use os; use path::GenericPath; use path; use result::*; +use slice::{Vector,OwnedVector}; use str; +use vec::Vec; pub struct DynamicLibrary { handle: *u8} @@ -73,8 +76,10 @@ impl DynamicLibrary { ("LD_LIBRARY_PATH", ':' as u8) }; let newenv = os::getenv_as_bytes(envvar).unwrap_or(box []); - let newenv = newenv + &[sep] + path.as_vec(); - os::setenv(envvar, str::from_utf8(newenv).unwrap()); + let mut newenv = newenv.move_iter().collect::<Vec<_>>(); + newenv.push_all(&[sep]); + newenv.push_all(path.as_vec()); + os::setenv(envvar, str::from_utf8(newenv.as_slice()).unwrap()); } /// Access the value at the symbol of the dynamic library diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index af146b96e50..da01da26709 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -22,12 +22,13 @@ use mem::{size_of, move_val_init}; use mem; use num; use num::{CheckedMul, CheckedAdd}; -use ops::Drop; +use ops::{Add, Drop}; use option::{None, Option, Some, Expect}; use ptr::RawPtr; use ptr; use rt::global_heap::{malloc_raw, realloc_raw}; use raw::Slice; +use RawVec = raw::Vec; use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector}; use slice::{MutableTotalOrdVector, OwnedVector, Vector}; use slice::{MutableVectorAllocating}; @@ -1370,6 +1371,16 @@ impl<T> Vector<T> for Vec<T> { } } +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) { @@ -1436,10 +1447,94 @@ impl<T> Drop for MoveItems<T> { } } +/** + * 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 = malloc_raw(size) as *mut RawVec<()>; + + (*ret).fill = len * mem::nonzero_size_of::<T>(); + (*ret).alloc = len * mem::nonzero_size_of::<T>(); + + 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); + + 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() { @@ -1649,4 +1744,75 @@ mod tests { 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_owned(), "two".to_owned()]; + let b: ~[~str] = FromVec::from_vec(a); + assert_eq!(b.as_slice(), &["one".to_owned(), "two".to_owned()]); + + 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); + } } |
