diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 04e839cf691dc..af4fabef78b64 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -46,8 +46,8 @@ use cmp::{Eq,Ord}; use ops::Add; use util; use num::Zero; -use iterator::Iterator; use iterator; +use iterator::{Iterator, DoubleEndedIterator}; use str::{StrSlice, OwnedStr}; use to_str::ToStr; use clone::DeepClone; @@ -372,7 +372,7 @@ impl Option { } } - /// Returns self or `Some(zero)` (for this type) + /// Returns self or `Some`-wrapped zero value #[inline] pub fn or_zero(self) -> Option { match self { @@ -407,6 +407,13 @@ impl Iterator for OptionIterator { } } +impl DoubleEndedIterator for OptionIterator { + #[inline] + fn next_back(&mut self) -> Option { + self.opt.take() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/libstd/std.rs b/src/libstd/std.rs index c4bd0a6d04354..9370e7b0e84c9 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -110,7 +110,7 @@ pub mod prelude; #[path = "num/f32.rs"] pub mod f32; #[path = "num/f64.rs"] pub mod f64; -pub mod nil; +pub mod unit; pub mod bool; pub mod char; pub mod tuple; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index b8e6153694121..9148767851f52 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1050,7 +1050,7 @@ pub trait Str { /// Work with `self` as a slice. fn as_slice<'a>(&'a self) -> &'a str; - /// Convert `self` into a ~str. + /// Convert `self` into a ~str, not making a copy if possible fn into_owned(self) -> ~str; } diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs index 701d57388158b..e0068f5e53e14 100644 --- a/src/libstd/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -23,7 +23,7 @@ use to_bytes::IterBytes; use option::{Some, None}; /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. -#[deriving(Clone, Eq)] +#[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)] pub struct Ascii { priv chr: u8 } impl Ascii { @@ -250,21 +250,40 @@ impl ToBytesConsume for ~[Ascii] { } } - -/// Convert the string to ASCII upper case: -/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', -/// but non-ASCII letters are unchanged. -#[inline] -pub fn to_ascii_upper(string: &str) -> ~str { - map_bytes(string, ASCII_UPPER_MAP) +/// Extension methods for ASCII-subset only operations on strings +pub trait StrAsciiExt { + /// Convert the string to ASCII upper case: + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + fn to_ascii_upper(&self) -> ~str; + + /// Convert the string to ASCII lower case: + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + fn to_ascii_lower(&self) -> ~str; + + /// Check that two strings are an ASCII case-insensitive match. + /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`, + /// but without allocating and copying temporary strings. + fn eq_ignore_ascii_case(&self, other: &str) -> bool; } -/// Convert the string to ASCII lower case: -/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', -/// but non-ASCII letters are unchanged. -#[inline] -pub fn to_ascii_lower(string: &str) -> ~str { - map_bytes(string, ASCII_LOWER_MAP) +impl<'self> StrAsciiExt for &'self str { + #[inline] + fn to_ascii_upper(&self) -> ~str { + map_bytes(*self, ASCII_UPPER_MAP) + } + + #[inline] + fn to_ascii_lower(&self) -> ~str { + map_bytes(*self, ASCII_LOWER_MAP) + } + + #[inline] + fn eq_ignore_ascii_case(&self, other: &str) -> bool { + self.len() == other.len() && self.as_bytes().iter().zip(other.as_bytes().iter()).all( + |(byte_self, byte_other)| ASCII_LOWER_MAP[*byte_self] == ASCII_LOWER_MAP[*byte_other]) + } } #[inline] @@ -283,15 +302,6 @@ fn map_bytes(string: &str, map: &'static [u8]) -> ~str { result } -/// Check that two strings are an ASCII case-insensitive match. -/// Same as `to_ascii_lower(a) == to_ascii_lower(b)`, -/// but without allocating and copying temporary strings. -#[inline] -pub fn eq_ignore_ascii_case(a: &str, b: &str) -> bool { - a.len() == b.len() && a.as_bytes().iter().zip(b.as_bytes().iter()).all( - |(byte_a, byte_b)| ASCII_LOWER_MAP[*byte_a] == ASCII_LOWER_MAP[*byte_b]) -} - static ASCII_LOWER_MAP: &'static [u8] = &[ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, @@ -453,49 +463,48 @@ mod tests { #[test] fn test_to_ascii_upper() { - assert_eq!(to_ascii_upper("url()URL()uRl()ürl"), ~"URL()URL()URL()üRL"); - assert_eq!(to_ascii_upper("hıKß"), ~"HıKß"); + assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), ~"URL()URL()URL()üRL"); + assert_eq!("hıKß".to_ascii_upper(), ~"HıKß"); let mut i = 0; while i <= 500 { let c = i as char; let upper = if 'a' <= c && c <= 'z' { c + 'A' - 'a' } else { c }; - assert_eq!(to_ascii_upper(from_char(i as char)), from_char(upper)) + assert_eq!(from_char(i as char).to_ascii_upper(), from_char(upper)) i += 1; } } #[test] fn test_to_ascii_lower() { - assert_eq!(to_ascii_lower("url()URL()uRl()Ürl"), ~"url()url()url()Ürl"); + assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), ~"url()url()url()Ürl"); // Dotted capital I, Kelvin sign, Sharp S. - assert_eq!(to_ascii_lower("HİKß"), ~"hİKß"); + assert_eq!("HİKß".to_ascii_lower(), ~"hİKß"); let mut i = 0; while i <= 500 { let c = i as char; let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c }; - assert_eq!(to_ascii_lower(from_char(i as char)), from_char(lower)) + assert_eq!(from_char(i as char).to_ascii_lower(), from_char(lower)) i += 1; } } - #[test] fn test_eq_ignore_ascii_case() { - assert!(eq_ignore_ascii_case("url()URL()uRl()Ürl", "url()url()url()Ürl")); - assert!(!eq_ignore_ascii_case("Ürl", "ürl")); + assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl")); + assert!(!"Ürl".eq_ignore_ascii_case("ürl")); // Dotted capital I, Kelvin sign, Sharp S. - assert!(eq_ignore_ascii_case("HİKß", "hİKß")); - assert!(!eq_ignore_ascii_case("İ", "i")); - assert!(!eq_ignore_ascii_case("K", "k")); - assert!(!eq_ignore_ascii_case("ß", "s")); + assert!("HİKß".eq_ignore_ascii_case("hİKß")); + assert!(!"İ".eq_ignore_ascii_case("i")); + assert!(!"K".eq_ignore_ascii_case("k")); + assert!(!"ß".eq_ignore_ascii_case("s")); let mut i = 0; while i <= 500 { let c = i as char; let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c }; - assert!(eq_ignore_ascii_case(from_char(i as char), from_char(lower))); + assert!(from_char(i as char).eq_ignore_ascii_case(from_char(lower))); i += 1; } } diff --git a/src/libstd/nil.rs b/src/libstd/unit.rs similarity index 99% rename from src/libstd/nil.rs rename to src/libstd/unit.rs index d2e9cf9ae7e96..82f14e4c8d72b 100644 --- a/src/libstd/nil.rs +++ b/src/libstd/unit.rs @@ -19,8 +19,6 @@ use prelude::*; #[cfg(not(test))] use num::Zero; - - #[cfg(not(test))] impl Eq for () { #[inline] @@ -54,4 +52,3 @@ impl Zero for () { #[inline] fn is_zero(&self) -> bool { true } } - diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 27e09d8547989..6d27c43def8c0 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -707,14 +707,17 @@ pub trait Vector { /// Work with `self` as a slice. fn as_slice<'a>(&'a self) -> &'a [T]; } + impl<'self,T> Vector for &'self [T] { #[inline(always)] fn as_slice<'a>(&'a self) -> &'a [T] { *self } } + impl Vector for ~[T] { #[inline(always)] fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v } } + impl Vector for @[T] { #[inline(always)] fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v } @@ -748,13 +751,17 @@ impl Container for ~[T] { } } -#[allow(missing_doc)] +/// Extension methods for vector slices with copyable elements pub trait CopyableVector { + /// Copy `self` into a new owned vector fn to_owned(&self) -> ~[T]; + + /// Convert `self` into a owned vector, not making a copy if possible. + fn into_owned(self) -> ~[T]; } -/// Extension methods for vectors -impl<'self,T:Clone> CopyableVector for &'self [T] { +/// Extension methods for vector slices +impl<'self, T: Clone> CopyableVector for &'self [T] { /// Returns a copy of `v`. #[inline] fn to_owned(&self) -> ~[T] { @@ -764,6 +771,27 @@ impl<'self,T:Clone> CopyableVector for &'self [T] { } result } + + #[inline(always)] + fn into_owned(self) -> ~[T] { self.to_owned() } +} + +/// Extension methods for owned vectors +impl CopyableVector for ~[T] { + #[inline] + fn to_owned(&self) -> ~[T] { self.clone() } + + #[inline(always)] + fn into_owned(self) -> ~[T] { self } +} + +/// Extension methods for managed vectors +impl CopyableVector for @[T] { + #[inline] + fn to_owned(&self) -> ~[T] { self.as_slice().to_owned() } + + #[inline(always)] + fn into_owned(self) -> ~[T] { self.to_owned() } } #[allow(missing_doc)]