barretenberg
Loading...
Searching...
No Matches
binary.hpp
1// Copyright (c) Facebook, Inc. and its affiliates
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4#pragma once
5
6#include <algorithm>
7#include <cassert>
8#include <variant>
9
10#include "serde.hpp"
11
12namespace serde {
13
14template <class S> class BinarySerializer {
15 protected:
16 std::vector<uint8_t> bytes_;
17 size_t container_depth_budget_;
18
19 public:
20 BinarySerializer(size_t max_container_depth)
21 : container_depth_budget_(max_container_depth)
22 {}
23
24 void serialize_str(const std::string& value);
25
26 void serialize_bool(bool value);
27 void serialize_unit();
28 void serialize_char(char32_t value);
29 void serialize_f32(float value);
30 void serialize_f64(double value);
31
32 void serialize_u8(uint8_t value);
33 void serialize_u16(uint16_t value);
34 void serialize_u32(uint32_t value);
35 void serialize_u64(uint64_t value);
36 void serialize_u128(const uint128_t& value);
37
38 void serialize_i8(int8_t value);
39 void serialize_i16(int16_t value);
40 void serialize_i32(int32_t value);
41 void serialize_i64(int64_t value);
42 void serialize_i128(const int128_t& value);
43 void serialize_option_tag(bool value);
44
45 size_t get_buffer_offset();
46 void increase_container_depth();
47 void decrease_container_depth();
48
49 std::vector<uint8_t> bytes() && { return std::move(bytes_); }
50};
51
52template <class D> class BinaryDeserializer {
53 size_t pos_;
54 size_t container_depth_budget_;
55
56 protected:
57 std::vector<uint8_t> bytes_;
58 uint8_t read_byte();
59
60 public:
61 BinaryDeserializer(std::vector<uint8_t> bytes, size_t max_container_depth)
62 : pos_(0)
63 , container_depth_budget_(max_container_depth)
64 , bytes_(std::move(bytes))
65 {}
66
67 std::string deserialize_str();
68
69 bool deserialize_bool();
70 std::monostate deserialize_unit();
71 char32_t deserialize_char();
72 float deserialize_f32();
73 double deserialize_f64();
74
75 uint8_t deserialize_u8();
76 uint16_t deserialize_u16();
77 uint32_t deserialize_u32();
78 uint64_t deserialize_u64();
79 uint128_t deserialize_u128();
80
81 int8_t deserialize_i8();
82 int16_t deserialize_i16();
83 int32_t deserialize_i32();
84 int64_t deserialize_i64();
85 int128_t deserialize_i128();
86
87 bool deserialize_option_tag();
88
89 size_t get_buffer_offset();
90 void increase_container_depth();
91 void decrease_container_depth();
92};
93
94template <class S> void BinarySerializer<S>::serialize_str(const std::string& value)
95{
96 static_cast<S*>(this)->serialize_len(value.size());
97 for (auto c : value) {
98 bytes_.push_back(c);
99 }
100}
101
102template <class S> void BinarySerializer<S>::serialize_unit() {}
103
104template <class S> void BinarySerializer<S>::serialize_f32(float)
105{
106 throw_or_abort("not implemented");
107}
108
109template <class S> void BinarySerializer<S>::serialize_f64(double)
110{
111 throw_or_abort("not implemented");
112}
113
114template <class S> void BinarySerializer<S>::serialize_char(char32_t)
115{
116 throw_or_abort("not implemented");
117}
118
119template <class S> void BinarySerializer<S>::serialize_bool(bool value)
120{
121 bytes_.push_back((uint8_t)value);
122}
123
124template <class S> void BinarySerializer<S>::serialize_u8(uint8_t value)
125{
126 bytes_.push_back(value);
127}
128
129template <class S> void BinarySerializer<S>::serialize_u16(uint16_t value)
130{
131 bytes_.push_back((uint8_t)value);
132 bytes_.push_back((uint8_t)(value >> 8));
133}
134
135template <class S> void BinarySerializer<S>::serialize_u32(uint32_t value)
136{
137 bytes_.push_back((uint8_t)value);
138 bytes_.push_back((uint8_t)(value >> 8));
139 bytes_.push_back((uint8_t)(value >> 16));
140 bytes_.push_back((uint8_t)(value >> 24));
141}
142
143template <class S> void BinarySerializer<S>::serialize_u64(uint64_t value)
144{
145 bytes_.push_back((uint8_t)value);
146 bytes_.push_back((uint8_t)(value >> 8));
147 bytes_.push_back((uint8_t)(value >> 16));
148 bytes_.push_back((uint8_t)(value >> 24));
149 bytes_.push_back((uint8_t)(value >> 32));
150 bytes_.push_back((uint8_t)(value >> 40));
151 bytes_.push_back((uint8_t)(value >> 48));
152 bytes_.push_back((uint8_t)(value >> 56));
153}
154
155template <class S> void BinarySerializer<S>::serialize_u128(const uint128_t& value)
156{
157 serialize_u64(value.low);
158 serialize_u64(value.high);
159}
160
161template <class S> void BinarySerializer<S>::serialize_i8(int8_t value)
162{
163 serialize_u8((uint8_t)value);
164}
165
166template <class S> void BinarySerializer<S>::serialize_i16(int16_t value)
167{
168 serialize_u16((uint16_t)value);
169}
170
171template <class S> void BinarySerializer<S>::serialize_i32(int32_t value)
172{
173 serialize_u32((uint32_t)value);
174}
175
176template <class S> void BinarySerializer<S>::serialize_i64(int64_t value)
177{
178 serialize_u64((uint64_t)value);
179}
180
181template <class S> void BinarySerializer<S>::serialize_i128(const int128_t& value)
182{
183 serialize_u64(value.low);
184 serialize_i64(value.high);
185}
186
187template <class S> void BinarySerializer<S>::serialize_option_tag(bool value)
188{
189 serialize_bool(value);
190}
191
192template <class S> size_t BinarySerializer<S>::get_buffer_offset()
193{
194 return bytes_.size();
195}
196
197template <class S> void BinarySerializer<S>::increase_container_depth()
198{
199 if (container_depth_budget_ == 0) {
200 throw_or_abort("Too many nested containers");
201 }
202 container_depth_budget_--;
203}
204
205template <class S> void BinarySerializer<S>::decrease_container_depth()
206{
207 container_depth_budget_++;
208}
209
210template <class D> uint8_t BinaryDeserializer<D>::read_byte()
211{
212 if (pos_ >= bytes_.size()) {
213 throw_or_abort("Input is not large enough");
214 }
215 return bytes_.at(pos_++);
216}
217
218inline bool is_valid_utf8(const std::string& input)
219{
220 uint8_t trailing_digits = 0;
221 for (char byte : input) {
222 if (trailing_digits == 0) {
223 // Start new codepoint.
224 if (byte >> 7 == 0) {
225 // ASCII character
226 } else if (byte >> 5 == 0b110) {
227 // Expecting a 2-byte codepoint
228 trailing_digits = 1;
229 } else if (byte >> 4 == 0b1110) {
230 // Expecting a 3-byte codepoint
231 trailing_digits = 2;
232 } else if (byte >> 3 == 0b11110) {
233 // Expecting a 4-byte codepoint
234 trailing_digits = 3;
235 } else {
236 return false;
237 }
238 } else {
239 // Process "trailing digit".
240 if (byte >> 6 != 0b10) {
241 return false;
242 }
243 trailing_digits -= 1;
244 }
245 }
246 return trailing_digits == 0;
247}
248
249template <class D> std::string BinaryDeserializer<D>::deserialize_str()
250{
251 auto len = static_cast<D*>(this)->deserialize_len();
252 std::string result;
253 result.reserve(len);
254 for (size_t i = 0; i < len; i++) {
255 result.push_back(read_byte());
256 }
257 if (!is_valid_utf8(result)) {
258 throw_or_abort("Invalid UTF8 string: " + result);
259 }
260 return result;
261}
262
263template <class D> std::monostate BinaryDeserializer<D>::deserialize_unit()
264{
265 return {};
266}
267
268template <class D> float BinaryDeserializer<D>::deserialize_f32()
269{
270 throw_or_abort("not implemented");
271}
272
273template <class D> double BinaryDeserializer<D>::deserialize_f64()
274{
275 throw_or_abort("not implemented");
276}
277
278template <class D> char32_t BinaryDeserializer<D>::deserialize_char()
279{
280 throw_or_abort("not implemented");
281}
282
283template <class D> bool BinaryDeserializer<D>::deserialize_bool()
284{
285 switch (read_byte()) {
286 case 0:
287 return false;
288 case 1:
289 return true;
290 default:
291 throw_or_abort("Invalid boolean value");
292 }
293}
294
295template <class D> uint8_t BinaryDeserializer<D>::deserialize_u8()
296{
297 return read_byte();
298}
299
300template <class D> uint16_t BinaryDeserializer<D>::deserialize_u16()
301{
302 uint16_t val = 0;
303 val |= (uint16_t)read_byte();
304 val |= (uint16_t)read_byte() << 8;
305 return val;
306}
307
308template <class D> uint32_t BinaryDeserializer<D>::deserialize_u32()
309{
310 uint32_t val = 0;
311 val |= (uint32_t)read_byte();
312 val |= (uint32_t)read_byte() << 8;
313 val |= (uint32_t)read_byte() << 16;
314 val |= (uint32_t)read_byte() << 24;
315 return val;
316}
317
318template <class D> uint64_t BinaryDeserializer<D>::deserialize_u64()
319{
320 uint64_t val = 0;
321 val |= (uint64_t)read_byte();
322 val |= (uint64_t)read_byte() << 8;
323 val |= (uint64_t)read_byte() << 16;
324 val |= (uint64_t)read_byte() << 24;
325 val |= (uint64_t)read_byte() << 32;
326 val |= (uint64_t)read_byte() << 40;
327 val |= (uint64_t)read_byte() << 48;
328 val |= (uint64_t)read_byte() << 56;
329 return val;
330}
331
332template <class D> uint128_t BinaryDeserializer<D>::deserialize_u128()
333{
334 uint128_t result;
335 result.low = deserialize_u64();
336 result.high = deserialize_u64();
337 return result;
338}
339
340template <class D> int8_t BinaryDeserializer<D>::deserialize_i8()
341{
342 return (int8_t)deserialize_u8();
343}
344
345template <class D> int16_t BinaryDeserializer<D>::deserialize_i16()
346{
347 return (int16_t)deserialize_u16();
348}
349
350template <class D> int32_t BinaryDeserializer<D>::deserialize_i32()
351{
352 return (int32_t)deserialize_u32();
353}
354
355template <class D> int64_t BinaryDeserializer<D>::deserialize_i64()
356{
357 return (int64_t)deserialize_u64();
358}
359
360template <class D> int128_t BinaryDeserializer<D>::deserialize_i128()
361{
362 int128_t result;
363 result.low = deserialize_u64();
364 result.high = deserialize_i64();
365 return result;
366}
367
368template <class D> bool BinaryDeserializer<D>::deserialize_option_tag()
369{
370 return deserialize_bool();
371}
372
373template <class D> size_t BinaryDeserializer<D>::get_buffer_offset()
374{
375 return pos_;
376}
377
378template <class S> void BinaryDeserializer<S>::increase_container_depth()
379{
380 if (container_depth_budget_ == 0) {
381 throw_or_abort("Too many nested containers");
382 }
383 container_depth_budget_--;
384}
385
386template <class S> void BinaryDeserializer<S>::decrease_container_depth()
387{
388 container_depth_budget_++;
389}
390
391} // end of namespace serde
Definition: binary.hpp:52
Definition: binary.hpp:14
Definition: serde.hpp:56
Definition: serde.hpp:43