Methodyfied the string ascii extionsion functions

Added into_owned() method for vectors
Added DoubleEnded Iterator impl to Option
Renamed nil.rs to unit.rs
This commit is contained in:
Marvin Löbel 2013-08-11 04:21:31 +02:00
parent 0efbb25a26
commit a00becd0eb
6 changed files with 87 additions and 46 deletions

View file

@ -46,8 +46,8 @@ use cmp::{Eq,Ord};
use ops::Add; use ops::Add;
use util; use util;
use num::Zero; use num::Zero;
use iterator::Iterator;
use iterator; use iterator;
use iterator::{Iterator, DoubleEndedIterator};
use str::{StrSlice, OwnedStr}; use str::{StrSlice, OwnedStr};
use to_str::ToStr; use to_str::ToStr;
use clone::DeepClone; use clone::DeepClone;
@ -372,7 +372,7 @@ impl<T:Zero> Option<T> {
} }
} }
/// Returns self or `Some(zero)` (for this type) /// Returns self or `Some`-wrapped zero value
#[inline] #[inline]
pub fn or_zero(self) -> Option<T> { pub fn or_zero(self) -> Option<T> {
match self { match self {
@ -407,6 +407,13 @@ impl<A> Iterator<A> for OptionIterator<A> {
} }
} }
impl<A> DoubleEndedIterator<A> for OptionIterator<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
self.opt.take()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -110,7 +110,7 @@ pub mod prelude;
#[path = "num/f32.rs"] pub mod f32; #[path = "num/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64; #[path = "num/f64.rs"] pub mod f64;
pub mod nil; pub mod unit;
pub mod bool; pub mod bool;
pub mod char; pub mod char;
pub mod tuple; pub mod tuple;

View file

@ -1050,7 +1050,7 @@ pub trait Str {
/// Work with `self` as a slice. /// Work with `self` as a slice.
fn as_slice<'a>(&'a self) -> &'a str; 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; fn into_owned(self) -> ~str;
} }

View file

@ -23,7 +23,7 @@ use to_bytes::IterBytes;
use option::{Some, None}; use option::{Some, None};
/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. /// 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 } pub struct Ascii { priv chr: u8 }
impl Ascii { impl Ascii {
@ -250,21 +250,40 @@ impl ToBytesConsume for ~[Ascii] {
} }
} }
/// Extension methods for ASCII-subset only operations on strings
pub trait StrAsciiExt {
/// Convert the string to ASCII upper case: /// Convert the string to ASCII upper case:
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged. /// but non-ASCII letters are unchanged.
#[inline] fn to_ascii_upper(&self) -> ~str;
pub fn to_ascii_upper(string: &str) -> ~str {
map_bytes(string, ASCII_UPPER_MAP)
}
/// Convert the string to ASCII lower case: /// Convert the string to ASCII lower case:
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged. /// 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;
}
impl<'self> StrAsciiExt for &'self str {
#[inline] #[inline]
pub fn to_ascii_lower(string: &str) -> ~str { fn to_ascii_upper(&self) -> ~str {
map_bytes(string, ASCII_LOWER_MAP) 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] #[inline]
@ -283,15 +302,6 @@ fn map_bytes(string: &str, map: &'static [u8]) -> ~str {
result 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] = &[ static ASCII_LOWER_MAP: &'static [u8] = &[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
@ -453,49 +463,48 @@ mod tests {
#[test] #[test]
fn test_to_ascii_upper() { fn test_to_ascii_upper() {
assert_eq!(to_ascii_upper("url()URL()uRl()ürl"), ~"URL()URL()URL()üRL"); assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), ~"URL()URL()URL()üRL");
assert_eq!(to_ascii_upper("hıß"), ~"Hıß"); assert_eq!("hıß".to_ascii_upper(), ~"Hıß");
let mut i = 0; let mut i = 0;
while i <= 500 { while i <= 500 {
let c = i as char; let c = i as char;
let upper = if 'a' <= c && c <= 'z' { c + 'A' - 'a' } else { c }; 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; i += 1;
} }
} }
#[test] #[test]
fn test_to_ascii_lower() { 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. // Dotted capital I, Kelvin sign, Sharp S.
assert_eq!(to_ascii_lower("ß"), ~"ß"); assert_eq!("ß".to_ascii_lower(), ~"ß");
let mut i = 0; let mut i = 0;
while i <= 500 { while i <= 500 {
let c = i as char; let c = i as char;
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c }; 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; i += 1;
} }
} }
#[test] #[test]
fn test_eq_ignore_ascii_case() { fn test_eq_ignore_ascii_case() {
assert!(eq_ignore_ascii_case("url()URL()uRl()Ürl", "url()url()url()Ürl")); assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
assert!(!eq_ignore_ascii_case("Ürl", "ürl")); assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
// Dotted capital I, Kelvin sign, Sharp S. // Dotted capital I, Kelvin sign, Sharp S.
assert!(eq_ignore_ascii_case("ß", "ß")); assert!("ß".eq_ignore_ascii_case("ß"));
assert!(!eq_ignore_ascii_case("İ", "i")); assert!(!"İ".eq_ignore_ascii_case("i"));
assert!(!eq_ignore_ascii_case("", "k")); assert!(!"".eq_ignore_ascii_case("k"));
assert!(!eq_ignore_ascii_case("ß", "s")); assert!(!"ß".eq_ignore_ascii_case("s"));
let mut i = 0; let mut i = 0;
while i <= 500 { while i <= 500 {
let c = i as char; let c = i as char;
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c }; 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; i += 1;
} }
} }

