Skip to content

Commit 61ffee7

Browse files
committed
Added Ascii type
1 parent 4357cbf commit 61ffee7

File tree

4 files changed

+243
-3
lines changed

4 files changed

+243
-3
lines changed

src/libcore/prelude.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,14 @@ pub use path::Path;
4040
pub use path::PosixPath;
4141
pub use path::WindowsPath;
4242
pub use ptr::Ptr;
43+
// NOTE: Remove markers after snapshot
44+
#[cfg(stage1)]
45+
#[cfg(stage2)]
46+
#[cfg(stage3)]
47+
pub use str::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii};
4348
pub use str::{StrSlice, OwnedStr};
4449
pub use to_bytes::IterBytes;
45-
pub use to_str::ToStr;
50+
pub use to_str::{ToStr, ToStrConsume};
4651
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
4752
pub use vec::{CopyableVector, ImmutableVector};
4853
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};

src/libcore/str.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
* some heavy-duty uses, try std::rope.
1818
*/
1919

20+
// NOTE: Remove markers after snapshot
21+
#[cfg(stage1)]
22+
#[cfg(stage2)]
23+
#[cfg(stage3)]
24+
pub use self::ascii::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii};
25+
2026
use at_vec;
2127
use cast;
2228
use char;
@@ -34,6 +40,13 @@ use to_str::ToStr;
3440

3541
#[cfg(notest)] use cmp::{Eq, Ord, Equiv, TotalEq};
3642

