@@ -17,8 +17,9 @@ use cast;
17
17
use old_iter:: BaseIter ;
18
18
use iterator:: IteratorUtil ;
19
19
use vec:: { CopyableVector , ImmutableVector , OwnedVector } ;
20
+ use to_bytes:: IterBytes ;
20
21
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 .
22
23
#[ deriving( Clone , Eq ) ]
23
24
pub struct Ascii { priv chr: u8 }
24
25
@@ -72,6 +73,9 @@ pub trait AsciiCast<T> {
72
73
/// Convert to an ascii type
73
74
fn to_ascii ( & self ) -> T ;
74
75
76
+ /// Convert to an ascii type, not doing any range asserts
77
+ unsafe fn to_ascii_nocheck ( & self ) -> T ;
78
+
75
79
/// Check if convertible to ascii
76
80
fn is_ascii ( & self ) -> bool ;
77
81
}
@@ -80,7 +84,12 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
80
84
#[ inline( always) ]
81
85
fn to_ascii ( & self ) -> & ' self [ Ascii ] {
82
86
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 )
84
93
}
85
94
86
95
#[ inline( always) ]
@@ -96,8 +105,13 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
96
105
#[ inline( always) ]
97
106
fn to_ascii ( & self ) -> & ' self [ Ascii ] {
98
107
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 ) )
101
115
}
102
116
103
117
#[ inline( always) ]
@@ -110,6 +124,11 @@ impl AsciiCast<Ascii> for u8 {
110
124
#[ inline( always) ]
111
125
fn to_ascii ( & self ) -> Ascii {
112
126
assert ! ( self . is_ascii( ) ) ;
127
+ unsafe { self . to_ascii_nocheck ( ) }
128
+ }
129
+
130
+ #[ inline( always) ]
131
+ unsafe fn to_ascii_nocheck ( & self ) -> Ascii {
113
132
Ascii { chr : * self }
114
133
}
115
134
@@ -123,6 +142,11 @@ impl AsciiCast<Ascii> for char {
123
142
#[ inline( always) ]
124
143
fn to_ascii ( & self ) -> Ascii {
125
144
assert ! ( self . is_ascii( ) ) ;
145
+ unsafe { self . to_ascii_nocheck ( ) }
146
+ }
147
+
148
+ #[ inline( always) ]
149
+ unsafe fn to_ascii_nocheck ( & self ) -> Ascii {
126
150
Ascii { chr : * self as u8 }
127
151
}
128
152
@@ -135,26 +159,38 @@ impl AsciiCast<Ascii> for char {
135
159
/// Trait for copyless casting to an ascii vector.
136
160
pub trait OwnedAsciiCast {
137
161
/// 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 ] ;
139
167
}
140
168
141
169
impl OwnedAsciiCast for ~[ u8 ] {
142
170
#[ inline( always) ]
143
- fn to_ascii_consume ( self ) -> ~[ Ascii ] {
171
+ fn into_ascii ( self ) -> ~[ Ascii ] {
144
172
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 )
146
179
}
147
180
}
148
181
149
182
impl OwnedAsciiCast for ~str {
150
183
#[ inline( always) ]
151
- fn to_ascii_consume ( self ) -> ~[ Ascii ] {
184
+ fn into_ascii ( self ) -> ~[ Ascii ] {
152
185
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
158
194
}
159
195
}
160
196
@@ -169,6 +205,8 @@ pub trait AsciiStr {
169
205
/// Convert to vector representing a upper cased ascii string.
170
206
fn to_upper ( & self ) -> ~[ Ascii ] ;
171
207
208
+ /// Compares two Ascii strings ignoring case
209
+ fn eq_ignore_case ( self , other : & [ Ascii ] ) -> bool ;
172
210
}
173
211
174
212
impl < ' self > AsciiStr for & ' self [ Ascii ] {
@@ -188,20 +226,45 @@ impl<'self> AsciiStr for &'self [Ascii] {
188
226
fn to_upper ( & self ) -> ~[ Ascii ] {
189
227
self . map ( |a| a. to_upper ( ) )
190
228
}
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
+ }
191
234
}
192
235
193
236
impl ToStrConsume for ~[ Ascii ] {
194
237
#[ inline( always) ]
195
- fn to_str_consume ( self ) -> ~str {
238
+ fn into_str ( self ) -> ~str {
196
239
let mut cpy = self ;
197
240
cpy. push ( 0u8 . to_ascii ( ) ) ;
198
241
unsafe { cast:: transmute ( cpy) }
199
242
}
200
243
}
201
244
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
+
202
264
#[ cfg( test) ]
203
265
mod tests {
204
266
use super :: * ;
267
+ use to_bytes:: ToBytes ;
205
268
206
269
macro_rules! v2ascii (
207
270
( [ $( $e: expr) ,* ] ) => ( [ $( Ascii { chr: $e} ) ,* ] ) ;
@@ -245,6 +308,8 @@ mod tests {
245
308
assert_eq!(" YMCA ".to_ascii().to_lower().to_str_ascii(), ~" ymca");
246
309
assert_eq!(" abcDEFxyz: . ; ".to_ascii().to_upper().to_str_ascii(), ~" ABCDEFXYZ : . ; ");
247
310
311
+ assert!(" aBcDeF& ?#".to_ascii().eq_ignore_case(" AbCdEf & ?#".to_ascii()));
312
+
248
313
assert!(" ".is_ascii());
249
314
assert!(" a".is_ascii());
250
315
assert!(!"\u2009 " . is_ascii( ) ) ;
@@ -253,21 +318,22 @@ mod tests {
253
318
254
319
#[ test]
255
320
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]));
262
323
}
263
324
264
325
#[test]
265
326
fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~" ( ; "); }
266
327
267
328
#[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]);
271
337
}
272
338
273
339
#[test] #[should_fail]
0 commit comments