]> git.lizzy.rs Git - rust.git/commitdiff
Allow for reading raw bytes from rustc_serialize::Decoder without unsafe code.
authorMichael Woerister <michaelwoerister@posteo>
Thu, 25 Mar 2021 10:43:03 +0000 (11:43 +0100)
committerMichael Woerister <michaelwoerister@posteo>
Thu, 25 Mar 2021 13:05:00 +0000 (14:05 +0100)
compiler/rustc_data_structures/src/fingerprint.rs
compiler/rustc_middle/src/ty/codec.rs
compiler/rustc_serialize/src/json.rs
compiler/rustc_serialize/src/opaque.rs
compiler/rustc_serialize/src/serialize.rs

index 81b115fac0d0e0ebc6cabfecc1de483f413f8edc..c0c0e7be3ca85cb36b95f4a9e6c933d08c833b65 100644 (file)
@@ -1,7 +1,7 @@
 use crate::stable_hasher;
 use rustc_serialize::{Decodable, Encodable};
+use std::convert::TryInto;
 use std::hash::{Hash, Hasher};
-use std::mem::{self, MaybeUninit};
 
 #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
 #[repr(C)]
@@ -60,6 +60,29 @@ pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
     pub fn to_hex(&self) -> String {
         format!("{:x}{:x}", self.0, self.1)
     }
+
+    #[inline]
+    pub fn to_le_bytes(&self) -> [u8; 16] {
+        // This seems to optimize to the same machine code as
+        // `unsafe { mem::transmute(*k) }`. Well done, LLVM! :)
+        let mut result = [0u8; 16];
+
+        let first_half: &mut [u8; 8] = (&mut result[0..8]).try_into().unwrap();
+        *first_half = self.0.to_le_bytes();
+
+        let second_half: &mut [u8; 8] = (&mut result[8..16]).try_into().unwrap();
+        *second_half = self.1.to_le_bytes();
+
+        result
+    }
+
+    #[inline]
+    pub fn from_le_bytes(bytes: [u8; 16]) -> Fingerprint {
+        Fingerprint(
+            u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
+            u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
+        )
+    }
 }
 
 impl std::fmt::Display for Fingerprint {
@@ -119,8 +142,7 @@ fn finish(hasher: stable_hasher::StableHasher) -> Self {
 impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
     #[inline]
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
-        s.emit_raw_bytes(&bytes)?;
+        s.emit_raw_bytes(&self.to_le_bytes()[..])?;
         Ok(())
     }
 }
@@ -128,11 +150,9 @@ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
 impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint {
     #[inline]
     fn decode(d: &mut D) -> Result<Self, D::Error> {
-        let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array();
-        d.read_raw_bytes(&mut bytes)?;
-
-        let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
-        Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
+        let mut bytes = [0u8; 16];
+        d.read_raw_bytes_into(&mut bytes[..])?;
+        Ok(Fingerprint::from_le_bytes(bytes))
     }
 }
 
index ea1caf58d780ff0e530d1279fb8d0b3503698113..3225efd05e4515c3e4754068822440bba222bf76 100644 (file)
@@ -473,8 +473,8 @@ impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
                 }
 
                 #[inline]
