Skip to content

Commit c9e7bb7

Browse files
committed
Improved std::ascii
- Fixed tests - Added methods - Renamed casting methods to be shorter closes #7150
1 parent 90b999a commit c9e7bb7

File tree

3 files changed

+91
-25
lines changed

3 files changed

+91
-25
lines changed

src/libstd/prelude.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub use path::Path;
6161
pub use path::PosixPath;
6262
pub use path::WindowsPath;
6363
pub use ptr::RawPtr;
64-
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
64+
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume};
6565
pub use str::{Str, StrVector, StrSlice, OwnedStr, StrUtil, NullTerminatedStr};
6666
pub use from_str::{FromStr};
6767
pub use to_bytes::IterBytes;

src/libstd/str/ascii.rs

+89-23
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ use cast;
1717
use old_iter::BaseIter;
1818
use iterator::IteratorUtil;
1919
use vec::{CopyableVector, ImmutableVector, OwnedVector};
20+
use to_bytes::IterBytes;
2021

21-
/// Datatype to hold one ascii character. It is 8 bit long.
22+
/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
2223
#[deriving(Clone, Eq)]
2324
pub struct Ascii { priv chr: u8 }
2425

@@ -72,6 +73,9 @@ pub trait AsciiCast<T> {
7273
/// Convert to an ascii type
7374
fn to_ascii(&self) -> T;
7475

76+
/// Convert to an ascii type, not doing any range asserts
77+
unsafe fn to_ascii_nocheck(&self) -> T;
78+
7579
/// Check if convertible to ascii
7680
fn is_ascii(&self) -> bool;
7781
}
@@ -80,7 +84,12 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
8084
#[inline(always)]
8185
fn to_ascii(&self) -> &'self[Ascii] {
8286
assert!(self.is_ascii());
83-
unsafe{ cast::transmute(*self) }
87+
unsafe {self.to_ascii_nocheck()}
88+
}
89+
90+
#[inline(always)]
91+
unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
92+
cast::transmute(*self)
8493
}
8594

8695
#[inline(always)]
@@ -96,8 +105,13 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
96105
#[inline(always)]
97106
fn to_ascii(&self) -> &'self[Ascii] {
98107
assert!(self.is_ascii());
99-
let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) };
100-
unsafe{ cast::transmute((p, len - 1))}
108+
unsafe {self.to_ascii_nocheck()}
109+
}
110+
111+
#[inline(always)]
112+
unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
113+
let (p,len): (*u8, uint) = cast::transmute(*self);
114+
cast::transmute((p, len - 1))
101115
}
102116

