about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe8472 <git@infinite-source.de>2021-03-17 23:45:03 +0100
committerThe8472 <git@infinite-source.de>2021-03-18 00:25:20 +0100
commitdd166da8f83c0792e2652cf64a2a2fd5f635d11c (patch)
tree32f1a77b45ff1a6ae54bcc2a1abad3bc65139ff3
parent36f1f04f18b89ba4a999bcfd6584663fd6fc1c5d (diff)
downloadrust-dd166da8f83c0792e2652cf64a2a2fd5f635d11c.tar.gz
rust-dd166da8f83c0792e2652cf64a2a2fd5f635d11c.zip
generalize slice::fill specialization for byte-sized items
This should also improve cross-crate inlining since the method is generic
-rw-r--r--library/core/src/slice/specialize.rs49
1 files changed, 13 insertions, 36 deletions
diff --git a/library/core/src/slice/specialize.rs b/library/core/src/slice/specialize.rs
index 16a9588989c..425cf71626f 100644
--- a/library/core/src/slice/specialize.rs
+++ b/library/core/src/slice/specialize.rs
@@ -1,3 +1,4 @@
+use crate::mem::{size_of, transmute_copy};
 use crate::ptr::write_bytes;
 
 pub(super) trait SpecFill<T> {
@@ -17,42 +18,18 @@ impl<T: Clone> SpecFill<T> for [T] {
 }
 
 impl<T: Copy> SpecFill<T> for [T] {
-    default fn spec_fill(&mut self, value: T) {
-        for item in self.iter_mut() {
-            *item = value;
-        }
-    }
-}
-
-impl SpecFill<u8> for [u8] {
-    fn spec_fill(&mut self, value: u8) {
-        // SAFETY: this is slice of u8
-        unsafe {
-            let ptr = self.as_mut_ptr();
-            let len = self.len();
-            write_bytes(ptr, value, len);
-        }
-    }
-}
-
-impl SpecFill<i8> for [i8] {
-    fn spec_fill(&mut self, value: i8) {
-        // SAFETY: this is slice of i8
-        unsafe {
-            let ptr = self.as_mut_ptr();
-            let len = self.len();
-            write_bytes(ptr, value as u8, len);
-        }
-    }
-}
-
-impl SpecFill<bool> for [bool] {
-    fn spec_fill(&mut self, value: bool) {
-        // SAFETY: this is slice of bool
-        unsafe {
-            let ptr = self.as_mut_ptr();
-            let len = self.len();
-            write_bytes(ptr, value as u8, len);
+    fn spec_fill(&mut self, value: T) {
+        if size_of::<T>() == 1 {
+            // SAFETY: The size_of check above ensures that values are 1 byte wide, as required
+            // for the transmute and write_bytes
+            unsafe {
+                let value: u8 = transmute_copy(&value);
+                write_bytes(self.as_mut_ptr(), value, self.len());
+            }
+        } else {
+            for item in self.iter_mut() {
+                *item = value;
+            }
         }
     }
 }