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)]
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 {
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(())
}
}
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))
}
}