]> git.lizzy.rs Git - rust.git/blob - src/librustc_data_structures/fingerprint.rs
Rollup merge of #75485 - RalfJung:pin, r=nagisa
[rust.git] / src / librustc_data_structures / fingerprint.rs
1 use crate::stable_hasher;
2 use rustc_serialize::{
3     opaque::{self, EncodeResult},
4     Decodable, Encodable,
5 };
6 use std::mem;
7
8 #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
9 pub struct Fingerprint(u64, u64);
10
11 impl Fingerprint {
12     pub const ZERO: Fingerprint = Fingerprint(0, 0);
13
14     #[inline]
15     pub fn from_smaller_hash(hash: u64) -> Fingerprint {
16         Fingerprint(hash, hash)
17     }
18
19     #[inline]
20     pub fn to_smaller_hash(&self) -> u64 {
21         self.0
22     }
23
24     #[inline]
25     pub fn as_value(&self) -> (u64, u64) {
26         (self.0, self.1)
27     }
28
29     #[inline]
30     pub fn combine(self, other: Fingerprint) -> Fingerprint {
31         // See https://stackoverflow.com/a/27952689 on why this function is
32         // implemented this way.
33         Fingerprint(
34             self.0.wrapping_mul(3).wrapping_add(other.0),
35             self.1.wrapping_mul(3).wrapping_add(other.1),
36         )
37     }
38
39     // Combines two hashes in an order independent way. Make sure this is what
40     // you want.
41     #[inline]
42     pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
43         let a = u128::from(self.1) << 64 | u128::from(self.0);
44         let b = u128::from(other.1) << 64 | u128::from(other.0);
45
46         let c = a.wrapping_add(b);
47
48         Fingerprint((c >> 64) as u64, c as u64)
49     }
50
51     pub fn to_hex(&self) -> String {
52         format!("{:x}{:x}", self.0, self.1)
53     }
54
55     pub fn encode_opaque(&self, encoder: &mut opaque::Encoder) -> EncodeResult {
56         let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
57
58         encoder.emit_raw_bytes(&bytes);
59         Ok(())
60     }
61
62     pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> {
63         let mut bytes = [0; 16];
64
65         decoder.read_raw_bytes(&mut bytes)?;
66
67         let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
68
69         Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
70     }
71 }
72
73 impl ::std::fmt::Display for Fingerprint {
74     fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
75         write!(formatter, "{:x}-{:x}", self.0, self.1)
76     }
77 }
78
79 impl stable_hasher::StableHasherResult for Fingerprint {
80     #[inline]
81     fn finish(hasher: stable_hasher::StableHasher) -> Self {
82         let (_0, _1) = hasher.finalize();
83         Fingerprint(_0, _1)
84     }
85 }
86
87 impl_stable_hash_via_hash!(Fingerprint);
88
89 impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
90     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
91         s.encode_fingerprint(self)
92     }
93 }
94
95 impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint {
96     fn decode(d: &mut D) -> Result<Self, D::Error> {
97         d.decode_fingerprint()
98     }
99 }
100
101 pub trait FingerprintEncoder: rustc_serialize::Encoder {
102     fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>;
103 }
104
105 pub trait FingerprintDecoder: rustc_serialize::Decoder {
106     fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error>;
107 }
108
109 impl<E: rustc_serialize::Encoder> FingerprintEncoder for E {
110     default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> {
111         panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::<E>());
112     }
113 }
114
115 impl FingerprintEncoder for opaque::Encoder {
116     fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult {
117         f.encode_opaque(self)
118     }
119 }
120
121 impl<D: rustc_serialize::Decoder> FingerprintDecoder for D {
122     default fn decode_fingerprint(&mut self) -> Result<Fingerprint, D::Error> {
123         panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::<D>());
124     }
125 }
126 impl FingerprintDecoder for opaque::Decoder<'_> {
127     fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
128         Fingerprint::decode_opaque(self)
129     }
130 }