15#ifndef ACTIONENGINE_MSGPACK_CORE_HELPERS_H_ 
   16#define ACTIONENGINE_MSGPACK_CORE_HELPERS_H_ 
   21#include <absl/container/inlined_vector.h> 
   22#include <absl/status/status.h> 
   23#include <absl/status/statusor.h> 
   24#include <absl/strings/str_cat.h> 
   25#include <absl/strings/str_format.h> 
   27namespace act::msgpack {
 
   32using SerializedBytesVector = absl::InlinedVector<Byte, 9>;
 
   34inline std::vector<Byte> ToStdVector(SerializedBytesVector bytes) {
 
   35  return {std::make_move_iterator(bytes.begin()),
 
   36          std::make_move_iterator(bytes.end())};
 
   40  SerializedBytesVector* absl_nonnull bytes;
 
   41  SerializedBytesVector::iterator absl_nonnull at;
 
   45  Byte* absl_nonnull pos;
 
   46  Byte* absl_nonnull end;
 
   47  Byte* absl_nullable begin;
 
   49  LookupPointer(Byte* absl_nonnull pos, Byte* absl_nonnull end,
 
   50                Byte* absl_nullable begin = 
nullptr)
 
   51      : pos(pos), end(end), begin(begin) {}
 
   53  bool operator==(
const LookupPointer& other)
 const {
 
   54    return pos == other.pos && end == other.end && begin == other.begin;
 
   65SerializedBytesVector ToBigEndianBytes(
const T& value, uint8_t pad = 0) {
 
   66  SerializedBytesVector bytes(
sizeof(T) + pad);
 
   67  if constexpr (std::endian::native == std::endian::little) {
 
   68    for (
size_t i = 0; i < 
sizeof(T); ++i) {
 
   69      bytes[i + pad] = (value >> ((
sizeof(T) - 1 - i) * 8)) & 0xFF;
 
   72    for (
size_t i = 0; i < 
sizeof(T); ++i) {
 
   73      bytes[i + pad] = (value >> (i * 8)) & 0xFF;
 
   79#if __STDCPP_FLOAT32_T__ != 1 
   80using float32_t = float;
 
   81using float64_t = double;
 
   85inline SerializedBytesVector ToBigEndianBytes<float32_t>(
const float32_t& value,
 
   87  return ToBigEndianBytes<uint32_t>(
reinterpret_cast<const uint32_t&
>(value),
 
   92inline SerializedBytesVector ToBigEndianBytes<float64_t>(
const float64_t& value,
 
   94  return ToBigEndianBytes<uint64_t>(
reinterpret_cast<const uint64_t&
>(value),
 
   99T FromBigEndianBytes(
const Byte* absl_nonnull bytes) {
 
  100  if constexpr (std::endian::native == std::endian::big) {
 
  101    return *
reinterpret_cast<T*
>(bytes);
 
  103  absl::InlinedVector<Byte, 
sizeof(T)> reversed_bytes(
sizeof(T));
 
  104  for (
size_t i = 0; i < 
sizeof(T); ++i) {
 
  105    reversed_bytes[i] = bytes[
sizeof(T) - 1 - i];
 
  107  return *
reinterpret_cast<T*
>(reversed_bytes.data());
 
  110enum FormatSignature {
 
  111  kPositiveFixint = 0b00000000,  
 
  112  kFixMap = 0b10000000,          
 
  113  kFixArray = 0b10010000,        
 
  114  kFixStr = 0b10100000,          
 
  116  kNeverUsed = 0b11000001,       
 
  125  kFloat32 = 0b11001010,         
 
  126  kFloat64 = 0b11001011,         
 
  128  kUInt16 = 0b11001101,          
 
  129  kUInt32 = 0b11001110,          
 
  130  kUInt64 = 0b11001111,          
 
  135  kFixExt1 = 0b11010100,         
 
  136  kFixExt2 = 0b11010101,         
 
  137  kFixExt4 = 0b11010110,         
 
  138  kFixExt8 = 0b11010111,         
 
  139  kFixExt16 = 0b11011000,        
 
  143  kArray16 = 0b11011100,         
 
  144  kArray32 = 0b11011101,         
 
  147  kNegativeFixint = 0b11100000   
 
  150inline std::string GetPositionString(
 
  151    const Byte* absl_nonnull pos, 
const Byte* absl_nullable begin = 
nullptr) {
 
  152  if (begin != 
nullptr) {
 
  153    return absl::StrFormat(
"%d", pos - begin);
 
  155  return absl::StrFormat(
"0x%02x", *pos);
 
  158inline absl::Status GetInvalidFormatSignatureError(
 
  159    const Byte* absl_nonnull pos, std::string_view type_name,
 
  160    const Byte* absl_nullable begin = 
nullptr) {
 
  162  return absl::InvalidArgumentError(absl::StrCat(
 
  163      "Expected a ", type_name,
 
  164      " value, but found a different format signature at position ",
 
  165      GetPositionString(pos, begin), 
": ", absl::StrFormat(
"0x%02x", *pos)));
 
  168inline absl::Status GetInsufficientDataError(
const LookupPointer& data,
 
  169                                             std::string_view type_name) {
 
  170  return absl::InvalidArgumentError(absl::StrCat(
 
  171      "Insufficient data to read a ", type_name, 
" value at position ",
 
  172      GetPositionString(data.pos, data.begin), 
": ",
 
  173      absl::StrFormat(
"0x%02x", *data.pos), 
". Only have ",
 
  174      absl::StrFormat(
"%d", data.end - data.pos), 
" bytes."));
 
  179absl::StatusOr<uint32_t> GetExtent(Byte* absl_nonnull pos,
 
  180                                   Byte* absl_nonnull end) {
 
  182    return absl::InvalidArgumentError(
 
  183        "Position is not within the bounds of the data.");
 
  186  if (*pos == FormatSignature::kNeverUsed) {
 
  187    return absl::InvalidArgumentError(
 
  188        "FormatSignature::kNeverUsed is not a valid format signature.");
 
  191  return EgltMsgpackGetExtent(LookupPointer(pos, end),
 
  192                              static_cast<T*
>(
nullptr));
 
  196absl::StatusOr<SerializedBytesVector> Serialize(T&& value) {
 
  197  SerializedBytesVector output;
 
  198  auto status = EgltMsgpackSerialize(std::forward<T>(value),
 
  199                                     InsertInfo{&output, output.end()});
 
  207absl::Status Serialize(T&& value, 
const InsertInfo& insert) {
 
  208  return EgltMsgpackSerialize(std::forward<T>(value), insert);
 
  212concept HasDefinedGetExtent = 
requires(T t) {
 
  214    EgltMsgpackGetExtent(std::declval<LookupPointer>(), std::declval<T*>())
 
  215  } -> std::same_as<absl::StatusOr<uint32_t>>;
 
  219absl::StatusOr<uint32_t> Deserialize(
const LookupPointer& data,
 
  220                                     T* absl_nonnull output)
 
  221    requires(!HasDefinedGetExtent<T>) {
 
  222  const auto [pos, end, _] = data;
 
  224    return absl::InvalidArgumentError(
 
  225        "Position is not within the bounds of the data.");
 
  228  if (*pos == FormatSignature::kNeverUsed) {
 
  229    return absl::InvalidArgumentError(
 
  230        "FormatSignature::kNeverUsed is not a valid format signature.");
 
  233  auto extent = EgltMsgpackDeserialize(LookupPointer(pos, end), output);
 
  235    return extent.status();
 
  241absl::StatusOr<uint32_t> Deserialize(
const LookupPointer& data,
 
  242                                     T* absl_nonnull output)
 
  243    requires(HasDefinedGetExtent<T>) {
 
  244  const auto [pos, end, _] = data;
 
  246    return absl::InvalidArgumentError(
 
  247        "Position is not within the bounds of the data.");
 
  250  if (*pos == FormatSignature::kNeverUsed) {
 
  251    return absl::InvalidArgumentError(
 
  252        "FormatSignature::kNeverUsed is not a valid format signature.");
 
  256  absl::StatusOr<uint32_t> expected_extent = GetExtent<T>(pos, end);
 
  257  if (!expected_extent.ok()) {
 
  258    return expected_extent.status();
 
  262  auto actual_extent = EgltMsgpackDeserialize(LookupPointer(pos, end), output);
 
  263  if (!actual_extent.ok()) {
 
  264    return actual_extent.status();
 
  268  if (*expected_extent != *actual_extent) {
 
  269    return absl::InvalidArgumentError(absl::StrFormat(
 
  270        "Expected extent: %d, actual extent: %d at position %s",
 
  271        *expected_extent, *actual_extent, GetPositionString(pos, data.begin)));
 
  275  return *actual_extent;
 
  279absl::StatusOr<Deserialized<T>> Deserialize(
const LookupPointer& data) {
 
  280  Deserialized<T> deserialized;
 
  281  deserialized.extent = 0;
 
  282  auto status_or_extent = Deserialize(data, &deserialized.value);
 
  283  if (!status_or_extent.ok()) {
 
  284    return status_or_extent.status();
 
  286  deserialized.extent = *status_or_extent;
 
  293absl::Status SerializeNonIec559Float32(float32_t value,
 
  294                                       const InsertInfo& insert);
 
  295absl::Status SerializeNonIec559Float64(float64_t value,
 
  296                                       const InsertInfo& insert);