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`
This commit is contained in:
commit
0ced530534
5 changed files with 48 additions and 45 deletions
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue