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 
142157unsafe  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