@@ -20,7 +20,8 @@ use iter::Iterator;
20
20
use mem;
21
21
use option:: { Option , Some , None } ;
22
22
use slice:: { ImmutableVector , MutableVector , Vector } ;
23
- use str:: { Str , StrAllocating , StrSlice } ;
23
+ use str:: { Str , StrSlice } ;
24
+ use str;
24
25
use string:: String ;
25
26
use to_string:: IntoStr ;
26
27
use vec:: Vec ;
@@ -366,91 +367,112 @@ impl IntoBytes for Vec<Ascii> {
366
367
}
367
368
}
368
369
370
+
369
371
/// Extension methods for ASCII-subset only operations on owned strings
370
- pub trait OwnedStrAsciiExt {
372
+ pub trait OwnedAsciiExt {
371
373
/// Convert the string to ASCII upper case:
372
374
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
373
375
/// but non-ASCII letters are unchanged.
374
- fn into_ascii_upper ( self ) -> String ;
376
+ fn into_ascii_upper ( self ) -> Self ;
375
377
376
378
/// Convert the string to ASCII lower case:
377
379
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
378
380
/// but non-ASCII letters are unchanged.
379
- fn into_ascii_lower ( self ) -> String ;
381
+ fn into_ascii_lower ( self ) -> Self ;
380
382
}
381
383
382
384
/// Extension methods for ASCII-subset only operations on string slices
383
- pub trait StrAsciiExt {
385
+ pub trait AsciiExt < T > {
384
386
/// Makes a copy of the string in ASCII upper case:
385
387
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
386
388
/// but non-ASCII letters are unchanged.
387
- fn to_ascii_upper ( & self ) -> String ;
389
+ fn to_ascii_upper ( & self ) -> T ;
388
390
389
391
/// Makes a copy of the string in ASCII lower case:
390
392
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
391
393
/// but non-ASCII letters are unchanged.
392
- fn to_ascii_lower ( & self ) -> String ;
394
+ fn to_ascii_lower ( & self ) -> T ;
393
395
394
396
/// Check that two strings are an ASCII case-insensitive match.
395
397
/// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
396
398
/// but without allocating and copying temporary strings.
397
- fn eq_ignore_ascii_case ( & self , other : & str ) -> bool ;
399
+ fn eq_ignore_ascii_case ( & self , other : Self ) -> bool ;
398
400
}
399
401
400
- impl < ' a > StrAsciiExt for & ' a str {
402
+ impl < ' a > AsciiExt < String > for & ' a str {
401
403
#[ inline]
402
404
fn to_ascii_upper ( & self ) -> String {
403
- unsafe { str_copy_map_bytes ( * self , & ASCII_UPPER_MAP ) }
405
+ // Vec<u8>::to_ascii_upper() preserves the UTF-8 invariant.
406
+ unsafe { str:: raw:: from_utf8_owned ( self . as_bytes ( ) . to_ascii_upper ( ) ) }
404
407
}
405
408
406
409
#[ inline]
407
410
fn to_ascii_lower ( & self ) -> String {
408
- unsafe { str_copy_map_bytes ( * self , & ASCII_LOWER_MAP ) }
411
+ // Vec<u8>::to_ascii_lower() preserves the UTF-8 invariant.
412
+ unsafe { str:: raw:: from_utf8_owned ( self . as_bytes ( ) . to_ascii_lower ( ) ) }
409
413
}
410
414
411
415
#[ inline]
412
416
fn eq_ignore_ascii_case ( & self , other : & str ) -> bool {
413
- self . len ( ) == other. len ( ) &&
414
- self . as_bytes ( ) . iter ( ) . zip ( other. as_bytes ( ) . iter ( ) ) . all (
415
- |( byte_self, byte_other) | {
416
- ASCII_LOWER_MAP [ * byte_self as uint ] ==
417
- ASCII_LOWER_MAP [ * byte_other as uint ]
418
- } )
417
+ self . as_bytes ( ) . eq_ignore_ascii_case ( other. as_bytes ( ) )
419
418
}
420
419
}
421
420
422
- impl OwnedStrAsciiExt for String {
421
+ impl OwnedAsciiExt for String {
423
422
#[ inline]
424
423
fn into_ascii_upper ( self ) -> String {
425
- unsafe { str_map_bytes ( self , & ASCII_UPPER_MAP ) }
424
+ // Vec<u8>::into_ascii_upper() preserves the UTF-8 invariant.
425
+ unsafe { str:: raw:: from_utf8_owned ( self . into_bytes ( ) . into_ascii_upper ( ) ) }
426
426
}
427
427
428
428
#[ inline]
429
429
fn into_ascii_lower ( self ) -> String {
430
- unsafe { str_map_bytes ( self , & ASCII_LOWER_MAP ) }
430
+ // Vec<u8>::into_ascii_lower() preserves the UTF-8 invariant.
431
+ unsafe { str:: raw:: from_utf8_owned ( self . into_bytes ( ) . into_ascii_lower ( ) ) }
431
432
}
432
433
}
433
434
434
- #[ inline]
435
- unsafe fn str_map_bytes ( string : String , map : & [ u8 , ..256 ] ) -> String {
436
- let mut bytes = string. into_bytes( ) ;
435
+ impl < ' a > AsciiExt < Vec < u8 > > for & ' a [ u8 ] {
436
+ #[ inline]
437
+ fn to_ascii_upper ( & self ) -> Vec < u8 > {
438
+ self . iter ( ) . map ( |& byte| ASCII_UPPER_MAP [ byte as uint ] ) . collect ( )
439
+ }
437
440
438
- for b in bytes. mut_iter ( ) {
439
- * b = map[ * b as uint ] ;
441
+ #[ inline]
442
+ fn to_ascii_lower ( & self ) -> Vec < u8 > {
443
+ self . iter ( ) . map ( |& byte| ASCII_LOWER_MAP [ byte as uint ] ) . collect ( )
440
444
}
441
445
442
- String :: from_utf8 ( bytes) . unwrap ( )
446
+ #[ inline]
447
+ fn eq_ignore_ascii_case ( & self , other : & [ u8 ] ) -> bool {
448
+ self . len ( ) == other. len ( ) &&
449
+ self . iter ( ) . zip ( other. iter ( ) ) . all (
450
+ |( byte_self, byte_other) | {
451
+ ASCII_LOWER_MAP [ * byte_self as uint ] ==
452
+ ASCII_LOWER_MAP [ * byte_other as uint ]
453
+ } )
454
+ }
443
455
}
444
456
445
- #[ inline]
446
- unsafe fn str_copy_map_bytes( string : & str , map : & [ u8 , ..256 ] ) -> String {
447
- let mut s = String : : from_str( string) ;
448
- for b in s. as_mut_bytes( ) . mut_iter( ) {
449
- * b = map[ * b as uint] ;
457
+ impl OwnedAsciiExt for Vec < u8 > {
458
+ #[ inline]
459
+ fn into_ascii_upper ( mut self ) -> Vec < u8 > {
460
+ for byte in self . mut_iter ( ) {
461
+ * byte = ASCII_UPPER_MAP [ * byte as uint ] ;
462
+ }
463
+ self
464
+ }
465
+
466
+ #[ inline]
467
+ fn into_ascii_lower ( mut self ) -> Vec < u8 > {
468
+ for byte in self . mut_iter ( ) {
469
+ * byte = ASCII_LOWER_MAP [ * byte as uint ] ;
470
+ }
471
+ self
450
472
}
451
- s. into_string( )
452
473
}
453
474
475
+
454
476
pub static ASCII_LOWER_MAP : [ u8 , ..256 ] = [
455
477
0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
456
478
0x08 , 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x0f ,
0 commit comments