1212
1313use to_str:: { ToStr , IntoStr } ;
1414use str;
15+ use str:: Str ;
1516use str:: StrSlice ;
1617use str:: OwnedStr ;
1718use container:: Container ;
1819use cast;
1920use iter:: Iterator ;
20- use vec:: { ImmutableVector , MutableVector } ;
21+ use vec:: { ImmutableVector , MutableVector , Vector } ;
2122use to_bytes:: IterBytes ;
22- use option:: { Some , None } ;
23+ use option:: { Option , Some , None } ;
2324
2425/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
2526#[ deriving( Clone , Eq , Ord , TotalOrd , TotalEq ) ]
@@ -135,8 +136,22 @@ impl ToStr for Ascii {
135136
136137/// Trait for converting into an ascii type.
137138pub trait AsciiCast < T > {
138- /// Convert to an ascii type
139- fn to_ascii ( & self ) -> T ;
139+ /// Convert to an ascii type, fail on non-ASCII input.
140+ #[ inline]
141+ fn to_ascii ( & self ) -> T {
142+ assert ! ( self . is_ascii( ) ) ;
143+ unsafe { self . to_ascii_nocheck ( ) }
144+ }
145+
146+ /// Convert to an ascii type, return None on non-ASCII input.
147+ #[ inline]
148+ fn to_ascii_opt ( & self ) -> Option < T > {
149+ if self . is_ascii ( ) {
150+ Some ( unsafe { self . to_ascii_nocheck ( ) } )
151+ } else {
152+ None
153+ }
154+ }
140155
141156 /// Convert to an ascii type, not doing any range asserts
142157 unsafe fn to_ascii_nocheck ( & self ) -> T ;
@@ -146,12 +161,6 @@ pub trait AsciiCast<T> {
146161}
147162
148163impl < ' a > AsciiCast < & ' a [ Ascii ] > for & ' a [ u8 ] {
149- #[ inline]
150- fn to_ascii ( & self ) -> & ' a [ Ascii ] {
151- assert ! ( self . is_ascii( ) ) ;
152- unsafe { self . to_ascii_nocheck ( ) }
153- }
154-
155164 #[ inline]
156165 unsafe fn to_ascii_nocheck ( & self ) -> & ' a [ Ascii ] {
157166 cast:: transmute ( * self )
@@ -167,12 +176,6 @@ impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
167176}
168177
169178impl < ' a > AsciiCast < & ' a [ Ascii ] > for & ' a str {
170- #[ inline]
171- fn to_ascii ( & self ) -> & ' a [ Ascii ] {
172- assert ! ( self . is_ascii( ) ) ;
173- unsafe { self . to_ascii_nocheck ( ) }
174- }
175-
176179 #[ inline]
177180 unsafe fn to_ascii_nocheck ( & self ) -> & ' a [ Ascii ] {
178181 cast:: transmute ( * self )
@@ -185,12 +188,6 @@ impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
185188}
186189
187190impl AsciiCast < Ascii > for u8 {
188- #[ inline]
189- fn to_ascii ( & self ) -> Ascii {
190- assert ! ( self . is_ascii( ) ) ;
191- unsafe { self . to_ascii_nocheck ( ) }
192- }
193-
194191 #[ inline]
195192 unsafe fn to_ascii_nocheck ( & self ) -> Ascii {
196193 Ascii { chr : * self }
@@ -203,12 +200,6 @@ impl AsciiCast<Ascii> for u8 {
203200}
204201
205202impl AsciiCast < Ascii > for char {
206- #[ inline]
207- fn to_ascii ( & self ) -> Ascii {
208- assert ! ( self . is_ascii( ) ) ;
209- unsafe { self . to_ascii_nocheck ( ) }
210- }
211-
212203 #[ inline]
213204 unsafe fn to_ascii_nocheck ( & self ) -> Ascii {
214205 Ascii { chr : * self as u8 }
@@ -222,8 +213,25 @@ impl AsciiCast<Ascii> for char {
222213
223214/// Trait for copyless casting to an ascii vector.
224215pub trait OwnedAsciiCast {
225- /// Take ownership and cast to an ascii vector.
226- fn into_ascii ( self ) -> ~[ Ascii ] ;
216+ /// Check if convertible to ascii
217+ fn is_ascii ( & self ) -> bool ;
218+
219+ /// Take ownership and cast to an ascii vector. Fail on non-ASCII input.
220+ #[ inline]
221+ fn into_ascii ( self ) -> ~[ Ascii ] {
222+ assert ! ( self . is_ascii( ) ) ;
223+ unsafe { self . into_ascii_nocheck ( ) }
224+ }
225+
226+ /// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
227+ #[ inline]
228+ fn into_ascii_opt ( self ) -> Option < ~[ Ascii ] > {
229+ if self . is_ascii ( ) {
230+ Some ( unsafe { self . into_ascii_nocheck ( ) } )
231+ } else {
232+ None
233+ }
234+ }
227235
228236 /// Take ownership and cast to an ascii vector.
229237 /// Does not perform validation checks.
@@ -232,9 +240,8 @@ pub trait OwnedAsciiCast {
232240
233241impl OwnedAsciiCast for ~[ u8 ] {
234242 #[ inline]
235- fn into_ascii ( self ) -> ~[ Ascii ] {
236- assert ! ( self . is_ascii( ) ) ;
237- unsafe { self . into_ascii_nocheck ( ) }
243+ fn is_ascii ( & self ) -> bool {
244+ self . as_slice ( ) . is_ascii ( )
238245 }
239246
240247 #[ inline]
@@ -245,9 +252,8 @@ impl OwnedAsciiCast for ~[u8] {
245252
246253impl OwnedAsciiCast for ~str {
247254 #[ inline]
248- fn into_ascii ( self ) -> ~[ Ascii ] {
249- assert ! ( self . is_ascii( ) ) ;
250- unsafe { self . into_ascii_nocheck ( ) }
255+ fn is_ascii ( & self ) -> bool {
256+ self . as_slice ( ) . is_ascii ( )
251257 }
252258
253259 #[ inline]
@@ -475,9 +481,11 @@ mod tests {
475481 use super :: * ;
476482 use str:: from_char;
477483 use char:: from_u32;
484+ use option:: { Some , None } ;
478485
479486 macro_rules! v2ascii (
480487 ( [ $( $e: expr) ,* ] ) => ( [ $( Ascii { chr: $e} ) ,* ] ) ;
488+ ( & [ $( $e: expr) ,* ] ) => ( & [ $( Ascii { chr: $e} ) ,* ] ) ;
481489 ( ~[ $( $e: expr) ,* ] ) => ( ~[ $( Ascii { chr: $e} ) ,* ] ) ;
482490 )
483491
@@ -569,6 +577,32 @@ mod tests {
569577 #[test] #[should_fail]
570578 fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
571579
580+ fn test_opt() {
581+ assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
582+ assert_eq!(255u8.to_ascii_opt(), None);
583+
584+ assert_eq!('A'.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
585+ assert_eq!('λ'.to_ascii_opt(), None);
586+
587+ assert_eq!(" zoä华".to_ascii_opt(), None);
588+
589+ assert_eq!((&[127u8, 128u8, 255u8]).to_ascii_opt(), None);
590+
591+ let v = [40u8, 32u8, 59u8];
592+ assert_eq!(v.to_ascii_opt(), Some(v2ascii!(&[40, 32, 59])));
593+ let v = [127u8, 128u8, 255u8];
594+ assert_eq!(v.to_ascii_opt(), None);
595+
596+ assert_eq!(" ( ; ".to_ascii_opt(), Some(v2ascii!(&[40, 32, 59])));
597+ assert_eq!(" zoä华".to_ascii_opt(), None);
598+
599+ assert_eq!((~[40u8, 32u8, 59u8]).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59])));
600+ assert_eq!((~[127u8, 128u8, 255u8]).into_ascii_opt(), None);
601+
602+ assert_eq!((~" ( ; ").into_ascii_opt(), Some(v2ascii!(~[40, 32, 59])));
603+ assert_eq!((~" zoä华").into_ascii_opt(), None);
604+ }
605+
572606 #[test]
573607 fn test_to_ascii_upper() {
574608 assert_eq!(" url( ) URL ( ) uRl( ) ürl".to_ascii_upper(), ~" URL ( ) URL ( ) URL ( ) üRL");
0 commit comments