@@ -469,19 +469,37 @@ impl<Static: StaticAtomSet> Deserialize for Atom<Static> {
469469// We don't need to implement is_ascii because there's no performance improvement
470470// over the one from &str.
471471impl < Static : StaticAtomSet > Atom < Static > {
472+ fn from_mutated_str < F : FnOnce ( & mut str ) > ( s : & str , f : F ) -> Self {
473+ let mut buffer: [ u8 ; 64 ] = unsafe { mem:: uninitialized ( ) } ;
474+ if let Some ( buffer_prefix) = buffer. get_mut ( ..s. len ( ) ) {
475+ buffer_prefix. copy_from_slice ( s. as_bytes ( ) ) ;
476+ // FIXME: use from std::str when stable https://github.com/rust-lang/rust/issues/41119
477+ pub unsafe fn from_utf8_unchecked_mut ( v : & mut [ u8 ] ) -> & mut str {
478+ mem:: transmute ( v)
479+ }
480+ let as_str = unsafe { from_utf8_unchecked_mut ( buffer_prefix) } ;
481+ f ( as_str) ;
482+ Atom :: from ( & * as_str)
483+ } else {
484+ let mut string = s. to_owned ( ) ;
485+ f ( & mut string) ;
486+ Atom :: from ( string)
487+ }
488+ }
489+
472490 pub fn to_ascii_uppercase ( & self ) -> Self {
473- for b in self . bytes ( ) {
491+ for ( i , b ) in self . bytes ( ) . enumerate ( ) {
474492 if let b'a' ... b'z' = b {
475- return Atom :: from ( ( & * * self ) . to_ascii_uppercase ( ) )
493+ return Atom :: from_mutated_str ( self , |s| s [ i.. ] . make_ascii_uppercase ( ) )
476494 }
477495 }
478496 self . clone ( )
479497 }
480498
481499 pub fn to_ascii_lowercase ( & self ) -> Self {
482- for b in self . bytes ( ) {
500+ for ( i , b ) in self . bytes ( ) . enumerate ( ) {
483501 if let b'A' ... b'Z' = b {
484- return Atom :: from ( ( & * * self ) . to_ascii_lowercase ( ) )
502+ return Atom :: from_mutated_str ( self , |s| s [ i.. ] . make_ascii_lowercase ( ) )
485503 }
486504 }
487505 self . clone ( )
0 commit comments