Action Engine
Loading...
Searching...
No Matches
float.h
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef ACTIONENGINE_MSGPACK_FLOAT_H
16#define ACTIONENGINE_MSGPACK_FLOAT_H
17
18#include <limits>
19
20#include "actionengine/msgpack/core_helpers.h"
21#include "actionengine/msgpack/int.h"
22
23namespace act::msgpack {
24
25inline absl::StatusOr<uint32_t> EgltMsgpackGetExtent(const LookupPointer& data,
26 float32_t* absl_nullable) {
27 const auto [pos, end, _] = data;
28 if (*pos == FormatSignature::kFloat32) {
29 if (end - pos < 5) {
30 return GetInsufficientDataError(data, "float32_t");
31 }
32 return 5; // 1 byte for the signature + 4 bytes for the value.
33 }
34
35 if (const auto int64_extent = GetExtent<int64_t>(pos, end);
36 int64_extent.ok()) {
37 return int64_extent;
38 }
39
40 if (const auto uint64_extent = GetExtent<uint64_t>(pos, end);
41 uint64_extent.ok()) {
42 return uint64_extent;
43 }
44
45 return GetInvalidFormatSignatureError(pos, "float32_t", data.begin);
46}
47
48inline absl::Status EgltMsgpackSerialize(float32_t value,
49 const InsertInfo& insert) {
50 if constexpr (!std::numeric_limits<float32_t>::is_iec559) {
51 return SerializeNonIec559Float32(value, insert);
52 }
53 auto result = ToBigEndianBytes<float32_t>(value, /*pad=*/1);
54 result[0] = FormatSignature::kFloat32;
55 insert.bytes->insert(insert.at, result.begin(), result.end());
56 return absl::OkStatus();
57}
58
59inline absl::StatusOr<uint32_t> EgltMsgpackDeserialize(
60 const LookupPointer& data, float32_t* absl_nonnull output) {
61 const auto [pos, end, _] = data;
62 if (*pos == FormatSignature::kFloat32) {
63 if (end - pos < 5) {
64 return GetInsufficientDataError(data, "float32_t");
65 }
66 *output = FromBigEndianBytes<float32_t>(pos + 1);
67 return 5; // 1 byte for the signature + 4 bytes for the value.
68 }
69
70 if (*pos == FormatSignature::kFloat64) {
71 if (end - pos < 9) {
72 return GetInsufficientDataError(data, "float32_t");
73 }
74 *output = static_cast<float32_t>(FromBigEndianBytes<float64_t>(pos + 1));
75 return 9; // 1 byte for the signature + 8 bytes for the value.
76 }
77
78 if (auto deserialized = Deserialize<int64_t>(data); deserialized.ok()) {
79 *output = static_cast<float32_t>(deserialized->value);
80 return deserialized->extent;
81 }
82
83 if (auto deserialized = Deserialize<uint64_t>(data); deserialized.ok()) {
84 *output = static_cast<float32_t>(deserialized->value);
85 return deserialized->extent;
86 }
87
88 return GetInvalidFormatSignatureError(pos, "float32_t", data.begin);
89}
90
91inline absl::StatusOr<uint32_t> EgltMsgpackGetExtent(const LookupPointer& data,
92 float64_t* absl_nullable) {
93 const auto [pos, end, _] = data;
94 if (*pos == FormatSignature::kFloat64) {
95 if (end - pos < 9) {
96 return GetInsufficientDataError(data, "float64_t");
97 }
98 return 9; // 1 byte for the signature + 8 bytes for the value.
99 }
100
101 if (const auto float32_extent = GetExtent<float32_t>(pos, end);
102 float32_extent.ok()) {
103 return float32_extent;
104 }
105
106 if (const auto int64_extent = GetExtent<int64_t>(pos, end);
107 int64_extent.ok()) {
108 return int64_extent;
109 }
110
111 if (const auto uint64_extent = GetExtent<uint64_t>(pos, end);
112 uint64_extent.ok()) {
113 return uint64_extent;
114 }
115
116 return GetInvalidFormatSignatureError(pos, "float64_t", data.begin);
117}
118
119inline absl::Status EgltMsgpackSerialize(float64_t value,
120 const InsertInfo& insert) {
121 if constexpr (!std::numeric_limits<float64_t>::is_iec559) {
122 return SerializeNonIec559Float64(value, insert);
123 }
124 auto result = ToBigEndianBytes<float64_t>(value, /*pad=*/1);
125 result[0] = FormatSignature::kFloat64;
126 insert.bytes->insert(insert.at, result.begin(), result.end());
127 return absl::OkStatus();
128}
129
130inline absl::StatusOr<uint32_t> EgltMsgpackDeserialize(
131 const LookupPointer& data, float64_t* absl_nonnull output) {
132 const auto [pos, end, _] = data;
133 if (*pos == FormatSignature::kFloat64) {
134 if (end - pos < 9) {
135 return GetInsufficientDataError(data, "float64_t");
136 }
137 *output = FromBigEndianBytes<float64_t>(pos + 1);
138 return 9; // 1 byte for the signature + 8 bytes for the value.
139 }
140
141 if (*pos == FormatSignature::kFloat32) {
142 if (end - pos < 5) {
143 return GetInsufficientDataError(data, "float64_t");
144 }
145 *output = static_cast<float64_t>(FromBigEndianBytes<float32_t>(pos + 1));
146 return 5; // 1 byte for the signature + 4 bytes for the value.
147 }
148
149 if (auto deserialized = Deserialize<int64_t>(data); deserialized.ok()) {
150 *output = static_cast<float64_t>(deserialized->value);
151 return deserialized->extent;
152 }
153
154 if (auto deserialized = Deserialize<uint64_t>(data); deserialized.ok()) {
155 *output = static_cast<float64_t>(deserialized->value);
156 return deserialized->extent;
157 }
158
159 return GetInvalidFormatSignatureError(pos, "float64_t", data.begin);
160}
161
162} // namespace act::msgpack
163
164#endif // ACTIONENGINE_MSGPACK_FLOAT_H