// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_WEB_SESSION_HASH_UTIL_H_
#define IOS_WEB_SESSION_HASH_UTIL_H_
#include <functional>
#include <string_view>
#include <tuple>
#include "net/base/hash_value.h"
#include "net/cert/x509_certificate.h"
namespace web {
namespace session {
namespace internal {
// Helper struct used to implement hash for session objects.
template <typename T>
struct Hasher : std::hash<T> {};
// Specialisation of Hasher for non-const pointers.
template <typename T>
struct Hasher<T*> : Hasher<const T*> {};
// Specialisation of Hasher for SHA256HashValue.
template <>
struct Hasher<net::SHA256HashValue> {
size_t operator()(const net::SHA256HashValue& value) const {
const std::string_view value_string_piece(
reinterpret_cast<const char*>(&value.data[0]), sizeof(value.data));
return Hasher<std::string_view>{}(value_string_piece);
}
};
// Specialisation of Hasher for X509Certificate.
template <>
struct Hasher<const net::X509Certificate*> {
size_t operator()(const net::X509Certificate* value) const {
const net::SHA256HashValue fingerprint =
value->CalculateChainFingerprint256();
return Hasher<net::SHA256HashValue>{}(fingerprint);
}
};
// Specialisation of Hasher for scoped_refptr<T>.
template <typename T>
struct Hasher<scoped_refptr<T>> {
size_t operator()(const scoped_refptr<T>& value) const {
return Hasher<std::add_pointer_t<std::decay_t<T>>>{}(value.get());
}
};
// Combine `hash` with the hash of `value`.
template <typename T>
size_t CombineHash(size_t hash, T&& value) {
const size_t value_hash = Hasher<std::decay_t<T>>{}(std::forward<T>(value));
return hash ^ (value_hash + 0xeeffccdd + (hash << 5) + (hash >> 3));
}
// Helper to compute the hash of a tuple (end recursion case).
template <typename... T>
size_t TupleHasherImpl(size_t hash) {
return hash;
}
// Helper to compute the hash of a tuple (general recursive case).
template <typename Head, typename... Tail>
size_t TupleHasherImpl(size_t hash, Head&& head, Tail&&... tail) {
size_t curr = CombineHash(hash, std::forward<Head>(head));
return TupleHasherImpl(curr, std::forward<Tail>(tail)...);
}
// Helper to compute the hash of a tuple (setup the recursion).
template <typename Tuple, size_t... I>
size_t TupleHasher(Tuple&& tuple, std::index_sequence<I...>) {
return TupleHasherImpl(0, std::get<I>(tuple)...);
}
// Specialisation of Hasher for tuples.
template <typename... T>
struct Hasher<std::tuple<T...>> {
size_t operator()(std::tuple<T...>&& value) const {
return TupleHasher(
std::forward<std::tuple<T...>>(value),
std::make_index_sequence<std::tuple_size_v<std::tuple<T...>>>());
}
};
} // namespace internal
// Helper function computing the hash of a variadic number of args.
template <typename... Args>
size_t ComputeHash(Args&&... args) {
using Hasher = internal::Hasher<std::tuple<Args...>>;
return Hasher{}(std::tuple<Args...>(std::forward<Args>(args)...));
}
} // namespace session
} // namespace web
#endif // IOS_WEB_SESSION_HASH_UTIL_H_