about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarvin Löbel <loebel.marvin@gmail.com>2013-04-20 19:39:15 +0200
committerMarvin Löbel <loebel.marvin@gmail.com>2013-04-20 22:51:55 +0200
commit61ffee738d505328fae14ac7c53bc388c69c5938 (patch)
treed772347208e74953fd9da7e9e95263d134116bcb
parent4357cbf2fac1e5a0d9723c1f0f9e94c831dc397c (diff)
downloadrust-61ffee738d505328fae14ac7c53bc388c69c5938.tar.gz
rust-61ffee738d505328fae14ac7c53bc388c69c5938.zip
Added Ascii type
-rw-r--r--src/libcore/prelude.rs7
-rw-r--r--src/libcore/str.rs17
-rw-r--r--src/libcore/str/ascii.rs216
-rw-r--r--src/libcore/to_str.rs6
4 files changed, 243 insertions, 3 deletions
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 822fb2e476b..84793694582 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -40,9 +40,14 @@ pub use path::Path;
 pub use path::PosixPath;
 pub use path::WindowsPath;
 pub use ptr::Ptr;
+// NOTE: Remove markers after snapshot
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+pub use str::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii};
 pub use str::{StrSlice, OwnedStr};
 pub use to_bytes::IterBytes;
-pub use to_str::ToStr;
+pub use to_str::{ToStr, ToStrConsume};
 pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
 pub use vec::{CopyableVector, ImmutableVector};
 pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 2296fea0454..11301c9f1db 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -17,6 +17,12 @@
  * some heavy-duty uses, try std::rope.
  */
 
+// NOTE: Remove markers after snapshot
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+pub use self::ascii::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii};
+
 use at_vec;
 use cast;
 use char;
@@ -34,6 +40,13 @@ use to_str::ToStr;
 
 #[cfg(notest)] use cmp::{Eq, Ord, Equiv, TotalEq};
 
+// NOTE: Remove markers after snapshot
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+#[path = "str/ascii.rs"]
+mod ascii;
+
 /*
 Section: Creating a string
 */