103117
#[inline(always)]
@@ -110,6 +124,11 @@ impl AsciiCast<Ascii> for u8 {
110124
#[inline(always)]
111125
fn to_ascii(&self) -> Ascii {
112126
assert!(self.is_ascii());
127+
unsafe {self.to_ascii_nocheck()}
128+
}
129+
130+
#[inline(always)]
131+
unsafe fn to_ascii_nocheck(&self) -> Ascii {
113132
Ascii{ chr: *self }
114133
}
115134

@@ -123,6 +142,11 @@ impl AsciiCast<Ascii> for char {
123142
#[inline(always)]
124143
fn to_ascii(&self) -> Ascii {
125144
assert!(self.is_ascii());
145+
unsafe {self.to_ascii_nocheck()}
146+
}
147+
148+
#[inline(always)]
149+
unsafe fn to_ascii_nocheck(&self) -> Ascii {
126150
Ascii{ chr: *self as u8 }
127151
}
128152

@@ -135,26 +159,38 @@ impl AsciiCast<Ascii> for char {
135159
/// Trait for copyless casting to an ascii vector.
136160
pub trait OwnedAsciiCast {
137161
/// Take ownership and cast to an ascii vector without trailing zero element.
138-
fn to_ascii_consume(self) -> ~[Ascii];
162+
fn into_ascii(self) -> ~[Ascii];
163+
164+
/// Take ownership and cast to an ascii vector without trailing zero element.
165+
/// Does not perform validation checks.
166+
unsafe fn into_ascii_nocheck(self) -> ~[Ascii];
139167
}
140168

141169
impl OwnedAsciiCast for ~[u8] {
142170
#[inline(always)]
143-
fn to_ascii_consume(self) -> ~[Ascii] {
171+
fn into_ascii(self) -> ~[Ascii] {
144172
assert!(self.is_ascii());
145-
unsafe {cast::transmute(self)}
173+
unsafe {self.into_ascii_nocheck()}
174+
}
175+
176+
#[inline(always)]
177+
unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
178+
cast::transmute(self)
146179
}
147180
}
148181

149182
impl OwnedAsciiCast for ~str {
150183
#[inline(always)]
151-
fn to_ascii_consume(self) -> ~[Ascii] {
184+
fn into_ascii(self) -> ~[Ascii] {
152185
assert!(self.is_ascii());
153-
let mut s = self;
154-
unsafe {
155-
str::raw::pop_byte(&mut s);
156-
cast::transmute(s)
157-
}
186+
unsafe {self.into_ascii_nocheck()}
187+
}
188+
189+
#[inline(always)]
190+
unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
191+
let mut r: ~[Ascii] = cast::transmute(self);
192+
r.pop();
193+
r
158194
}
159195
}
160196

@@ -169,6 +205,8 @@ pub trait AsciiStr {
169205
/// Convert to vector representing a upper cased ascii string.
170206
fn to_upper(&self) -> ~[Ascii];
171207

208+
/// Compares two Ascii strings ignoring case
209+
fn eq_ignore_case(self, other: &[Ascii]) -> bool;
172210
}
173211

174212
impl<'self> AsciiStr for &'self [Ascii] {
@@ -188,20 +226,45 @@ impl<'self> AsciiStr for &'self [Ascii] {
188226
fn to_upper(&self) -> ~[Ascii] {
189227
self.map(|a| a.to_upper())
190228
}
229+
230+
#[inline(always)]
231+
fn eq_ignore_case(self, other: &[Ascii]) -> bool {
232+
do self.iter().zip(other.iter()).all |(&a, &b)| { a.eq_ignore_case(b) }
233+
}
191234
}
192235

193236
impl ToStrConsume for ~[Ascii] {
194237
#[inline(always)]
195-
fn to_str_consume(self) -> ~str {
238+
fn into_str(self) -> ~str {
196239
let mut cpy = self;
197240
cpy.push(0u8.to_ascii());
198241
unsafe {cast::transmute(cpy)}
199242
}
200243
}
201244

245+
impl IterBytes for Ascii {
246+
#[inline(always)]
247+
fn iter_bytes(&self, _lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool {
248+
f([self.to_byte()])
249+
}
250+
}
251+
252+
/// Trait to convert to a owned byte array by consuming self
253+
pub trait ToBytesConsume {
254+
/// Converts to a owned byte array by consuming self
255+
fn into_bytes(self) -> ~[u8];
256+
}
257+
258+
impl ToBytesConsume for ~[Ascii] {
259+
fn into_bytes(self) -> ~[u8] {
260+
unsafe {cast::transmute(self)}
261+
}
262+
}
263+
202264
#[cfg(test)]
203265
mod tests {
204266
use super::*;
267+
use to_bytes::ToBytes;
205268

206269
macro_rules! v2ascii (
207270
( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
@@ -245,6 +308,8 @@ mod tests {
245308
assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca");
246309
assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;");
247310
311+
assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
312+
248313
assert!("".is_ascii());
249314
assert!("a".is_ascii());
250315
assert!(!"\u2009".is_ascii());
@@ -253,21 +318,22 @@ mod tests {
253318

254319
#[test]
255320
fn test_owned_ascii_vec() {
256-
// FIXME: #4318 Compiler crashes on moving self
257-
//assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59]));
258-
//assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59]));
259-
//assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0]));
260-
//assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(),
261-
// v2ascii!(~[40, 32, 59, 0]));
321+
assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59]));
322+
assert_eq!((~[40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59]));
262323
}
263324
264325
#[test]
265326
fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }
266327
267328
#[test]
268-
fn test_ascii_to_str_consume() {
269-
// FIXME: #4318 Compiler crashes on moving self
270-
//assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;");
329+
fn test_ascii_into_str() {
330+
assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;");
331+
}
332+
333+
#[test]
334+
fn test_ascii_to_bytes() {
335+
assert_eq!(v2ascii!(~[40, 32, 59]).to_bytes(false), ~[40u8, 32u8, 59u8]);
336+
assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), ~[40u8, 32u8, 59u8]);
271337
}
272338
273339
#[test] #[should_fail]

src/libstd/to_str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub trait ToStr {
3131
/// Trait for converting a type to a string, consuming it in the process.
3232
pub trait ToStrConsume {
3333
/// Cosume and convert to a string.
34-
fn to_str_consume(self) -> ~str;
34+
fn into_str(self) -> ~str;
3535
}
3636

3737
impl ToStr for () {

0 commit comments

Comments
 (0)