@@ -114,7 +114,8 @@ macro_rules! cssparser_internal__to_lowercase {
114
114
( $input: expr, $BUFFER_SIZE: expr => $output: ident) => {
115
115
#[ allow( unsafe_code) ]
116
116
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( )
118
119
} ;
119
120
let input: & str = $input;
120
121
let $output = $crate:: _internal__to_lowercase( & mut buffer, input) ;
@@ -129,18 +130,28 @@ macro_rules! cssparser_internal__to_lowercase {
129
130
/// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
130
131
#[ doc( hidden) ]
131
132
#[ 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 > {
133
137
if let Some ( buffer) = buffer. get_mut ( ..input. len ( ) ) {
134
138
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
+ }
144
155
} else {
145
156
// Input is already lower-case
146
157
Some ( input)
0 commit comments