43+
// NOTE: Remove markers after snapshot
44+
#[cfg(stage1)]
45+
#[cfg(stage2)]
46+
#[cfg(stage3)]
47+
#[path = "str/ascii.rs"]
48+
mod ascii;
49+
3750
/*
3851
Section: Creating a string
3952
*/
@@ -3347,15 +3360,15 @@ mod tests {
33473360
#[test]
33483361
fn test_shift_byte() {
33493362
let mut s = ~"ABC";
3350-
let b = raw::shift_byte(&mut s);
3363+
let b = unsafe{raw::shift_byte(&mut s)};
33513364
assert!((s == ~"BC"));
33523365
assert!((b == 65u8));
33533366
}
33543367
33553368
#[test]
33563369
fn test_pop_byte() {
33573370
let mut s = ~"ABC";
3358-
let b = raw::pop_byte(&mut s);
3371+
let b = unsafe{raw::pop_byte(&mut s)};
33593372
assert!((s == ~"AB"));
33603373
assert!((b == 67u8));
33613374
}

src/libcore/str/ascii.rs

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use to_str::{ToStr,ToStrConsume};
12+
use str;
13+
use cast;
14+
15+
#[cfg(test)]
16+
pub struct Ascii { priv chr: u8 }
17+
18+
/// Datatype to hold one ascii character. It is 8 bit long.
19+
#[cfg(notest)]
20+
#[deriving(Clone, Eq, Ord)]
21+
pub struct Ascii { priv chr: u8 }
22+
23+
pub impl Ascii {
24+
/// Converts a ascii character into a `u8`.
25+
fn to_byte(self) -> u8 {
26+
self.chr
27+
}
28+
29+
/// Converts a ascii character into a `char`.
30+
fn to_char(self) -> char {
31+
self.chr as char
32+
}
33+
}
34+
35+
impl ToStr for Ascii {
36+
fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) }
37+
}
38+
39+
/// Trait for converting into an ascii type.
40+
pub trait AsciiCast<T> {
41+
/// Convert to an ascii type
42+
fn to_ascii(&self) -> T;
43+
44+
/// Check if convertible to ascii
45+
fn is_ascii(&self) -> bool;
46+
}
47+
48+
impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
49+
fn to_ascii(&self) -> &'self[Ascii] {
50+
assert!(self.is_ascii());
51+
52+
unsafe{ cast::transmute(*self) }
53+
}
54+
55+
fn is_ascii(&self) -> bool {
56+
for self.each |b| {
57+
if !b.is_ascii() { return false; }
58+
}
59+
true
60+
}
61+
}
62+
63+
impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
64+
fn to_ascii(&self) -> &'self[Ascii] {
65+
assert!(self.is_ascii());
66+
67+
let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) };
68+
unsafe{ cast::transmute((p, len - 1))}
69+
}
70+
71+
fn is_ascii(&self) -> bool {
72+
for self.each |b| {
73+
if !b.is_ascii() { return false; }
74+
}
75+
true
76+
}
77+
}
78+
79+
impl AsciiCast<Ascii> for u8 {
80+
fn to_ascii(&self) -> Ascii {
81+
assert!(self.is_ascii());
82+
Ascii{ chr: *self }
83+
}
84+
85+
fn is_ascii(&self) -> bool {
86+
*self & 128 == 0u8
87+
}
88+
}
89+
90+
impl AsciiCast<Ascii> for char {
91+
fn to_ascii(&self) -> Ascii {
92+
assert!(self.is_ascii());
93+
Ascii{ chr: *self as u8 }
94+
}
95+
96+
fn is_ascii(&self) -> bool {
97+
*self - ('\x7F' & *self) == '\x00'
98+
}
99+
}
100+
101+
/// Trait for copyless casting to an ascii vector.
102+
pub trait OwnedAsciiCast {
103+
/// Take ownership and cast to an ascii vector without trailing zero element.
104+
fn to_ascii_consume(self) -> ~[Ascii];
105+
}
106+
107+
impl OwnedAsciiCast for ~[u8] {
108+
fn to_ascii_consume(self) -> ~[Ascii] {
109+
assert!(self.is_ascii());
110+
111+
unsafe {cast::transmute(self)}
112+
}
113+
}
114+
115+
impl OwnedAsciiCast for ~str {
116+
fn to_ascii_consume(self) -> ~[Ascii] {
117+
let mut s = self;
118+
unsafe {
119+
str::raw::pop_byte(&mut s);
120+
cast::transmute(s)
121+
}
122+
}
123+
}
124+
125+
/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
126+
pub trait ToStrAscii {
127+
/// Convert to a string.
128+
fn to_str_ascii(&self) -> ~str;
129+
}
130+
131+
impl<'self> ToStrAscii for &'self [Ascii] {
132+
fn to_str_ascii(&self) -> ~str {
133+
let mut cpy = self.to_owned();
134+
cpy.push(0u8.to_ascii());
135+
unsafe {cast::transmute(cpy)}
136+
}
137+
}
138+
139+
impl ToStrConsume for ~[Ascii] {
140+
fn to_str_consume(self) -> ~str {
141+
let mut cpy = self;
142+
cpy.push(0u8.to_ascii());
143+
unsafe {cast::transmute(cpy)}
144+
}
145+
}
146+
147+
// NOTE: Remove stage0 marker after snapshot
148+
#[cfg(and(test, not(stage0)))]
149+
mod tests {
150+
use super::*;
151+
use to_str::{ToStr,ToStrConsume};
152+
use str;
153+
use cast;
154+
155+
macro_rules! v2ascii (
156+
( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
157+
(~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
158+
)
159+
160+
#[test]
161+
fn test_ascii() {
162+
assert_eq!(65u8.to_ascii().to_byte(), 65u8);
163+
assert_eq!(65u8.to_ascii().to_char(), 'A');
164+
assert_eq!('A'.to_ascii().to_char(), 'A');
165+
assert_eq!('A'.to_ascii().to_byte(), 65u8);
166+
}
167+
168+
#[test]
169+
fn test_ascii_vec() {
170+
assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
171+
assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59]));
172+
// FIXME: #5475 borrowchk error, owned vectors do not live long enough
173+
// if chained-from directly
174+
let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
175+
let v = ~"( ;"; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
176+
}
177+
178+
#[test]
179+
fn test_owned_ascii_vec() {
180+
// FIXME: #4318 Compiler crashes on moving self
181+
//assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59]));
182+
//assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59]));
183+
//assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0]));
184+
//assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(),
185+
// v2ascii!(~[40, 32, 59, 0]));
186+
}
187+
188+
#[test]
189+
fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }
190+
191+
#[test]
192+
fn test_ascii_to_str_consume() {
193+
// FIXME: #4318 Compiler crashes on moving self
194+
//assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;");
195+
}
196+
197+
#[test] #[should_fail]
198+
fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); }
199+
200+
#[test] #[should_fail]
201+
fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
202+
203+
#[test] #[should_fail]
204+
fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
205+
206+
#[test] #[should_fail]
207+
fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
208+
}
209+
210+
211+
212+
213+
214+
215+
216+

src/libcore/to_str.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ pub trait ToStr {
2020
fn to_str(&self) -> ~str;
2121
}
2222

23+
/// Trait for converting a type to a string, consuming it in the process.
24+
pub trait ToStrConsume {
25+
// Cosume and convert to a string.
26+
fn to_str_consume(self) -> ~str;
27+
}
28+
2329
impl ToStr for bool {
2430
#[inline(always)]
2531
fn to_str(&self) -> ~str { ::bool::to_str(*self) }

0 commit comments

Comments
 (0)