1- use std:: any:: Any ;
2- use std:: cmp:: { Ord , PartialOrd } ;
3- use std:: fmt:: { self , Debug , Formatter } ;
4- use std:: hash:: { Hash , Hasher } ;
5- use std:: ops:: Deref ;
1+ use std:: hash:: Hash ;
62
73use siphasher:: sip128:: { Hasher128 , SipHasher13 } ;
84
@@ -13,129 +9,3 @@ pub fn hash<T: Hash>(value: &T) -> u128 {
139 value. hash ( & mut state) ;
1410 state. finish128 ( ) . as_u128 ( )
1511}
16-
17- /// Produce a 128-bit hash of a value's type and the value.
18- ///
19- /// Prefer this over `hash` if the resulting hash is used for the same purpose
20- /// as hashes of other types.
21- #[ inline]
22- pub fn hash_any < T : Hash + ' static > ( item : & T ) -> u128 {
23- // Also hash the TypeId because the type might be converted
24- // through an unsized coercion.
25- let mut state = SipHasher13 :: new ( ) ;
26- item. type_id ( ) . hash ( & mut state) ;
27- item. hash ( & mut state) ;
28- state. finish128 ( ) . as_u128 ( )
29- }
30-
31- /// A wrapper type with precomputed hash.
32- ///
33- /// This is useful if you want to pass large values of `T` to memoized
34- /// functions. Especially recursive structures like trees benefit from
35- /// intermediate prehashed nodes.
36- ///
37- /// Note that for a value `v` of type `T`, `hash(v)` is not necessarily equal to
38- /// `hash(Prehashed::new(v))`. Writing the precomputed hash into a hasher's
39- /// state produces different output than writing the value's parts directly.
40- /// However, that seldomly matters as you are typically either dealing with
41- /// values of type `T` or with values of type `Prehashed<T>`, not a mix of both.
42- ///
43- /// # Equality
44- /// Because comemo uses high-quality 128 bit hashes in all places, the risk of a
45- /// hash collision is reduced to an absolute minimum. Therefore, this type
46- /// additionally provides `PartialEq` and `Eq` implementations that compare by
47- /// hash instead of by value. For this to be correct, your hash implementation
48- /// **must feed all information relevant to the `PartialEq` impl to the
49- /// hasher.**
50- #[ derive( Copy , Clone ) ]
51- pub struct Prehashed < T : ?Sized > {
52- /// The precomputed hash.
53- hash : u128 ,
54- /// The wrapped item.
55- item : T ,
56- }
57-
58- impl < T : Hash + ' static > Prehashed < T > {
59- /// Compute an item's hash and wrap it.
60- #[ inline]
61- pub fn new ( item : T ) -> Self {
62- Self { hash : hash_any ( & item) , item }
63- }
64-
65- /// Return the wrapped value.
66- #[ inline]
67- pub fn into_inner ( self ) -> T {
68- self . item
69- }
70-
71- /// Update the wrapped value and recompute the hash.
72- #[ inline]
73- pub fn update < F , U > ( & mut self , f : F ) -> U
74- where
75- F : FnOnce ( & mut T ) -> U ,
76- {
77- let output = f ( & mut self . item ) ;
78- self . hash = hash_any ( & self . item ) ;
79- output
80- }
81- }
82-
83- impl < T : ?Sized > Deref for Prehashed < T > {
84- type Target = T ;
85-
86- #[ inline]
87- fn deref ( & self ) -> & Self :: Target {
88- & self . item
89- }
90- }
91-
92- impl < T : Hash + ' static > From < T > for Prehashed < T > {
93- #[ inline]
94- fn from ( value : T ) -> Self {
95- Self :: new ( value)
96- }
97- }
98-
99- impl < T : ?Sized > Hash for Prehashed < T > {
100- #[ inline]
101- fn hash < H : Hasher > ( & self , state : & mut H ) {
102- state. write_u128 ( self . hash ) ;
103- }
104- }
105-
106- impl < T : Debug + ?Sized > Debug for Prehashed < T > {
107- #[ inline]
108- fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
109- self . item . fmt ( f)
110- }
111- }
112-
113- impl < T : Default + Hash + ' static > Default for Prehashed < T > {
114- #[ inline]
115- fn default ( ) -> Self {
116- Self :: new ( T :: default ( ) )
117- }
118- }
119-
120- impl < T : ?Sized > Eq for Prehashed < T > { }
121-
122- impl < T : ?Sized > PartialEq for Prehashed < T > {
123- #[ inline]
124- fn eq ( & self , other : & Self ) -> bool {
125- self . hash == other. hash
126- }
127- }
128-
129- impl < T : Ord + ?Sized > Ord for Prehashed < T > {
130- #[ inline]
131- fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
132- self . item . cmp ( & other. item )
133- }
134- }
135-
136- impl < T : PartialOrd + ?Sized > PartialOrd for Prehashed < T > {
137- #[ inline]
138- fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
139- self . item . partial_cmp ( & other. item )
140- }
141- }
0 commit comments