blob: 39374c679113a5c6bb3ad9866c890523bab6d0cf [file]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_BASIC_OPS_IMPL_H_
#define BASE_NUMERICS_BASIC_OPS_IMPL_H_
#include <algorithm>
#include <array>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <span>
#include <type_traits>
namespace base::numerics_internal {
// Converts from a byte array to an integer. We use `std::ranges::copy` and
// `std::bit_cast` to support `constexpr` evaluation while maintaining optimal
// runtime performance (compilers can optimize this to a single load). We avoid
// `base::span` here to keep `base/numerics` free of dependencies on other parts
// of `base`. See https://godbolt.org/z/cssPcEnG4 for a proof.
template <class T>
requires(std::is_unsigned_v<T> && std::is_integral_v<T>)
inline constexpr T FromLittleEndian(std::span<const uint8_t, sizeof(T)> bytes) {
std::array<uint8_t, sizeof(T)> arr;
std::ranges::copy(bytes, arr.begin());
return std::bit_cast<T>(arr);
}
template <class T>
requires(std::is_signed_v<T> && std::is_integral_v<T>)
inline constexpr T FromLittleEndian(std::span<const uint8_t, sizeof(T)> bytes) {
return static_cast<T>(FromLittleEndian<std::make_unsigned_t<T>>(bytes));
}
// Converts to a byte array from an integer. We use `std::bit_cast` for
// `constexpr` support and optimal performance.
template <class T>
requires(std::is_unsigned_v<T> && std::is_integral_v<T>)
inline constexpr std::array<uint8_t, sizeof(T)> ToLittleEndian(T val) {
return std::bit_cast<std::array<uint8_t, sizeof(T)>>(val);
}
template <class T>
requires(std::is_signed_v<T> && std::is_integral_v<T>)
inline constexpr std::array<uint8_t, sizeof(T)> ToLittleEndian(T val) {
return ToLittleEndian(static_cast<std::make_unsigned_t<T>>(val));
}
} // namespace base::numerics_internal
#endif // BASE_NUMERICS_BASIC_OPS_IMPL_H_