blob: db6915d7522e46c3c5d31962041b178215c35dd8 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_INTERNAL_TEMPLATES_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_INTERNAL_TEMPLATES_H_
#include <cstdint>
#include <cstring>
#include <type_traits>
namespace blink {
namespace internal {
// Handroll a remove_cv_t until we get to C++20.
template <typename T>
using remove_cvref_t = typename std::remove_cv_t<std::remove_reference_t<T>>;
// Kinda conservative implementation of
// std::has_unique_object_representations<>. Perhaps not as conservative as we'd
// like.
//
// At a minimum, this predicate should require that the data type not contain
// internal padding since uninitialized padding bytes defeat the uniqueness of
// the representation. Trailing padding is allowed.
//
// Not checking <version> because we don't want to use the feature
// automatically. We should wait until C++-17 library functionality is
// explicitly allowed in Chromium.
template <typename T>
using has_unique_object_representations = std::is_arithmetic<T>;
// Calculate a digest of an object with a unique representation.
//
// In a perfect world, we should also require that this representation be
// portable or made to be portable. Such a transformation could be done, for
// example, by adopting a consistent byte ordering on all platforms.
//
// This function should only be invoked on a bare (sans qualifiers and
// references) type for the sake of simplicity.
//
// Should not be used as a primitive for manually constructing a unique
// representation. For such cases, use the byte-wise digest functions instead.
//
// Should not be used outside of the narrow use cases in this file.
//
// This implementation does not work for x86 extended precision floating point
// numbers. These are 80-bits wide, but in practice includes 6 bytes of padding
// in order to extend the size to 16 bytes. The extra bytes are uninitialized
// and will not contribute a stable digest.
template <
typename T,
typename std::enable_if_t<std::is_same<T, remove_cvref_t<T>>::value &&
std::is_trivially_copyable<T>::value &&
has_unique_object_representations<T>::value &&
sizeof(T) <= sizeof(int64_t)>* = nullptr>
constexpr int64_t DigestOfObjectRepresentation(T in) {
// If |in| is small enough, the digest is itself. There's no point hashing
// this value since the identity has all the properties we are looking for
// in a digest.
if (std::is_integral<T>::value && std::is_signed<T>::value)
return in;
if (std::is_integral<T>::value && sizeof(T) < sizeof(int64_t))
return in;
int64_t result = 0;
std::memcpy(&result, &in, sizeof(in));
return result;
}
} // namespace internal
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_INTERNAL_TEMPLATES_H_