use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::stable_hasher;
-use rustc_data_structures::ToHex;
-
-const FINGERPRINT_LENGTH: usize = 16;
+use std::mem;
+use std::slice;
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
-pub struct Fingerprint(pub [u8; FINGERPRINT_LENGTH]);
+pub struct Fingerprint(u64, u64);
impl Fingerprint {
#[inline]
pub fn zero() -> Fingerprint {
- Fingerprint([0; FINGERPRINT_LENGTH])
+ Fingerprint(0, 0)
}
+ #[inline]
pub fn from_smaller_hash(hash: u64) -> Fingerprint {
- let mut result = Fingerprint::zero();
- result.0[0] = (hash >> 0) as u8;
- result.0[1] = (hash >> 8) as u8;
- result.0[2] = (hash >> 16) as u8;
- result.0[3] = (hash >> 24) as u8;
- result.0[4] = (hash >> 32) as u8;
- result.0[5] = (hash >> 40) as u8;
- result.0[6] = (hash >> 48) as u8;
- result.0[7] = (hash >> 56) as u8;
- result
+ Fingerprint(hash, hash)
}
+ #[inline]
pub fn to_smaller_hash(&self) -> u64 {
- ((self.0[0] as u64) << 0) |
- ((self.0[1] as u64) << 8) |
- ((self.0[2] as u64) << 16) |
- ((self.0[3] as u64) << 24) |
- ((self.0[4] as u64) << 32) |
- ((self.0[5] as u64) << 40) |
- ((self.0[6] as u64) << 48) |
- ((self.0[7] as u64) << 56)
+ self.0
}
pub fn to_hex(&self) -> String {
- self.0.to_hex()
+ format!("{:x}{:x}", self.0, self.1)
}
}
impl Encodable for Fingerprint {
#[inline]
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- for &byte in &self.0 {
- s.emit_u8(byte)?;
- }
- Ok(())
+ s.emit_u64(self.0.to_le())?;
+ s.emit_u64(self.1.to_le())
}
}
impl Decodable for Fingerprint {
#[inline]
fn decode<D: Decoder>(d: &mut D) -> Result<Fingerprint, D::Error> {
- let mut result = Fingerprint([0u8; FINGERPRINT_LENGTH]);
- for byte in &mut result.0 {
- *byte = d.read_u8()?;
- }
- Ok(result)
+ let _0 = u64::from_le(d.read_u64()?);
+ let _1 = u64::from_le(d.read_u64()?);
+ Ok(Fingerprint(_0, _1))
}
}
impl ::std::fmt::Display for Fingerprint {
fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
- for i in 0 .. self.0.len() {
- if i > 0 {
- write!(formatter, "::")?;
- }
-
- write!(formatter, "{}", self.0[i])?;
- }
- Ok(())
+ write!(formatter, "{:x}-{:x}", self.0, self.1)
}
}
-
impl stable_hasher::StableHasherResult for Fingerprint {
fn finish(mut hasher: stable_hasher::StableHasher<Self>) -> Self {
- let mut fingerprint = Fingerprint::zero();
- fingerprint.0.copy_from_slice(hasher.finalize());
- fingerprint
+ let hash_bytes: &[u8] = hasher.finalize();
+
+ assert!(hash_bytes.len() >= mem::size_of::<u64>() * 2);
+ let hash_bytes: &[u64] = unsafe {
+ slice::from_raw_parts(hash_bytes.as_ptr() as *const u64, 2)
+ };
+
+ // The bytes returned bytes the Blake2B hasher are always little-endian.
+ Fingerprint(u64::from_le(hash_bytes[0]), u64::from_le(hash_bytes[1]))
}
}
impl<CTX> stable_hasher::HashStable<CTX> for Fingerprint {
+ #[inline]
fn hash_stable<W: stable_hasher::StableHasherResult>(&self,
_: &mut CTX,
hasher: &mut stable_hasher::StableHasher<W>) {
- ::std::hash::Hash::hash(&self.0, hasher);
+ ::std::hash::Hash::hash(self, hasher);
}
}