@@ -17,8 +17,9 @@ use cast;
1717use old_iter:: BaseIter ;
1818use iterator:: IteratorUtil ;
1919use 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 ) ]
2324pub 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.
136160pub 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
141169impl 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
149182impl 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
174212impl < ' 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
193236impl 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) ]
203265mod 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]
0 commit comments