@@ -114,7 +114,8 @@ macro_rules! cssparser_internal__to_lowercase {
114114 ( $input: expr, $BUFFER_SIZE: expr => $output: ident) => {
115115 #[ allow( unsafe_code) ]
116116 let mut buffer = unsafe {
117- :: std:: mem:: MaybeUninit :: <[ :: std:: mem:: MaybeUninit <u8 >; $BUFFER_SIZE] >:: uninit( ) . assume_init( )
117+ :: std:: mem:: MaybeUninit :: <[ :: std:: mem:: MaybeUninit <u8 >; $BUFFER_SIZE] >:: uninit( )
118+ . assume_init( )
118119 } ;
119120 let input: & str = $input;
120121 let $output = $crate:: _internal__to_lowercase( & mut buffer, input) ;
@@ -129,18 +130,28 @@ macro_rules! cssparser_internal__to_lowercase {
129130/// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
130131#[ doc( hidden) ]
131132#[ allow( non_snake_case) ]
132- pub fn _internal__to_lowercase < ' a > ( buffer : & ' a mut [ MaybeUninit < u8 > ] , input : & ' a str ) -> Option < & ' a str > {
133+ pub fn _internal__to_lowercase < ' a > (
134+ buffer : & ' a mut [ MaybeUninit < u8 > ] ,
135+ input : & ' a str ,
136+ ) -> Option < & ' a str > {
133137 if let Some ( buffer) = buffer. get_mut ( ..input. len ( ) ) {
134138 if let Some ( first_uppercase) = input. bytes ( ) . position ( |byte| matches ! ( byte, b'A' ..=b'Z' ) ) {
135- let buffer = unsafe {
136- let ptr = buffer. as_mut_ptr ( ) as * mut u8 ;
137- std:: ptr:: copy_nonoverlapping ( input. as_bytes ( ) . as_ptr ( ) , ptr, input. len ( ) ) ;
138- & mut * ( buffer as * mut [ MaybeUninit < u8 > ] as * mut [ u8 ] )
139- } ;
140- buffer[ first_uppercase..] . make_ascii_lowercase ( ) ;
141- // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
142- // then lowercased (which preserves UTF-8 well-formedness)
143- unsafe { Some ( :: std:: str:: from_utf8_unchecked ( buffer) ) }
139+ unsafe {
140+ // This cast doesn’t change the pointer’s validity
141+ // since `u8` has the same layout as `MaybeUninit<u8>`:
142+ let input_bytes = & * ( input. as_bytes ( ) as * const [ u8 ] as * const [ MaybeUninit < u8 > ] ) ;
143+
144+ buffer. copy_from_slice ( & * input_bytes) ;
145+
146+ // Same as above re layout, plus these bytes have been initialized:
147+ let buffer = & mut * ( buffer as * mut [ MaybeUninit < u8 > ] as * mut [ u8 ] ) ;
148+
149+ buffer[ first_uppercase..] . make_ascii_lowercase ( ) ;
150+ // `buffer` was initialized to a copy of `input`
151+ // (which is `&str` so well-formed UTF-8)
152+ // then ASCII-lowercased (which preserves UTF-8 well-formedness):
153+ Some ( :: std:: str:: from_utf8_unchecked ( buffer) )
154+ }
144155 } else {
145156 // Input is already lower-case
146157 Some ( input)
0 commit comments