diff options
| author | bors <bors@rust-lang.org> | 2014-01-02 14:41:50 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-01-02 14:41:50 -0800 |
| commit | 2e98a93ba991e2390b0068af72c5600b659cfb66 (patch) | |
| tree | 67eca7db9ad23e30dae76c4ccf6b91598237f7dd /src/libstd | |
| parent | 0df9b850ac1ed3abd0ff5abfbb716af83501dd5a (diff) | |
| parent | f8cc9a9cb1e221abb0cbf2e169b10c826f3fbd98 (diff) | |
| download | rust-2e98a93ba991e2390b0068af72c5600b659cfb66.tar.gz rust-2e98a93ba991e2390b0068af72c5600b659cfb66.zip | |
auto merge of #10828 : SimonSapin/rust/ascii_opt, r=pcwalton
… instead of failing. Make them default methods on the trait, and also make .to_ascii() a default method while we’re at it.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/ascii.rs | 106 |
1 files changed, 70 insertions, 36 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 97f0a6a9d8a..974bc454c66 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -12,14 +12,15 @@ use to_str::{ToStr,IntoStr}; use str; +use str::Str; use str::StrSlice; use str::OwnedStr; use container::Container; use cast; use iter::Iterator; -use vec::{ImmutableVector, MutableVector}; +use vec::{ImmutableVector, MutableVector, Vector}; use to_bytes::IterBytes; -use option::{Some, None}; +use option::{Option, Some, None}; /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)] @@ -135,8 +136,22 @@ impl ToStr for Ascii { /// Trait for converting into an ascii type. pub trait AsciiCast<T> { - /// Convert to an ascii type - fn to_ascii(&self) -> T; + /// Convert to an ascii type, fail on non-ASCII input. + #[inline] + fn to_ascii(&self) -> T { + assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + /// Convert to an ascii type, return None on non-ASCII input. + #[inline] + fn to_ascii_opt(&self) -> Option<T> { + if self.is_ascii() { + Some(unsafe { self.to_ascii_nocheck() }) + } else { + None + } + } /// Convert to an ascii type, not doing any range asserts unsafe fn to_ascii_nocheck(&self) -> T; @@ -147,12 +162,6 @@ pub trait AsciiCast<T> { impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] { #[inline] - fn to_ascii(&self) -> &'a[Ascii] { - assert!(self.is_ascii()); - unsafe {self.to_ascii_nocheck()} - } - - #[inline] unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] { cast::transmute(*self) } @@ -168,12 +177,6 @@ impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] { impl<'a> AsciiCast<&'a [Ascii]> for &'a str { #[inline] - fn to_ascii(&self) -> &'a [Ascii] { - assert!(self.is_ascii()); - unsafe { self.to_ascii_nocheck() } - } - - #[inline] unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] { cast::transmute(*self) } @@ -186,12 +189,6 @@ impl<'a> AsciiCast<&'a [Ascii]> for &'a str { impl AsciiCast<Ascii> for u8 { #[inline] - fn to_ascii(&self) -> Ascii { - assert!(self.is_ascii()); - unsafe {self.to_ascii_nocheck()} - } - - #[inline] unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self } } @@ -204,12 +201,6 @@ impl AsciiCast<Ascii> for u8 { impl AsciiCast<Ascii> for char { #[inline] - fn to_ascii(&self) -> Ascii { - assert!(self.is_ascii()); - unsafe {self.to_ascii_nocheck()} - } - - #[inline] unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self as u8 } } @@ -222,8 +213,25 @@ impl AsciiCast<Ascii> for char { /// Trait for copyless casting to an ascii vector. pub trait OwnedAsciiCast { - /// Take ownership and cast to an ascii vector. - fn into_ascii(self) -> ~[Ascii]; + /// Check if convertible to ascii + fn is_ascii(&self) -> bool; + + /// Take ownership and cast to an ascii vector. Fail on non-ASCII input. + #[inline] + fn into_ascii(self) -> ~[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]> { + if self.is_ascii() { + Some(unsafe { self.into_ascii_nocheck() }) + } else { + None + } + } /// Take ownership and cast to an ascii vector. /// Does not perform validation checks. @@ -232,9 +240,8 @@ pub trait OwnedAsciiCast { impl OwnedAsciiCast for ~[u8] { #[inline] - fn into_ascii(self) -> ~[Ascii] { - assert!(self.is_ascii()); - unsafe {self.into_ascii_nocheck()} + fn is_ascii(&self) -> bool { + self.as_slice().is_ascii() } #[inline] @@ -245,9 +252,8 @@ impl OwnedAsciiCast for ~[u8] { impl OwnedAsciiCast for ~str { #[inline] - fn into_ascii(self) -> ~[Ascii] { - assert!(self.is_ascii()); - unsafe {self.into_ascii_nocheck()} + fn is_ascii(&self) -> bool { + self.as_slice().is_ascii() } #[inline] @@ -475,9 +481,11 @@ mod tests { use super::*; use str::from_char; use char::from_u32; + use option::{Some, None}; macro_rules! v2ascii ( ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); + (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]); (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]); ) @@ -569,6 +577,32 @@ mod tests { #[test] #[should_fail] fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); } + fn test_opt() { + assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 })); + assert_eq!(255u8.to_ascii_opt(), None); + + assert_eq!('A'.to_ascii_opt(), Some(Ascii { chr: 65u8 })); + assert_eq!('λ'.to_ascii_opt(), None); + + assert_eq!("zoä华".to_ascii_opt(), None); + + assert_eq!((&[127u8, 128u8, 255u8]).to_ascii_opt(), None); + + let v = [40u8, 32u8, 59u8]; + assert_eq!(v.to_ascii_opt(), Some(v2ascii!(&[40, 32, 59]))); + let v = [127u8, 128u8, 255u8]; + assert_eq!(v.to_ascii_opt(), None); + + assert_eq!("( ;".to_ascii_opt(), Some(v2ascii!(&[40, 32, 59]))); + assert_eq!("zoä华".to_ascii_opt(), None); + + assert_eq!((~[40u8, 32u8, 59u8]).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59]))); + assert_eq!((~[127u8, 128u8, 255u8]).into_ascii_opt(), None); + + assert_eq!((~"( ;").into_ascii_opt(), Some(v2ascii!(~[40, 32, 59]))); + assert_eq!((~"zoä华").into_ascii_opt(), None); + } + #[test] fn test_to_ascii_upper() { assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), ~"URL()URL()URL()üRL"); |
