15#ifndef ACTIONENGINE_MSGPACK_MISC_H 
   16#define ACTIONENGINE_MSGPACK_MISC_H 
   18namespace act::msgpack {
 
   24  [[nodiscard]] absl::Time ToAbslTime()
 const {
 
   25    return absl::FromUnixSeconds(seconds) + absl::Nanoseconds(nanos);
 
   28  template <
typename Clock>
 
   29  [[nodiscard]] std::chrono::time_point<Clock> ToChronoTimePoint()
 const {
 
   30    return std::chrono::time_point<Clock, std::chrono::nanoseconds>(
 
   31        std::chrono::seconds(seconds) + std::chrono::nanoseconds(nanos));
 
   35inline absl::StatusOr<uint32_t> EgltMsgpackGetExtent(
const LookupPointer& data,
 
   36                                                     Timestamp* absl_nullable) {
 
   37  const auto [pos, end, _] = data;
 
   38  if (*pos == FormatSignature::kFixExt4) {
 
   40      return GetInsufficientDataError(data, 
"Timestamp");
 
   44  if (*pos == FormatSignature::kFixExt8) {
 
   46      return GetInsufficientDataError(data, 
"Timestamp");
 
   50  if (*pos == FormatSignature::kExt8) {
 
   52      return GetInsufficientDataError(data, 
"Timestamp");
 
   57  return GetInvalidFormatSignatureError(pos, 
"Timestamp", data.begin);
 
   60inline absl::Status EgltMsgpackSerialize(
const Timestamp& value,
 
   61                                         const InsertInfo& insert) {
 
   63  if (value.seconds >= 0 && value.seconds <= 0xFFFFFFFF && value.nanos == 0) {
 
   65    SerializedBytesVector result = ToBigEndianBytes<uint32_t>(value.seconds,
 
   67    result[0] = FormatSignature::kFixExt4;
 
   69    insert.bytes->insert(insert.at, result.begin(), result.end());
 
   70    return absl::OkStatus();
 
   74  if (insert.at == insert.bytes->end()) {
 
   75    insert.bytes->reserve(insert.bytes->size() + 15);
 
   78  insert.bytes->insert(insert.at, {FormatSignature::kExt8, 12, 255});
 
   80      ToBigEndianBytes(
static_cast<uint32_t
>(value.nanos), 0);
 
   81  auto seconds_bytes = ToBigEndianBytes(value.seconds, 0);
 
   82  insert.bytes->insert(insert.at, nanos_bytes.begin(), nanos_bytes.end());
 
   83  insert.bytes->insert(insert.at, seconds_bytes.begin(), seconds_bytes.end());
 
   84  return absl::OkStatus();
 
   87inline absl::StatusOr<uint32_t> EgltMsgpackDeserialize(
 
   88    const LookupPointer& data, Timestamp* absl_nonnull output) {
 
   89  const auto [pos, end, _] = data;
 
   90  if (*pos == FormatSignature::kFixExt4) {
 
   92      return GetInsufficientDataError(data, 
"Timestamp");
 
   94    output->seconds = FromBigEndianBytes<uint32_t>(pos + 2);
 
   98  if (*pos == FormatSignature::kFixExt8) {
 
   99    return absl::UnimplementedError(
 
  100        "FixExt8 for Timestamp64 is not yet implemented.");
 
  102  if (*pos == FormatSignature::kExt8) {
 
  103    if (end - pos < 15) {
 
  104      return GetInsufficientDataError(data, 
"Timestamp");
 
  106    output->nanos = FromBigEndianBytes<uint32_t>(pos + 3);
 
  107    output->seconds = FromBigEndianBytes<int64_t>(pos + 7);
 
  111  return GetInvalidFormatSignatureError(pos, 
"Timestamp", data.begin);
 
  114inline absl::StatusOr<uint32_t> EgltMsgpackGetExtent(
 
  115    const LookupPointer& data, absl::Time* absl_nullable) {
 
  116  return EgltMsgpackGetExtent(data, 
static_cast<Timestamp*
>(
nullptr));
 
  119inline absl::Status EgltMsgpackSerialize(absl::Time value,
 
  120                                         const InsertInfo& insert) {
 
  121  const uint64_t nanos = absl::ToUnixNanos(value) % 1000000000;
 
  122  return EgltMsgpackSerialize(Timestamp{absl::ToUnixSeconds(value), nanos},
 
  126inline absl::StatusOr<uint32_t> EgltMsgpackDeserialize(
 
  127    const LookupPointer& data, absl::Time* absl_nonnull output) {
 
  129  auto status = EgltMsgpackDeserialize(data, ×tamp);
 
  133  *output = timestamp.ToAbslTime();
 
  137inline absl::StatusOr<uint32_t> EgltMsgpackGetExtent(
const LookupPointer& data,
 
  138                                                     bool* absl_nullable) {
 
  139  const auto [pos, end, _] = data;
 
  141    return absl::InvalidArgumentError(
 
  142        "Position is not within the bounds of the data.");
 
  144  if (*pos == FormatSignature::kFalse || *pos == FormatSignature::kTrue) {
 
  147  return absl::InvalidArgumentError(
 
  148      "Expected a boolean value, but found a different format signature.");
 
  151inline absl::Status EgltMsgpackSerialize(
bool value, 
const InsertInfo& insert) {
 
  153    insert.bytes->insert(insert.at, FormatSignature::kTrue);
 
  154    return absl::OkStatus();
 
  156  insert.bytes->insert(insert.at, FormatSignature::kFalse);
 
  157  return absl::OkStatus();
 
  160inline absl::StatusOr<uint32_t> EgltMsgpackDeserialize(
 
  161    const LookupPointer& data, 
bool* absl_nonnull output) {
 
  162  const auto [pos, end, _] = data;
 
  163  if (*pos == FormatSignature::kFalse) {
 
  165    return absl::OkStatus();
 
  167  if (*pos == FormatSignature::kTrue) {
 
  169    return absl::OkStatus();
 
  171  return GetInvalidFormatSignatureError(pos, 
"bool", data.begin);
 
  175absl::StatusOr<uint32_t> EgltMsgpackGetExtent(
const LookupPointer& data,
 
  176                                              std::optional<T>* absl_nullable) {
 
  177  const auto [pos, end, _] = data;
 
  178  if (*pos == FormatSignature::kNil) {
 
  181  return GetExtent<T>(pos, end);
 
  185absl::Status EgltMsgpackSerialize(
const std::optional<T>& value,
 
  186                                  const InsertInfo& insert) {
 
  188    insert.bytes->insert(insert.at, FormatSignature::kNil);
 
  189    return absl::OkStatus();
 
  191  return Serialize<T>(*value, insert);
 
  195absl::StatusOr<uint32_t> EgltMsgpackDeserialize(
 
  196    const LookupPointer& data, std::optional<T>* absl_nonnull output) {
 
  197  const auto [pos, end, _] = data;
 
  198  if (*pos == FormatSignature::kNil) {
 
  199    *output = std::nullopt;
 
  201  *output = Deserialize<T>(pos, end);
 
  202  return absl::OkStatus();
 
  205inline absl::StatusOr<uint32_t> EgltMsgpackGetExtent(
 
  206    const LookupPointer& data, std::nullopt_t* absl_nullable) {
 
  207  if (data.pos >= data.end) {
 
  208    return absl::InvalidArgumentError(
 
  209        "Position is not within the bounds of the data.");
 
  211  if (*data.pos == FormatSignature::kNil) {
 
  214  return GetInvalidFormatSignatureError(data.pos, 
"std::nullopt_t", data.begin);
 
  217inline absl::Status EgltMsgpackSerialize(std::nullopt_t,
 
  218                                         const InsertInfo& insert) {
 
  219  insert.bytes->insert(insert.at, FormatSignature::kNil);
 
  220  return absl::OkStatus();
 
  223inline absl::StatusOr<uint32_t> EgltMsgpackDeserialize(
 
  224    const LookupPointer& data, std::nullopt_t* absl_nonnull output) {
 
  225  const auto [pos, end, _] = data;
 
  226  if (*pos == FormatSignature::kNil) {
 
  227    *output = std::nullopt;
 
  230  return GetInvalidFormatSignatureError(pos, 
"std::nullopt_t", data.begin);