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