From 517d5ac230ab11ba5e8810dacc5878065fcdd08e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 25 Mar 2021 11:43:03 +0100 Subject: Allow for reading raw bytes from rustc_serialize::Decoder without unsafe code. --- compiler/rustc_data_structures/src/fingerprint.rs | 36 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'compiler/rustc_data_structures') 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 Encodable 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 Encodable for Fingerprint { impl Decodable for Fingerprint { #[inline] fn decode(d: &mut D) -> Result { - let mut bytes: [MaybeUninit; 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)) } } -- cgit 1.4.1-3-g733a5