1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker //
15*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
16*9356374aSAndroid Build Coastguard Worker // File: hash.h
17*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
18*9356374aSAndroid Build Coastguard Worker //
19*9356374aSAndroid Build Coastguard Worker // This header file defines the Abseil `hash` library and the Abseil hashing
20*9356374aSAndroid Build Coastguard Worker // framework. This framework consists of the following:
21*9356374aSAndroid Build Coastguard Worker //
22*9356374aSAndroid Build Coastguard Worker // * The `absl::Hash` functor, which is used to invoke the hasher within the
23*9356374aSAndroid Build Coastguard Worker // Abseil hashing framework. `absl::Hash<T>` supports most basic types and
24*9356374aSAndroid Build Coastguard Worker // a number of Abseil types out of the box.
25*9356374aSAndroid Build Coastguard Worker // * `AbslHashValue`, an extension point that allows you to extend types to
26*9356374aSAndroid Build Coastguard Worker // support Abseil hashing without requiring you to define a hashing
27*9356374aSAndroid Build Coastguard Worker // algorithm.
28*9356374aSAndroid Build Coastguard Worker // * `HashState`, a type-erased class which implements the manipulation of the
29*9356374aSAndroid Build Coastguard Worker // hash state (H) itself; contains member functions `combine()`,
30*9356374aSAndroid Build Coastguard Worker // `combine_contiguous()`, and `combine_unordered()`; and which you can use
31*9356374aSAndroid Build Coastguard Worker // to contribute to an existing hash state when hashing your types.
32*9356374aSAndroid Build Coastguard Worker //
33*9356374aSAndroid Build Coastguard Worker // Unlike `std::hash` or other hashing frameworks, the Abseil hashing framework
34*9356374aSAndroid Build Coastguard Worker // provides most of its utility by abstracting away the hash algorithm (and its
35*9356374aSAndroid Build Coastguard Worker // implementation) entirely. Instead, a type invokes the Abseil hashing
36*9356374aSAndroid Build Coastguard Worker // framework by simply combining its state with the state of known, hashable
37*9356374aSAndroid Build Coastguard Worker // types. Hashing of that combined state is separately done by `absl::Hash`.
38*9356374aSAndroid Build Coastguard Worker //
39*9356374aSAndroid Build Coastguard Worker // One should assume that a hash algorithm is chosen randomly at the start of
40*9356374aSAndroid Build Coastguard Worker // each process. E.g., `absl::Hash<int>{}(9)` in one process and
41*9356374aSAndroid Build Coastguard Worker // `absl::Hash<int>{}(9)` in another process are likely to differ.
42*9356374aSAndroid Build Coastguard Worker //
43*9356374aSAndroid Build Coastguard Worker // `absl::Hash` may also produce different values from different dynamically
44*9356374aSAndroid Build Coastguard Worker // loaded libraries. For this reason, `absl::Hash` values must never cross
45*9356374aSAndroid Build Coastguard Worker // boundaries in dynamically loaded libraries (including when used in types like
46*9356374aSAndroid Build Coastguard Worker // hash containers.)
47*9356374aSAndroid Build Coastguard Worker //
48*9356374aSAndroid Build Coastguard Worker // `absl::Hash` is intended to strongly mix input bits with a target of passing
49*9356374aSAndroid Build Coastguard Worker // an [Avalanche Test](https://en.wikipedia.org/wiki/Avalanche_effect).
50*9356374aSAndroid Build Coastguard Worker //
51*9356374aSAndroid Build Coastguard Worker // Example:
52*9356374aSAndroid Build Coastguard Worker //
53*9356374aSAndroid Build Coastguard Worker // // Suppose we have a class `Circle` for which we want to add hashing:
54*9356374aSAndroid Build Coastguard Worker // class Circle {
55*9356374aSAndroid Build Coastguard Worker // public:
56*9356374aSAndroid Build Coastguard Worker // ...
57*9356374aSAndroid Build Coastguard Worker // private:
58*9356374aSAndroid Build Coastguard Worker // std::pair<int, int> center_;
59*9356374aSAndroid Build Coastguard Worker // int radius_;
60*9356374aSAndroid Build Coastguard Worker // };
61*9356374aSAndroid Build Coastguard Worker //
62*9356374aSAndroid Build Coastguard Worker // // To add hashing support to `Circle`, we simply need to add a free
63*9356374aSAndroid Build Coastguard Worker // // (non-member) function `AbslHashValue()`, and return the combined hash
64*9356374aSAndroid Build Coastguard Worker // // state of the existing hash state and the class state. You can add such a
65*9356374aSAndroid Build Coastguard Worker // // free function using a friend declaration within the body of the class:
66*9356374aSAndroid Build Coastguard Worker // class Circle {
67*9356374aSAndroid Build Coastguard Worker // public:
68*9356374aSAndroid Build Coastguard Worker // ...
69*9356374aSAndroid Build Coastguard Worker // template <typename H>
70*9356374aSAndroid Build Coastguard Worker // friend H AbslHashValue(H h, const Circle& c) {
71*9356374aSAndroid Build Coastguard Worker // return H::combine(std::move(h), c.center_, c.radius_);
72*9356374aSAndroid Build Coastguard Worker // }
73*9356374aSAndroid Build Coastguard Worker // ...
74*9356374aSAndroid Build Coastguard Worker // };
75*9356374aSAndroid Build Coastguard Worker //
76*9356374aSAndroid Build Coastguard Worker // For more information, see Adding Type Support to `absl::Hash` below.
77*9356374aSAndroid Build Coastguard Worker //
78*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_HASH_HASH_H_
79*9356374aSAndroid Build Coastguard Worker #define ABSL_HASH_HASH_H_
80*9356374aSAndroid Build Coastguard Worker
81*9356374aSAndroid Build Coastguard Worker #include <tuple>
82*9356374aSAndroid Build Coastguard Worker #include <utility>
83*9356374aSAndroid Build Coastguard Worker
84*9356374aSAndroid Build Coastguard Worker #include "absl/functional/function_ref.h"
85*9356374aSAndroid Build Coastguard Worker #include "absl/hash/internal/hash.h"
86*9356374aSAndroid Build Coastguard Worker
87*9356374aSAndroid Build Coastguard Worker namespace absl {
88*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
89*9356374aSAndroid Build Coastguard Worker
90*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
91*9356374aSAndroid Build Coastguard Worker // `absl::Hash`
92*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
93*9356374aSAndroid Build Coastguard Worker //
94*9356374aSAndroid Build Coastguard Worker // `absl::Hash<T>` is a convenient general-purpose hash functor for any type `T`
95*9356374aSAndroid Build Coastguard Worker // satisfying any of the following conditions (in order):
96*9356374aSAndroid Build Coastguard Worker //
97*9356374aSAndroid Build Coastguard Worker // * T is an arithmetic or pointer type
98*9356374aSAndroid Build Coastguard Worker // * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary
99*9356374aSAndroid Build Coastguard Worker // hash state `H`.
100*9356374aSAndroid Build Coastguard Worker // - T defines a specialization of `std::hash<T>`
101*9356374aSAndroid Build Coastguard Worker //
102*9356374aSAndroid Build Coastguard Worker // `absl::Hash` intrinsically supports the following types:
103*9356374aSAndroid Build Coastguard Worker //
104*9356374aSAndroid Build Coastguard Worker // * All integral types (including bool)
105*9356374aSAndroid Build Coastguard Worker // * All enum types
106*9356374aSAndroid Build Coastguard Worker // * All floating-point types (although hashing them is discouraged)
107*9356374aSAndroid Build Coastguard Worker // * All pointer types, including nullptr_t
108*9356374aSAndroid Build Coastguard Worker // * std::pair<T1, T2>, if T1 and T2 are hashable
109*9356374aSAndroid Build Coastguard Worker // * std::tuple<Ts...>, if all the Ts... are hashable
110*9356374aSAndroid Build Coastguard Worker // * std::unique_ptr and std::shared_ptr
111*9356374aSAndroid Build Coastguard Worker // * All string-like types including:
112*9356374aSAndroid Build Coastguard Worker // * absl::Cord
113*9356374aSAndroid Build Coastguard Worker // * std::string (as well as any instance of std::basic_string that
114*9356374aSAndroid Build Coastguard Worker // uses one of {char, wchar_t, char16_t, char32_t} and its associated
115*9356374aSAndroid Build Coastguard Worker // std::char_traits)
116*9356374aSAndroid Build Coastguard Worker // * std::string_view (as well as any instance of std::basic_string_view
117*9356374aSAndroid Build Coastguard Worker // that uses one of {char, wchar_t, char16_t, char32_t} and its associated
118*9356374aSAndroid Build Coastguard Worker // std::char_traits)
119*9356374aSAndroid Build Coastguard Worker // * All the standard sequence containers (provided the elements are hashable)
120*9356374aSAndroid Build Coastguard Worker // * All the standard associative containers (provided the elements are
121*9356374aSAndroid Build Coastguard Worker // hashable)
122*9356374aSAndroid Build Coastguard Worker // * absl types such as the following:
123*9356374aSAndroid Build Coastguard Worker // * absl::string_view
124*9356374aSAndroid Build Coastguard Worker // * absl::uint128
125*9356374aSAndroid Build Coastguard Worker // * absl::Time, absl::Duration, and absl::TimeZone
126*9356374aSAndroid Build Coastguard Worker // * absl containers (provided the elements are hashable) such as the
127*9356374aSAndroid Build Coastguard Worker // following:
128*9356374aSAndroid Build Coastguard Worker // * absl::flat_hash_set, absl::node_hash_set, absl::btree_set
129*9356374aSAndroid Build Coastguard Worker // * absl::flat_hash_map, absl::node_hash_map, absl::btree_map
130*9356374aSAndroid Build Coastguard Worker // * absl::btree_multiset, absl::btree_multimap
131*9356374aSAndroid Build Coastguard Worker // * absl::InlinedVector
132*9356374aSAndroid Build Coastguard Worker // * absl::FixedArray
133*9356374aSAndroid Build Coastguard Worker //
134*9356374aSAndroid Build Coastguard Worker // When absl::Hash is used to hash an unordered container with a custom hash
135*9356374aSAndroid Build Coastguard Worker // functor, the elements are hashed using default absl::Hash semantics, not
136*9356374aSAndroid Build Coastguard Worker // the custom hash functor. This is consistent with the behavior of
137*9356374aSAndroid Build Coastguard Worker // operator==() on unordered containers, which compares elements pairwise with
138*9356374aSAndroid Build Coastguard Worker // operator==() rather than the custom equality functor. It is usually a
139*9356374aSAndroid Build Coastguard Worker // mistake to use either operator==() or absl::Hash on unordered collections
140*9356374aSAndroid Build Coastguard Worker // that use functors incompatible with operator==() equality.
141*9356374aSAndroid Build Coastguard Worker //
142*9356374aSAndroid Build Coastguard Worker // Note: the list above is not meant to be exhaustive. Additional type support
143*9356374aSAndroid Build Coastguard Worker // may be added, in which case the above list will be updated.
144*9356374aSAndroid Build Coastguard Worker //
145*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
146*9356374aSAndroid Build Coastguard Worker // absl::Hash Invocation Evaluation
147*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
148*9356374aSAndroid Build Coastguard Worker //
149*9356374aSAndroid Build Coastguard Worker // When invoked, `absl::Hash<T>` searches for supplied hash functions in the
150*9356374aSAndroid Build Coastguard Worker // following order:
151*9356374aSAndroid Build Coastguard Worker //
152*9356374aSAndroid Build Coastguard Worker // * Natively supported types out of the box (see above)
153*9356374aSAndroid Build Coastguard Worker // * Types for which an `AbslHashValue()` overload is provided (such as
154*9356374aSAndroid Build Coastguard Worker // user-defined types). See "Adding Type Support to `absl::Hash`" below.
155*9356374aSAndroid Build Coastguard Worker // * Types which define a `std::hash<T>` specialization
156*9356374aSAndroid Build Coastguard Worker //
157*9356374aSAndroid Build Coastguard Worker // The fallback to legacy hash functions exists mainly for backwards
158*9356374aSAndroid Build Coastguard Worker // compatibility. If you have a choice, prefer defining an `AbslHashValue`
159*9356374aSAndroid Build Coastguard Worker // overload instead of specializing any legacy hash functors.
160*9356374aSAndroid Build Coastguard Worker //
161*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
162*9356374aSAndroid Build Coastguard Worker // The Hash State Concept, and using `HashState` for Type Erasure
163*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
164*9356374aSAndroid Build Coastguard Worker //
165*9356374aSAndroid Build Coastguard Worker // The `absl::Hash` framework relies on the Concept of a "hash state." Such a
166*9356374aSAndroid Build Coastguard Worker // hash state is used in several places:
167*9356374aSAndroid Build Coastguard Worker //
168*9356374aSAndroid Build Coastguard Worker // * Within existing implementations of `absl::Hash<T>` to store the hashed
169*9356374aSAndroid Build Coastguard Worker // state of an object. Note that it is up to the implementation how it stores
170*9356374aSAndroid Build Coastguard Worker // such state. A hash table, for example, may mix the state to produce an
171*9356374aSAndroid Build Coastguard Worker // integer value; a testing framework may simply hold a vector of that state.
172*9356374aSAndroid Build Coastguard Worker // * Within implementations of `AbslHashValue()` used to extend user-defined
173*9356374aSAndroid Build Coastguard Worker // types. (See "Adding Type Support to absl::Hash" below.)
174*9356374aSAndroid Build Coastguard Worker // * Inside a `HashState`, providing type erasure for the concept of a hash
175*9356374aSAndroid Build Coastguard Worker // state, which you can use to extend the `absl::Hash` framework for types
176*9356374aSAndroid Build Coastguard Worker // that are otherwise difficult to extend using `AbslHashValue()`. (See the
177*9356374aSAndroid Build Coastguard Worker // `HashState` class below.)
178*9356374aSAndroid Build Coastguard Worker //
179*9356374aSAndroid Build Coastguard Worker // The "hash state" concept contains three member functions for mixing hash
180*9356374aSAndroid Build Coastguard Worker // state:
181*9356374aSAndroid Build Coastguard Worker //
182*9356374aSAndroid Build Coastguard Worker // * `H::combine(state, values...)`
183*9356374aSAndroid Build Coastguard Worker //
184*9356374aSAndroid Build Coastguard Worker // Combines an arbitrary number of values into a hash state, returning the
185*9356374aSAndroid Build Coastguard Worker // updated state. Note that the existing hash state is move-only and must be
186*9356374aSAndroid Build Coastguard Worker // passed by value.
187*9356374aSAndroid Build Coastguard Worker //
188*9356374aSAndroid Build Coastguard Worker // Each of the value types T must be hashable by H.
189*9356374aSAndroid Build Coastguard Worker //
190*9356374aSAndroid Build Coastguard Worker // NOTE:
191*9356374aSAndroid Build Coastguard Worker //
192*9356374aSAndroid Build Coastguard Worker // state = H::combine(std::move(state), value1, value2, value3);
193*9356374aSAndroid Build Coastguard Worker //
194*9356374aSAndroid Build Coastguard Worker // must be guaranteed to produce the same hash expansion as
195*9356374aSAndroid Build Coastguard Worker //
196*9356374aSAndroid Build Coastguard Worker // state = H::combine(std::move(state), value1);
197*9356374aSAndroid Build Coastguard Worker // state = H::combine(std::move(state), value2);
198*9356374aSAndroid Build Coastguard Worker // state = H::combine(std::move(state), value3);
199*9356374aSAndroid Build Coastguard Worker //
200*9356374aSAndroid Build Coastguard Worker // * `H::combine_contiguous(state, data, size)`
201*9356374aSAndroid Build Coastguard Worker //
202*9356374aSAndroid Build Coastguard Worker // Combines a contiguous array of `size` elements into a hash state,
203*9356374aSAndroid Build Coastguard Worker // returning the updated state. Note that the existing hash state is
204*9356374aSAndroid Build Coastguard Worker // move-only and must be passed by value.
205*9356374aSAndroid Build Coastguard Worker //
206*9356374aSAndroid Build Coastguard Worker // NOTE:
207*9356374aSAndroid Build Coastguard Worker //
208*9356374aSAndroid Build Coastguard Worker // state = H::combine_contiguous(std::move(state), data, size);
209*9356374aSAndroid Build Coastguard Worker //
210*9356374aSAndroid Build Coastguard Worker // need NOT be guaranteed to produce the same hash expansion as a loop
211*9356374aSAndroid Build Coastguard Worker // (it may perform internal optimizations). If you need this guarantee, use a
212*9356374aSAndroid Build Coastguard Worker // loop instead.
213*9356374aSAndroid Build Coastguard Worker //
214*9356374aSAndroid Build Coastguard Worker // * `H::combine_unordered(state, begin, end)`
215*9356374aSAndroid Build Coastguard Worker //
216*9356374aSAndroid Build Coastguard Worker // Combines a set of elements denoted by an iterator pair into a hash
217*9356374aSAndroid Build Coastguard Worker // state, returning the updated state. Note that the existing hash
218*9356374aSAndroid Build Coastguard Worker // state is move-only and must be passed by value.
219*9356374aSAndroid Build Coastguard Worker //
220*9356374aSAndroid Build Coastguard Worker // Unlike the other two methods, the hashing is order-independent.
221*9356374aSAndroid Build Coastguard Worker // This can be used to hash unordered collections.
222*9356374aSAndroid Build Coastguard Worker //
223*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
224*9356374aSAndroid Build Coastguard Worker // Adding Type Support to `absl::Hash`
225*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
226*9356374aSAndroid Build Coastguard Worker //
227*9356374aSAndroid Build Coastguard Worker // To add support for your user-defined type, add a proper `AbslHashValue()`
228*9356374aSAndroid Build Coastguard Worker // overload as a free (non-member) function. The overload will take an
229*9356374aSAndroid Build Coastguard Worker // existing hash state and should combine that state with state from the type.
230*9356374aSAndroid Build Coastguard Worker //
231*9356374aSAndroid Build Coastguard Worker // Example:
232*9356374aSAndroid Build Coastguard Worker //
233*9356374aSAndroid Build Coastguard Worker // template <typename H>
234*9356374aSAndroid Build Coastguard Worker // H AbslHashValue(H state, const MyType& v) {
235*9356374aSAndroid Build Coastguard Worker // return H::combine(std::move(state), v.field1, ..., v.fieldN);
236*9356374aSAndroid Build Coastguard Worker // }
237*9356374aSAndroid Build Coastguard Worker //
238*9356374aSAndroid Build Coastguard Worker // where `(field1, ..., fieldN)` are the members you would use on your
239*9356374aSAndroid Build Coastguard Worker // `operator==` to define equality.
240*9356374aSAndroid Build Coastguard Worker //
241*9356374aSAndroid Build Coastguard Worker // Notice that `AbslHashValue` is not a class member, but an ordinary function.
242*9356374aSAndroid Build Coastguard Worker // An `AbslHashValue` overload for a type should only be declared in the same
243*9356374aSAndroid Build Coastguard Worker // file and namespace as said type. The proper `AbslHashValue` implementation
244*9356374aSAndroid Build Coastguard Worker // for a given type will be discovered via ADL.
245*9356374aSAndroid Build Coastguard Worker //
246*9356374aSAndroid Build Coastguard Worker // Note: unlike `std::hash', `absl::Hash` should never be specialized. It must
247*9356374aSAndroid Build Coastguard Worker // only be extended by adding `AbslHashValue()` overloads.
248*9356374aSAndroid Build Coastguard Worker //
249*9356374aSAndroid Build Coastguard Worker template <typename T>
250*9356374aSAndroid Build Coastguard Worker using Hash = absl::hash_internal::Hash<T>;
251*9356374aSAndroid Build Coastguard Worker
252*9356374aSAndroid Build Coastguard Worker // HashOf
253*9356374aSAndroid Build Coastguard Worker //
254*9356374aSAndroid Build Coastguard Worker // absl::HashOf() is a helper that generates a hash from the values of its
255*9356374aSAndroid Build Coastguard Worker // arguments. It dispatches to absl::Hash directly, as follows:
256*9356374aSAndroid Build Coastguard Worker // * HashOf(t) == absl::Hash<T>{}(t)
257*9356374aSAndroid Build Coastguard Worker // * HashOf(a, b, c) == HashOf(std::make_tuple(a, b, c))
258*9356374aSAndroid Build Coastguard Worker //
259*9356374aSAndroid Build Coastguard Worker // HashOf(a1, a2, ...) == HashOf(b1, b2, ...) is guaranteed when
260*9356374aSAndroid Build Coastguard Worker // * The argument lists have pairwise identical C++ types
261*9356374aSAndroid Build Coastguard Worker // * a1 == b1 && a2 == b2 && ...
262*9356374aSAndroid Build Coastguard Worker //
263*9356374aSAndroid Build Coastguard Worker // The requirement that the arguments match in both type and value is critical.
264*9356374aSAndroid Build Coastguard Worker // It means that `a == b` does not necessarily imply `HashOf(a) == HashOf(b)` if
265*9356374aSAndroid Build Coastguard Worker // `a` and `b` have different types. For example, `HashOf(2) != HashOf(2.0)`.
266*9356374aSAndroid Build Coastguard Worker template <int&... ExplicitArgumentBarrier, typename... Types>
HashOf(const Types &...values)267*9356374aSAndroid Build Coastguard Worker size_t HashOf(const Types&... values) {
268*9356374aSAndroid Build Coastguard Worker auto tuple = std::tie(values...);
269*9356374aSAndroid Build Coastguard Worker return absl::Hash<decltype(tuple)>{}(tuple);
270*9356374aSAndroid Build Coastguard Worker }
271*9356374aSAndroid Build Coastguard Worker
272*9356374aSAndroid Build Coastguard Worker // HashState
273*9356374aSAndroid Build Coastguard Worker //
274*9356374aSAndroid Build Coastguard Worker // A type erased version of the hash state concept, for use in user-defined
275*9356374aSAndroid Build Coastguard Worker // `AbslHashValue` implementations that can't use templates (such as PImpl
276*9356374aSAndroid Build Coastguard Worker // classes, virtual functions, etc.). The type erasure adds overhead so it
277*9356374aSAndroid Build Coastguard Worker // should be avoided unless necessary.
278*9356374aSAndroid Build Coastguard Worker //
279*9356374aSAndroid Build Coastguard Worker // Note: This wrapper will only erase calls to
280*9356374aSAndroid Build Coastguard Worker // combine_contiguous(H, const unsigned char*, size_t)
281*9356374aSAndroid Build Coastguard Worker // RunCombineUnordered(H, CombinerF)
282*9356374aSAndroid Build Coastguard Worker //
283*9356374aSAndroid Build Coastguard Worker // All other calls will be handled internally and will not invoke overloads
284*9356374aSAndroid Build Coastguard Worker // provided by the wrapped class.
285*9356374aSAndroid Build Coastguard Worker //
286*9356374aSAndroid Build Coastguard Worker // Users of this class should still define a template `AbslHashValue` function,
287*9356374aSAndroid Build Coastguard Worker // but can use `absl::HashState::Create(&state)` to erase the type of the hash
288*9356374aSAndroid Build Coastguard Worker // state and dispatch to their private hashing logic.
289*9356374aSAndroid Build Coastguard Worker //
290*9356374aSAndroid Build Coastguard Worker // This state can be used like any other hash state. In particular, you can call
291*9356374aSAndroid Build Coastguard Worker // `HashState::combine()` and `HashState::combine_contiguous()` on it.
292*9356374aSAndroid Build Coastguard Worker //
293*9356374aSAndroid Build Coastguard Worker // Example:
294*9356374aSAndroid Build Coastguard Worker //
295*9356374aSAndroid Build Coastguard Worker // class Interface {
296*9356374aSAndroid Build Coastguard Worker // public:
297*9356374aSAndroid Build Coastguard Worker // template <typename H>
298*9356374aSAndroid Build Coastguard Worker // friend H AbslHashValue(H state, const Interface& value) {
299*9356374aSAndroid Build Coastguard Worker // state = H::combine(std::move(state), std::type_index(typeid(*this)));
300*9356374aSAndroid Build Coastguard Worker // value.HashValue(absl::HashState::Create(&state));
301*9356374aSAndroid Build Coastguard Worker // return state;
302*9356374aSAndroid Build Coastguard Worker // }
303*9356374aSAndroid Build Coastguard Worker // private:
304*9356374aSAndroid Build Coastguard Worker // virtual void HashValue(absl::HashState state) const = 0;
305*9356374aSAndroid Build Coastguard Worker // };
306*9356374aSAndroid Build Coastguard Worker //
307*9356374aSAndroid Build Coastguard Worker // class Impl : Interface {
308*9356374aSAndroid Build Coastguard Worker // private:
309*9356374aSAndroid Build Coastguard Worker // void HashValue(absl::HashState state) const override {
310*9356374aSAndroid Build Coastguard Worker // absl::HashState::combine(std::move(state), v1_, v2_);
311*9356374aSAndroid Build Coastguard Worker // }
312*9356374aSAndroid Build Coastguard Worker // int v1_;
313*9356374aSAndroid Build Coastguard Worker // std::string v2_;
314*9356374aSAndroid Build Coastguard Worker // };
315*9356374aSAndroid Build Coastguard Worker class HashState : public hash_internal::HashStateBase<HashState> {
316*9356374aSAndroid Build Coastguard Worker public:
317*9356374aSAndroid Build Coastguard Worker // HashState::Create()
318*9356374aSAndroid Build Coastguard Worker //
319*9356374aSAndroid Build Coastguard Worker // Create a new `HashState` instance that wraps `state`. All calls to
320*9356374aSAndroid Build Coastguard Worker // `combine()` and `combine_contiguous()` on the new instance will be
321*9356374aSAndroid Build Coastguard Worker // redirected to the original `state` object. The `state` object must outlive
322*9356374aSAndroid Build Coastguard Worker // the `HashState` instance.
323*9356374aSAndroid Build Coastguard Worker template <typename T>
Create(T * state)324*9356374aSAndroid Build Coastguard Worker static HashState Create(T* state) {
325*9356374aSAndroid Build Coastguard Worker HashState s;
326*9356374aSAndroid Build Coastguard Worker s.Init(state);
327*9356374aSAndroid Build Coastguard Worker return s;
328*9356374aSAndroid Build Coastguard Worker }
329*9356374aSAndroid Build Coastguard Worker
330*9356374aSAndroid Build Coastguard Worker HashState(const HashState&) = delete;
331*9356374aSAndroid Build Coastguard Worker HashState& operator=(const HashState&) = delete;
332*9356374aSAndroid Build Coastguard Worker HashState(HashState&&) = default;
333*9356374aSAndroid Build Coastguard Worker HashState& operator=(HashState&&) = default;
334*9356374aSAndroid Build Coastguard Worker
335*9356374aSAndroid Build Coastguard Worker // HashState::combine()
336*9356374aSAndroid Build Coastguard Worker //
337*9356374aSAndroid Build Coastguard Worker // Combines an arbitrary number of values into a hash state, returning the
338*9356374aSAndroid Build Coastguard Worker // updated state.
339*9356374aSAndroid Build Coastguard Worker using HashState::HashStateBase::combine;
340*9356374aSAndroid Build Coastguard Worker
341*9356374aSAndroid Build Coastguard Worker // HashState::combine_contiguous()
342*9356374aSAndroid Build Coastguard Worker //
343*9356374aSAndroid Build Coastguard Worker // Combines a contiguous array of `size` elements into a hash state, returning
344*9356374aSAndroid Build Coastguard Worker // the updated state.
combine_contiguous(HashState hash_state,const unsigned char * first,size_t size)345*9356374aSAndroid Build Coastguard Worker static HashState combine_contiguous(HashState hash_state,
346*9356374aSAndroid Build Coastguard Worker const unsigned char* first, size_t size) {
347*9356374aSAndroid Build Coastguard Worker hash_state.combine_contiguous_(hash_state.state_, first, size);
348*9356374aSAndroid Build Coastguard Worker return hash_state;
349*9356374aSAndroid Build Coastguard Worker }
350*9356374aSAndroid Build Coastguard Worker using HashState::HashStateBase::combine_contiguous;
351*9356374aSAndroid Build Coastguard Worker
352*9356374aSAndroid Build Coastguard Worker private:
353*9356374aSAndroid Build Coastguard Worker HashState() = default;
354*9356374aSAndroid Build Coastguard Worker
355*9356374aSAndroid Build Coastguard Worker friend class HashState::HashStateBase;
356*9356374aSAndroid Build Coastguard Worker
357*9356374aSAndroid Build Coastguard Worker template <typename T>
CombineContiguousImpl(void * p,const unsigned char * first,size_t size)358*9356374aSAndroid Build Coastguard Worker static void CombineContiguousImpl(void* p, const unsigned char* first,
359*9356374aSAndroid Build Coastguard Worker size_t size) {
360*9356374aSAndroid Build Coastguard Worker T& state = *static_cast<T*>(p);
361*9356374aSAndroid Build Coastguard Worker state = T::combine_contiguous(std::move(state), first, size);
362*9356374aSAndroid Build Coastguard Worker }
363*9356374aSAndroid Build Coastguard Worker
364*9356374aSAndroid Build Coastguard Worker template <typename T>
Init(T * state)365*9356374aSAndroid Build Coastguard Worker void Init(T* state) {
366*9356374aSAndroid Build Coastguard Worker state_ = state;
367*9356374aSAndroid Build Coastguard Worker combine_contiguous_ = &CombineContiguousImpl<T>;
368*9356374aSAndroid Build Coastguard Worker run_combine_unordered_ = &RunCombineUnorderedImpl<T>;
369*9356374aSAndroid Build Coastguard Worker }
370*9356374aSAndroid Build Coastguard Worker
371*9356374aSAndroid Build Coastguard Worker template <typename HS>
372*9356374aSAndroid Build Coastguard Worker struct CombineUnorderedInvoker {
373*9356374aSAndroid Build Coastguard Worker template <typename T, typename ConsumerT>
operatorCombineUnorderedInvoker374*9356374aSAndroid Build Coastguard Worker void operator()(T inner_state, ConsumerT inner_cb) {
375*9356374aSAndroid Build Coastguard Worker f(HashState::Create(&inner_state),
376*9356374aSAndroid Build Coastguard Worker [&](HashState& inner_erased) { inner_cb(inner_erased.Real<T>()); });
377*9356374aSAndroid Build Coastguard Worker }
378*9356374aSAndroid Build Coastguard Worker
379*9356374aSAndroid Build Coastguard Worker absl::FunctionRef<void(HS, absl::FunctionRef<void(HS&)>)> f;
380*9356374aSAndroid Build Coastguard Worker };
381*9356374aSAndroid Build Coastguard Worker
382*9356374aSAndroid Build Coastguard Worker template <typename T>
RunCombineUnorderedImpl(HashState state,absl::FunctionRef<void (HashState,absl::FunctionRef<void (HashState &)>)> f)383*9356374aSAndroid Build Coastguard Worker static HashState RunCombineUnorderedImpl(
384*9356374aSAndroid Build Coastguard Worker HashState state,
385*9356374aSAndroid Build Coastguard Worker absl::FunctionRef<void(HashState, absl::FunctionRef<void(HashState&)>)>
386*9356374aSAndroid Build Coastguard Worker f) {
387*9356374aSAndroid Build Coastguard Worker // Note that this implementation assumes that inner_state and outer_state
388*9356374aSAndroid Build Coastguard Worker // are the same type. This isn't true in the SpyHash case, but SpyHash
389*9356374aSAndroid Build Coastguard Worker // types are move-convertible to each other, so this still works.
390*9356374aSAndroid Build Coastguard Worker T& real_state = state.Real<T>();
391*9356374aSAndroid Build Coastguard Worker real_state = T::RunCombineUnordered(
392*9356374aSAndroid Build Coastguard Worker std::move(real_state), CombineUnorderedInvoker<HashState>{f});
393*9356374aSAndroid Build Coastguard Worker return state;
394*9356374aSAndroid Build Coastguard Worker }
395*9356374aSAndroid Build Coastguard Worker
396*9356374aSAndroid Build Coastguard Worker template <typename CombinerT>
RunCombineUnordered(HashState state,CombinerT combiner)397*9356374aSAndroid Build Coastguard Worker static HashState RunCombineUnordered(HashState state, CombinerT combiner) {
398*9356374aSAndroid Build Coastguard Worker auto* run = state.run_combine_unordered_;
399*9356374aSAndroid Build Coastguard Worker return run(std::move(state), std::ref(combiner));
400*9356374aSAndroid Build Coastguard Worker }
401*9356374aSAndroid Build Coastguard Worker
402*9356374aSAndroid Build Coastguard Worker // Do not erase an already erased state.
Init(HashState * state)403*9356374aSAndroid Build Coastguard Worker void Init(HashState* state) {
404*9356374aSAndroid Build Coastguard Worker state_ = state->state_;
405*9356374aSAndroid Build Coastguard Worker combine_contiguous_ = state->combine_contiguous_;
406*9356374aSAndroid Build Coastguard Worker run_combine_unordered_ = state->run_combine_unordered_;
407*9356374aSAndroid Build Coastguard Worker }
408*9356374aSAndroid Build Coastguard Worker
409*9356374aSAndroid Build Coastguard Worker template <typename T>
Real()410*9356374aSAndroid Build Coastguard Worker T& Real() {
411*9356374aSAndroid Build Coastguard Worker return *static_cast<T*>(state_);
412*9356374aSAndroid Build Coastguard Worker }
413*9356374aSAndroid Build Coastguard Worker
414*9356374aSAndroid Build Coastguard Worker void* state_;
415*9356374aSAndroid Build Coastguard Worker void (*combine_contiguous_)(void*, const unsigned char*, size_t);
416*9356374aSAndroid Build Coastguard Worker HashState (*run_combine_unordered_)(
417*9356374aSAndroid Build Coastguard Worker HashState state,
418*9356374aSAndroid Build Coastguard Worker absl::FunctionRef<void(HashState, absl::FunctionRef<void(HashState&)>)>);
419*9356374aSAndroid Build Coastguard Worker };
420*9356374aSAndroid Build Coastguard Worker
421*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
422*9356374aSAndroid Build Coastguard Worker } // namespace absl
423*9356374aSAndroid Build Coastguard Worker
424*9356374aSAndroid Build Coastguard Worker #endif // ABSL_HASH_HASH_H_
425