View file

@ -19,8 +19,6 @@ use prelude::*;
#[cfg(not(test))] #[cfg(not(test))]
use num::Zero; use num::Zero;
#[cfg(not(test))] #[cfg(not(test))]
impl Eq for () { impl Eq for () {
#[inline] #[inline]
@ -54,4 +52,3 @@ impl Zero for () {
#[inline] #[inline]
fn is_zero(&self) -> bool { true } fn is_zero(&self) -> bool { true }
} }

View file

@ -707,14 +707,17 @@ pub trait Vector<T> {
/// Work with `self` as a slice. /// Work with `self` as a slice.
fn as_slice<'a>(&'a self) -> &'a [T]; fn as_slice<'a>(&'a self) -> &'a [T];
} }
impl<'self,T> Vector<T> for &'self [T] { impl<'self,T> Vector<T> for &'self [T] {
#[inline(always)] #[inline(always)]
fn as_slice<'a>(&'a self) -> &'a [T] { *self } fn as_slice<'a>(&'a self) -> &'a [T] { *self }
} }
impl<T> Vector<T> for ~[T] { impl<T> Vector<T> for ~[T] {
#[inline(always)] #[inline(always)]
fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v } fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v }
} }
impl<T> Vector<T> for @[T] { impl<T> Vector<T> for @[T] {
#[inline(always)] #[inline(always)]
fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v } fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v }
@ -748,12 +751,16 @@ impl<T> Container for ~[T] {
} }
} }
#[allow(missing_doc)] /// Extension methods for vector slices with copyable elements
pub trait CopyableVector<T> { pub trait CopyableVector<T> {
/// Copy `self` into a new owned vector
fn to_owned(&self) -> ~[T]; 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 /// Extension methods for vector slices
impl<'self, T: Clone> CopyableVector<T> for &'self [T] { impl<'self, T: Clone> CopyableVector<T> for &'self [T] {
/// Returns a copy of `v`. /// Returns a copy of `v`.
#[inline] #[inline]
@ -764,6 +771,27 @@ impl<'self,T:Clone> CopyableVector<T> for &'self [T] {
} }
result result
} }
#[inline(always)]
fn into_owned(self) -> ~[T] { self.to_owned() }
}
/// Extension methods for owned vectors
impl<T: Clone> CopyableVector<T> for ~[T] {
#[inline]
fn to_owned(&self) -> ~[T] { self.clone() }
#[inline(always)]
fn into_owned(self) -> ~[T] { self }
}
/// Extension methods for managed vectors
impl<T: Clone> CopyableVector<T> 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)] #[allow(missing_doc)]