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