]> git.lizzy.rs Git - rust.git/blob - src/librustc_data_structures/fingerprint.rs
Rollup merge of #60187 - tmandry:generator-optimization, r=eddyb
[rust.git] / src / librustc_data_structures / fingerprint.rs
1 use crate::stable_hasher;
2 use std::mem;
3 use serialize;
4 use serialize::opaque::{EncodeResult, Encoder, Decoder};
5
6 #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
7 pub struct Fingerprint(u64, u64);
8
9 impl Fingerprint {
10
11     pub const ZERO: Fingerprint = Fingerprint(0, 0);
12
13     #[inline]
14     pub fn from_smaller_hash(hash: u64) -> Fingerprint {
15         Fingerprint(hash, hash)
16     }
17
18     #[inline]
19     pub fn to_smaller_hash(&self) -> u64 {
20         self.0
21     }
22
23     #[inline]
24     pub fn as_value(&self) -> (u64, u64) {
25         (self.0, self.1)
26     }
27
28     #[inline]
29     pub fn combine(self, other: Fingerprint) -> Fingerprint {
30         // See https://stackoverflow.com/a/27952689 on why this function is
31         // implemented this way.
32         Fingerprint(
33             self.0.wrapping_mul(3).wrapping_add(other.0),
34             self.1.wrapping_mul(3).wrapping_add(other.1)
35         )
36     }
37
38     // Combines two hashes in an order independent way. Make sure this is what
39     // you want.
40     #[inline]
41     pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
42         let a = (self.1 as u128) << 64 | self.0 as u128;
43         let b = (other.1 as u128) << 64 | other.0 as u128;
44
45         let c = a.wrapping_add(b);
46
47         Fingerprint((c >> 64) as u64, c as u64)
48     }
49
50     pub fn to_hex(&self) -> String {
51         format!("{:x}{:x}", self.0, self.1)
52     }
53
54     pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
55         let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
56
57         encoder.emit_raw_bytes(&bytes);
58         Ok(())
59     }
60
61     pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
62         let mut bytes = [0; 16];
63
64         decoder.read_raw_bytes(&mut bytes)?;
65
66         let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
67
68         Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
69     }
70 }
71
72 impl ::std::fmt::Display for Fingerprint {
73     fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
74         write!(formatter, "{:x}-{:x}", self.0, self.1)
75     }
76 }
77
78 impl stable_hasher::StableHasherResult for Fingerprint {
79     #[inline]
80     fn finish(hasher: stable_hasher::StableHasher<Self>) -> Self {
81         let (_0, _1) = hasher.finalize();
82         Fingerprint(_0, _1)
83     }
84 }
85
86 impl_stable_hash_via_hash!(Fingerprint);
87
88 impl serialize::UseSpecializedEncodable for Fingerprint { }
89
90 impl serialize::UseSpecializedDecodable for Fingerprint { }
91
92 impl serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder {
93     fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
94         f.encode_opaque(self)
95     }
96 }
97
98 impl<'a> serialize::SpecializedDecoder<Fingerprint> for serialize::opaque::Decoder<'a> {
99     fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
100         Fingerprint::decode_opaque(self)
101     }
102 }