rustc_data_structures/
fingerprint.rs
1use std::hash::{Hash, Hasher};
2
3use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
4
5use crate::stable_hasher::{
6 FromStableHash, Hash64, StableHasherHash, impl_stable_traits_for_trivial_type,
7};
8
9#[cfg(test)]
10mod tests;
11
12#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
13#[repr(C)]
14pub struct Fingerprint(u64, u64);
15
16pub trait FingerprintComponent {
17 fn as_u64(&self) -> u64;
18}
19
20impl FingerprintComponent for Hash64 {
21 #[inline]
22 fn as_u64(&self) -> u64 {
23 Hash64::as_u64(*self)
24 }
25}
26
27impl FingerprintComponent for u64 {
28 #[inline]
29 fn as_u64(&self) -> u64 {
30 *self
31 }
32}
33
34impl Fingerprint {
35 pub const ZERO: Fingerprint = Fingerprint(0, 0);
36
37 #[inline]
38 pub fn new<A, B>(_0: A, _1: B) -> Fingerprint
39 where
40 A: FingerprintComponent,
41 B: FingerprintComponent,
42 {
43 Fingerprint(_0.as_u64(), _1.as_u64())
44 }
45
46 #[inline]
47 pub fn to_smaller_hash(&self) -> Hash64 {
48 Hash64::new(self.0.wrapping_mul(3).wrapping_add(self.1))
54 }
55
56 #[inline]
57 pub fn split(&self) -> (Hash64, Hash64) {
58 (Hash64::new(self.0), Hash64::new(self.1))
59 }
60
61 #[inline]
62 pub fn combine(self, other: Fingerprint) -> Fingerprint {
63 Fingerprint(
66 self.0.wrapping_mul(3).wrapping_add(other.0),
67 self.1.wrapping_mul(3).wrapping_add(other.1),
68 )
69 }
70
71 #[inline]
72 pub(crate) fn as_u128(self) -> u128 {
73 u128::from(self.1) << 64 | u128::from(self.0)
74 }
75
76 #[inline]
79 pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
80 let a = u128::from(self.1) << 64 | u128::from(self.0);
81 let b = u128::from(other.1) << 64 | u128::from(other.0);
82
83 let c = a.wrapping_add(b);
84
85 Fingerprint(c as u64, (c >> 64) as u64)
86 }
87
88 pub fn to_hex(&self) -> String {
89 format!("{:x}{:x}", self.0, self.1)
90 }
91
92 #[inline]
93 pub fn to_le_bytes(&self) -> [u8; 16] {
94 let mut result = [0u8; 16];
97
98 let first_half: &mut [u8; 8] = (&mut result[0..8]).try_into().unwrap();
99 *first_half = self.0.to_le_bytes();
100
101 let second_half: &mut [u8; 8] = (&mut result[8..16]).try_into().unwrap();
102 *second_half = self.1.to_le_bytes();
103
104 result
105 }
106
107 #[inline]
108 pub fn from_le_bytes(bytes: [u8; 16]) -> Fingerprint {
109 Fingerprint(
110 u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
111 u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
112 )
113 }
114}
115
116impl std::fmt::Display for Fingerprint {
117 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 write!(formatter, "{:x}-{:x}", self.0, self.1)
119 }
120}
121
122impl Hash for Fingerprint {
123 #[inline]
124 fn hash<H: Hasher>(&self, state: &mut H) {
125 state.write_fingerprint(self);
126 }
127}
128
129trait FingerprintHasher {
130 fn write_fingerprint(&mut self, fingerprint: &Fingerprint);
131}
132
133impl<H: Hasher> FingerprintHasher for H {
134 #[inline]
135 default fn write_fingerprint(&mut self, fingerprint: &Fingerprint) {
136 self.write_u64(fingerprint.0);
137 self.write_u64(fingerprint.1);
138 }
139}
140
141impl FingerprintHasher for crate::unhash::Unhasher {
142 #[inline]
143 fn write_fingerprint(&mut self, fingerprint: &Fingerprint) {
144 self.write_u64(fingerprint.0.wrapping_add(fingerprint.1));
157 }
158}
159
160impl FromStableHash for Fingerprint {
161 type Hash = StableHasherHash;
162
163 #[inline]
164 fn from(StableHasherHash([_0, _1]): Self::Hash) -> Self {
165 Fingerprint(_0, _1)
166 }
167}
168
169impl_stable_traits_for_trivial_type!(Fingerprint);
170
171impl<E: Encoder> Encodable<E> for Fingerprint {
172 #[inline]
173 fn encode(&self, s: &mut E) {
174 s.emit_raw_bytes(&self.to_le_bytes());
175 }
176}
177
178impl<D: Decoder> Decodable<D> for Fingerprint {
179 #[inline]
180 fn decode(d: &mut D) -> Self {
181 Fingerprint::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap())
182 }
183}
184
185#[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))]
201#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
202pub struct PackedFingerprint(Fingerprint);
203
204impl std::fmt::Display for PackedFingerprint {
205 #[inline]
206 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 let copy = self.0;
209 copy.fmt(formatter)
210 }
211}
212
213impl<E: Encoder> Encodable<E> for PackedFingerprint {
214 #[inline]
215 fn encode(&self, s: &mut E) {
216 let copy = self.0;
218 copy.encode(s);
219 }
220}
221
222impl<D: Decoder> Decodable<D> for PackedFingerprint {
223 #[inline]
224 fn decode(d: &mut D) -> Self {
225 Self(Fingerprint::decode(d))
226 }
227}
228
229impl From<Fingerprint> for PackedFingerprint {
230 #[inline]
231 fn from(f: Fingerprint) -> PackedFingerprint {
232 PackedFingerprint(f)
233 }
234}
235
236impl From<PackedFingerprint> for Fingerprint {
237 #[inline]
238 fn from(f: PackedFingerprint) -> Fingerprint {
239 f.0
240 }
241}