-                fn read_raw_bytes(&mut self, bytes: &mut [std::mem::MaybeUninit<u8>]) -> Result<(), Self::Error> {
-                    self.opaque.read_raw_bytes(bytes)
+                fn read_raw_bytes_into(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> {
+                    self.opaque.read_raw_bytes_into(bytes)
                 }
 
                 fn error(&mut self, err: &str) -> Self::Error {
index 51945ab435eab164cd17befb99a94508bdf6b066..78a102c5c23304ae043b05f5cc58b1a5bef82def 100644 (file)
 use std::io;
 use std::io::prelude::*;
 use std::mem::swap;
-use std::mem::MaybeUninit;
 use std::num::FpCategory as Fp;
 use std::ops::Index;
 use std::str::FromStr;
@@ -2367,10 +2366,9 @@ fn read_str(&mut self) -> DecodeResult<Cow<'_, str>> {
         expect!(self.pop(), String).map(Cow::Owned)
     }
 
-    fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), Self::Error> {
+    fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error> {
         for c in s.iter_mut() {
-            let h = self.read_u8()?;
-            unsafe { *c.as_mut_ptr() = h };
+            *c = self.read_u8()?;
         }
         Ok(())
     }
index c171593ebdca604c96cc19d7d3a35de3df0981c0..6e36184aff051776552c22f1bfb8b4272261c271 100644 (file)
@@ -1,6 +1,7 @@
 use crate::leb128::{self, max_leb128_len};
-use crate::serialize::{self, Decoder as _, Encoder as _};
+use crate::serialize::{self, Encoder as _};
 use std::borrow::Cow;
+use std::convert::TryInto;
 use std::fs::File;
 use std::io::{self, Write};
 use std::mem::MaybeUninit;
@@ -539,6 +540,13 @@ pub fn set_position(&mut self, pos: usize) {
     pub fn advance(&mut self, bytes: usize) {
         self.position += bytes;
     }
+
+    #[inline]
+    pub fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] {
+        let start = self.position;
+        self.position += bytes;
+        &self.data[start..self.position]
+    }
 }
 
 macro_rules! read_leb128 {
@@ -659,22 +667,10 @@ fn error(&mut self, err: &str) -> Self::Error {
     }
 
     #[inline]
-    fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
+    fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), String> {
         let start = self.position;
-        let end = start + s.len();
-        assert!(end <= self.data.len());
-
-        // SAFETY: Both `src` and `dst` point to at least `s.len()` elements:
-        // `src` points to at least `s.len()` elements by above assert, and
-        // `dst` points to `s.len()` elements by derivation from `s`.
-        unsafe {
-            let src = self.data.as_ptr().add(start);
-            let dst = s.as_mut_ptr() as *mut u8;
-            ptr::copy_nonoverlapping(src, dst, s.len());
-        }
-
-        self.position = end;
-
+        self.position += s.len();
+        s.copy_from_slice(&self.data[start..self.position]);
         Ok(())
     }
 }
@@ -705,16 +701,7 @@ fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
 impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
     fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
         let len = serialize::Decoder::read_usize(d)?;
-
-        let mut v = Vec::with_capacity(len);
-        let buf = &mut v.spare_capacity_mut()[..len];
-        d.read_raw_bytes(buf)?;
-
-        unsafe {
-            v.set_len(len);
-        }
-
-        Ok(v)
+        Ok(d.read_raw_bytes(len).to_owned())
     }
 }
 
@@ -750,13 +737,12 @@ fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
 impl<'a> serialize::Decodable<Decoder<'a>> for IntEncodedWithFixedSize {
     #[inline]
     fn decode(decoder: &mut Decoder<'a>) -> Result<IntEncodedWithFixedSize, String> {
-        let mut bytes = MaybeUninit::uninit_array();
         let _start_pos = decoder.position();
-        decoder.read_raw_bytes(&mut bytes)?;
+        let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
         let _end_pos = decoder.position();
         debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
 
-        let value = u64::from_le_bytes(unsafe { MaybeUninit::array_assume_init(bytes) });
+        let value = u64::from_le_bytes(bytes.try_into().unwrap());
         Ok(IntEncodedWithFixedSize(value))
     }
 }
index a3b02b7c34abab1d8e37160d305f1436401fb68b..d3e5f306970c519e0ec58f92795516a19374d00c 100644 (file)
@@ -7,7 +7,6 @@
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::marker::PhantomData;
-use std::mem::MaybeUninit;
 use std::path;
 use std::rc::Rc;
 use std::sync::Arc;
@@ -226,7 +225,7 @@ pub trait Decoder {
     fn read_f32(&mut self) -> Result<f32, Self::Error>;
     fn read_char(&mut self) -> Result<char, Self::Error>;
     fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error>;
-    fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), Self::Error>;
+    fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error>;
 
     // Compound types:
     #[inline]