@@ -3347,7 +3360,7 @@ mod tests {
     #[test]
     fn test_shift_byte() {
         let mut s = ~"ABC";
-        let b = raw::shift_byte(&mut s);
+        let b = unsafe{raw::shift_byte(&mut s)};
         assert!((s == ~"BC"));
         assert!((b == 65u8));
     }
@@ -3355,7 +3368,7 @@ mod tests {
     #[test]
     fn test_pop_byte() {
         let mut s = ~"ABC";
-        let b = raw::pop_byte(&mut s);
+        let b = unsafe{raw::pop_byte(&mut s)};
         assert!((s == ~"AB"));
         assert!((b == 67u8));
     }
diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs
new file mode 100644
index 00000000000..1e882daeef9
--- /dev/null
+++ b/src/libcore/str/ascii.rs
@@ -0,0 +1,216 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use to_str::{ToStr,ToStrConsume};
+use str;
+use cast;
+
+#[cfg(test)]
+pub struct Ascii { priv chr: u8 }
+
+/// Datatype to hold one ascii character. It is 8 bit long.
+#[cfg(notest)]
+#[deriving(Clone, Eq, Ord)]
+pub struct Ascii { priv chr: u8 }
+
+pub impl Ascii {
+    /// Converts a ascii character into a `u8`.
+    fn to_byte(self) -> u8 {
+        self.chr
+    }
+
+    /// Converts a ascii character into a `char`.
+    fn to_char(self) -> char {
+        self.chr as char
+    }
+}
+
+impl ToStr for Ascii {
+    fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) }
+}
+
+/// Trait for converting into an ascii type.
+pub trait AsciiCast<T> {
+    /// Convert to an ascii type
+    fn to_ascii(&self) -> T;
+
+    /// Check if convertible to ascii
+    fn is_ascii(&self) -> bool;
+}
+
+impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
+    fn to_ascii(&self) -> &'self[Ascii] {
+        assert!(self.is_ascii());
+
+        unsafe{ cast::transmute(*self) }
+    }
+
+    fn is_ascii(&self) -> bool {
+        for self.each |b| {
+            if !b.is_ascii() { return false; }
+        }
+        true
+    }
+}
+
+impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
+    fn to_ascii(&self) -> &'self[Ascii] {
+        assert!(self.is_ascii());
+
+        let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) };
+        unsafe{ cast::transmute((p, len - 1))}
+    }
+
+    fn is_ascii(&self) -> bool {
+        for self.each |b| {
+            if !b.is_ascii() { return false; }
+        }
+        true
+    }
+}
+
+impl AsciiCast<Ascii> for u8 {
+    fn to_ascii(&self) -> Ascii {
+        assert!(self.is_ascii());
+        Ascii{ chr: *self }
+    }
+
+    fn is_ascii(&self) -> bool {
+        *self & 128 == 0u8
+    }
+}
+
+impl AsciiCast<Ascii> for char {
+    fn to_ascii(&self) -> Ascii {
+        assert!(self.is_ascii());
+        Ascii{ chr: *self as u8 }
+    }
+
+    fn is_ascii(&self) -> bool {
+        *self - ('\x7F' & *self) == '\x00'
+    }
+}
+
+/// Trait for copyless casting to an ascii vector.
+pub trait OwnedAsciiCast {
+    /// Take ownership and cast to an ascii vector without trailing zero element.
+    fn to_ascii_consume(self) -> ~[Ascii];
+}
+
+impl OwnedAsciiCast for ~[u8] {
+    fn to_ascii_consume(self) -> ~[Ascii] {
+        assert!(self.is_ascii());
+
+        unsafe {cast::transmute(self)}
+    }
+}
+
+impl OwnedAsciiCast for ~str {
+    fn to_ascii_consume(self) -> ~[Ascii] {
+        let mut s = self;
+        unsafe {
+            str::raw::pop_byte(&mut s);
+            cast::transmute(s)
+        }
+    }
+}
+
+/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
+pub trait ToStrAscii {
+    /// Convert to a string.
+    fn to_str_ascii(&self) -> ~str;
+}
+
+impl<'self> ToStrAscii for &'self [Ascii] {
+    fn to_str_ascii(&self) -> ~str {
+        let mut cpy = self.to_owned();
+        cpy.push(0u8.to_ascii());
+        unsafe {cast::transmute(cpy)}
+    }
+}
+
+impl ToStrConsume for ~[Ascii] {
+    fn to_str_consume(self) -> ~str {
+        let mut cpy = self;
+        cpy.push(0u8.to_ascii());
+        unsafe {cast::transmute(cpy)}
+    }
+}
+
+// NOTE: Remove stage0 marker after snapshot
+#[cfg(and(test, not(stage0)))]
+mod tests {
+    use super::*;
+    use to_str::{ToStr,ToStrConsume};
+    use str;
+    use cast;
+
+    macro_rules! v2ascii (
+        ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
+        (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
+    )
+
+    #[test]
+    fn test_ascii() {
+        assert_eq!(65u8.to_ascii().to_byte(), 65u8);
+        assert_eq!(65u8.to_ascii().to_char(), 'A');
+        assert_eq!('A'.to_ascii().to_char(), 'A');
+        assert_eq!('A'.to_ascii().to_byte(), 65u8);
+    }
+
+    #[test]
+    fn test_ascii_vec() {
+        assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
+        assert_eq!("( ;".to_ascii(),                 v2ascii!([40, 32, 59]));
+        // FIXME: #5475 borrowchk error, owned vectors do not live long enough
+        // if chained-from directly
+        let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
+        let v = ~"( ;";              assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
+    }
+
+    #[test]
+    fn test_owned_ascii_vec() {
+        // FIXME: #4318 Compiler crashes on moving self
+        //assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59]));
+        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59]));
+        //assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0]));
+        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(),
+        //           v2ascii!(~[40, 32, 59, 0]));
+    }
+
+    #[test]
+    fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }
+
+    #[test]
+    fn test_ascii_to_str_consume() {
+        // FIXME: #4318 Compiler crashes on moving self
+        //assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;");
+    }
+
+    #[test] #[should_fail]
+    fn test_ascii_vec_fail_u8_slice()  { (&[127u8, 128u8, 255u8]).to_ascii(); }
+
+    #[test] #[should_fail]
+    fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
+
+    #[test] #[should_fail]
+    fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
+
+    #[test] #[should_fail]
+    fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
+}
+
+
+
+
+
+
+
+
diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs
index 980d4b445d0..7f8e6915add 100644
--- a/src/libcore/to_str.rs
+++ b/src/libcore/to_str.rs
@@ -20,6 +20,12 @@ pub trait ToStr {
     fn to_str(&self) -> ~str;
 }
 
+/// Trait for converting a type to a string, consuming it in the process.
+pub trait ToStrConsume {
+    // Cosume and convert to a string.
+    fn to_str_consume(self) -> ~str;
+}
+
 impl ToStr for bool {
     #[inline(always)]
     fn to_str(&self) -> ~str { ::bool::to_str(*self) }