core/slice/
specialize.rs

1use crate::clone::TrivialClone;
2use crate::ptr;
3
4pub(super) trait SpecFill<T> {
5    fn spec_fill(&mut self, value: T);
6}
7
8impl<T: Clone> SpecFill<T> for [T] {
9    default fn spec_fill(&mut self, value: T) {
10        if let Some((last, elems)) = self.split_last_mut() {
11            for el in elems {
12                el.clone_from(&value);
13            }
14
15            *last = value
16        }
17    }
18}
19
20impl<T: TrivialClone> SpecFill<T> for [T] {
21    default fn spec_fill(&mut self, value: T) {
22        for item in self.iter_mut() {
23            // SAFETY: `TrivialClone` indicates that this is equivalent to
24            // calling `Clone::clone`
25            *item = unsafe { ptr::read(&value) };
26        }
27    }
28}
29
30#[cfg(not(feature = "ferrocene_subset"))]
31impl SpecFill<u8> for [u8] {
32    fn spec_fill(&mut self, value: u8) {
33        // SAFETY: The pointer is derived from a reference, so it's writable.
34        unsafe {
35            crate::intrinsics::write_bytes(self.as_mut_ptr(), value, self.len());
36        }
37    }
38}
39
40#[cfg(not(feature = "ferrocene_subset"))]
41impl SpecFill<i8> for [i8] {
42    fn spec_fill(&mut self, value: i8) {
43        // SAFETY: The pointer is derived from a reference, so it's writable.
44        unsafe {
45            crate::intrinsics::write_bytes(self.as_mut_ptr(), value.cast_unsigned(), self.len());
46        }
47    }
48}
49
50#[cfg(not(feature = "ferrocene_subset"))]
51macro spec_fill_int {
52    ($($type:ty)*) => {$(
53        impl SpecFill<$type> for [$type] {
54            #[inline]
55            fn spec_fill(&mut self, value: $type) {
56                // We always take this fastpath in Miri for long slices as the manual `for`
57                // loop can be prohibitively slow.
58                if (cfg!(miri) && self.len() > 32) || crate::intrinsics::is_val_statically_known(value) {
59                    let bytes = value.to_ne_bytes();
60                    if value == <$type>::from_ne_bytes([bytes[0]; size_of::<$type>()]) {
61                        // SAFETY: The pointer is derived from a reference, so it's writable.
62                        unsafe {
63                            crate::intrinsics::write_bytes(self.as_mut_ptr(), bytes[0], self.len());
64                        }
65                        return;
66                    }
67                }
68                for item in self.iter_mut() {
69                    *item = value;
70                }
71            }
72        }
73    )*}
74}
75
76#[cfg(not(feature = "ferrocene_subset"))]
77spec_fill_int! { u16 i16 u32 i32 u64 i64 u128 i128 usize isize }