22 * License, v. 2.0. If a copy of the MPL was not distributed with this
33 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44
5+ use std:: mem:: MaybeUninit ;
6+
57// See docs of the `procedural-masquerade` crate.
68define_invoke_proc_macro ! ( cssparser_internal__invoke_proc_macro) ;
79
@@ -110,42 +112,16 @@ macro_rules! ascii_case_insensitive_phf_map {
110112#[ doc( hidden) ]
111113macro_rules! cssparser_internal__to_lowercase {
112114 ( $input: expr, $BUFFER_SIZE: expr => $output: ident) => {
113- let mut buffer;
114- // Safety: `buffer` is only used in `_internal__to_lowercase`,
115- // which initializes with `copy_from_slice` the part of the buffer it uses,
116- // before it uses it.
117115 #[ allow( unsafe_code) ]
118- let buffer = unsafe { cssparser_internal__uninit!( buffer, $BUFFER_SIZE) } ;
116+ let mut buffer = unsafe {
117+ :: std:: mem:: MaybeUninit :: <[ :: std:: mem:: MaybeUninit <u8 >; $BUFFER_SIZE] >:: uninit( )
118+ . assume_init( )
119+ } ;
119120 let input: & str = $input;
120- let $output = $crate:: _internal__to_lowercase( buffer, input) ;
121+ let $output = $crate:: _internal__to_lowercase( & mut buffer, input) ;
121122 } ;
122123}
123124
124- #[ cfg( has_std__mem__MaybeUninit) ]
125- #[ macro_export]
126- #[ doc( hidden) ]
127- macro_rules! cssparser_internal__uninit {
128- ( $buffer: ident, $BUFFER_SIZE: expr) => {
129- {
130- $buffer = :: std:: mem:: MaybeUninit :: <[ u8 ; $BUFFER_SIZE] >:: uninit( ) ;
131- & mut * ( $buffer. as_mut_ptr( ) )
132- }
133- }
134- }
135-
136- // FIXME: remove this when we require Rust 1.36
137- #[ cfg( not( has_std__mem__MaybeUninit) ) ]
138- #[ macro_export]
139- #[ doc( hidden) ]
140- macro_rules! cssparser_internal__uninit {
141- ( $buffer: ident, $BUFFER_SIZE: expr) => {
142- {
143- $buffer = :: std:: mem:: uninitialized:: <[ u8 ; $BUFFER_SIZE] >( ) ;
144- & mut $buffer
145- }
146- }
147- }
148-
149125/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
150126///
151127/// **This function is not part of the public API. It can change or be removed between any verisons.**
@@ -154,14 +130,28 @@ macro_rules! cssparser_internal__uninit {
154130/// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
155131#[ doc( hidden) ]
156132#[ allow( non_snake_case) ]
157- pub fn _internal__to_lowercase < ' a > ( buffer : & ' a mut [ 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 > {
158137 if let Some ( buffer) = buffer. get_mut ( ..input. len ( ) ) {
159138 if let Some ( first_uppercase) = input. bytes ( ) . position ( |byte| matches ! ( byte, b'A' ..=b'Z' ) ) {
160- buffer. copy_from_slice ( input. as_bytes ( ) ) ;
161- buffer[ first_uppercase..] . make_ascii_lowercase ( ) ;
162- // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
163- // then lowercased (which preserves UTF-8 well-formedness)
164- 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+ }
165155 } else {
166156 // Input is already lower-case
167157 Some ( input)
0 commit comments