Use in-memory representation for Fingerprint that is more amenable to hashing.
This commit is contained in:
parent
6af8c6c7d1
commit
474cc91440
1 changed files with 26 additions and 46 deletions
|
|
@ -10,95 +10,75 @@
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue