summary refs log tree commit diff
path: root/compiler/rustc_data_structures/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-26 01:28:59 +0000
committerbors <bors@rust-lang.org>2021-03-26 01:28:59 +0000
commit0ced530534de1a77504b6229e6303d37a12282ee (patch)
tree57f7a07189e5b8761db60756feb05de6d1be9537 /compiler/rustc_data_structures/src
parent3debe9acb8df363e0b5363f23f8218c2d7919904 (diff)
parent517d5ac230ab11ba5e8810dacc5878065fcdd08e (diff)
downloadrust-0ced530534de1a77504b6229e6303d37a12282ee.tar.gz
rust-0ced530534de1a77504b6229e6303d37a12282ee.zip
Auto merge of #83465 - michaelwoerister:safe-read_raw_bytes, r=cjgillot
Allow for reading raw bytes from rustc_serialize::Decoder without unsafe code

The current `read_raw_bytes` method requires using `MaybeUninit` and `unsafe`. I don't think this is necessary. Let's see if a safe interface has any performance drawbacks.

This is a followup to #83273 and will make it easier to rebase #82183.

r? `@cjgillot`
Diffstat (limited to 'compiler/rustc_data_structures/src')
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs36
1 files changed, 28 insertions, 8 deletions
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index 81b115fac0d..c0c0e7be3ca 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -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 @@ impl 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 @@ impl_stable_hash_via_hash!(Fingerprint);
 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 @@ impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
 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))
     }
 }