Skip to content

Commit 4721b69

Browse files
committed
Use [T]::copy_from_slice instead of ptr::copy_nonoverlapping
1 parent 20602d1 commit 4721b69

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

src/macros.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)