Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
serde.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7// Copyright (c) Facebook, Inc. and its affiliates
8// SPDX-License-Identifier: MIT OR Apache-2.0
9
10#pragma once
11
13#include <array>
14#include <cstdint>
15#include <functional>
16#include <map>
17#include <memory>
18#include <optional>
19#include <stdexcept>
20#include <string>
21#include <tuple>
22#include <type_traits>
23#include <variant>
24#include <vector>
25
26namespace serde {
27
28class serialization_error : public std::invalid_argument {
29 public:
30 explicit serialization_error(const std::string& what_arg)
31 : std::invalid_argument(what_arg)
32 {}
33 explicit serialization_error(const char* what_arg)
34 : std::invalid_argument(what_arg)
35 {}
36};
37
38class deserialization_error : public std::invalid_argument {
39 public:
40 explicit deserialization_error(const std::string& what_arg)
41 : std::invalid_argument(what_arg)
42 {}
43 explicit deserialization_error(const char* what_arg)
44 : std::invalid_argument(what_arg)
45 {}
46};
47
48// Basic implementation for 128-bit unsigned integers.
49struct uint128_t {
50 uint64_t high;
51 uint64_t low;
52
53 friend bool operator==(const uint128_t&, const uint128_t&);
54};
55
56inline bool operator==(const uint128_t& lhs, const uint128_t& rhs)
57{
58 return lhs.high == rhs.high && lhs.low == rhs.low;
59}
60
61// 128-bit signed integers.
62struct int128_t {
63 int64_t high;
64 uint64_t low;
65
66 friend bool operator==(const int128_t&, const int128_t&);
67};
68
69inline bool operator==(const int128_t& lhs, const int128_t& rhs)
70{
71 return lhs.high == rhs.high && lhs.low == rhs.low;
72}
73
74// A copyable unique_ptr with value semantics.
75// Freely inspired by the following discussion:
76// https://codereview.stackexchange.com/questions/103744/deepptr-a-deep-copying-unique-ptr-wrapper-in-c
77template <typename T> class value_ptr {
78 public:
80 : ptr_(nullptr)
81 {}
82
83 value_ptr(const T& value)
84 : ptr_(new T{ value })
85 {}
86
87 value_ptr(const value_ptr& other)
88 : ptr_(nullptr)
89 {
90 if (other) {
91 ptr_ = std::unique_ptr<T>{ new T{ *other } };
92 }
93 }
94
96 {
97 value_ptr temp{ other };
98 std::swap(ptr_, temp.ptr_);
99 return *this;
100 }
101
102 value_ptr(value_ptr&& other) = default;
103
104 value_ptr& operator=(value_ptr&& other) = default;
105
106 T& operator*() { return *ptr_; }
107
108 const T& operator*() const { return *ptr_; }
109
110 T* const operator->() { return ptr_.operator->(); }
111
112 const T* const operator->() const { return ptr_.operator->(); }
113
114 const T* const get() const { return ptr_.get(); }
115
116 operator bool() const { return (bool)ptr_; }
117
118 template <typename U> friend bool operator==(const value_ptr<U>&, const value_ptr<U>&);
119
120 private:
122};
123
124template <typename T> bool operator==(const value_ptr<T>& lhs, const value_ptr<T>& rhs)
125{
126 return *lhs == *rhs;
127}
128
129// Trait to enable serialization of values of type T.
130// This is similar to the `serde::Serialize` trait in Rust.
131template <typename T> struct Serializable {
132 template <typename Serializer> static void serialize(const T& value, Serializer& serializer);
133};
134
135// Trait to enable deserialization of values of type T.
136// This is similar to the `serde::Deserialize` trait in Rust.
137template <typename T> struct Deserializable {
138 template <typename Deserializer> static T deserialize(Deserializer& deserializer);
139};
140
141// --- Implementation of Serializable for base types ---
142
143// string
144template <> struct Serializable<std::string> {
145 template <typename Serializer> static void serialize(const std::string& value, Serializer& serializer)
146 {
147 serializer.serialize_str(value);
148 }
149};
150
151// unit
152template <> struct Serializable<std::monostate> {
153 template <typename Serializer> static void serialize(const std::monostate&, Serializer& serializer)
154 {
155 serializer.serialize_unit();
156 }
157};
158
159// bool
160template <> struct Serializable<bool> {
161 template <typename Serializer> static void serialize(const bool& value, Serializer& serializer)
162 {
163 serializer.serialize_bool(value);
164 }
165};
166
167// UTF-8 char
168template <> struct Serializable<char32_t> {
169 template <typename Serializer> static void serialize(const char32_t& value, Serializer& serializer)
170 {
171 serializer.serialize_char(value);
172 }
173};
174
175// f32
176template <> struct Serializable<float> {
177 template <typename Serializer> static void serialize(const float& value, Serializer& serializer)
178 {
179 serializer.serialize_f32(value);
180 }
181};
182
183// f64
184template <> struct Serializable<double> {
185 template <typename Serializer> static void serialize(const double& value, Serializer& serializer)
186 {
187 serializer.serialize_f64(value);
188 }
189};
190
191// u8
192template <> struct Serializable<uint8_t> {
193 template <typename Serializer> static void serialize(const uint8_t& value, Serializer& serializer)
194 {
195 serializer.serialize_u8(value);
196 }
197};
198
199// u16
200template <> struct Serializable<uint16_t> {
201 template <typename Serializer> static void serialize(const uint16_t& value, Serializer& serializer)
202 {
203 serializer.serialize_u16(value);
204 }
205};
206
207// u32
208template <> struct Serializable<uint32_t> {
209 template <typename Serializer> static void serialize(const uint32_t& value, Serializer& serializer)
210 {
211 serializer.serialize_u32(value);
212 }
213};
214
215// u64
216template <> struct Serializable<uint64_t> {
217 template <typename Serializer> static void serialize(const uint64_t& value, Serializer& serializer)
218 {
219 serializer.serialize_u64(value);
220 }
221};
222
223// u128
224template <> struct Serializable<uint128_t> {
225 template <typename Serializer> static void serialize(const uint128_t& value, Serializer& serializer)
226 {
227 serializer.serialize_u128(value);
228 }
229};
230
231// i8
232template <> struct Serializable<int8_t> {
233 template <typename Serializer> static void serialize(const int8_t& value, Serializer& serializer)
234 {
235 serializer.serialize_i8(value);
236 }
237};
238
239// i16
240template <> struct Serializable<int16_t> {
241 template <typename Serializer> static void serialize(const int16_t& value, Serializer& serializer)
242 {
243 serializer.serialize_i16(value);
244 }
245};
246
247// i32
248template <> struct Serializable<int32_t> {
249 template <typename Serializer> static void serialize(const int32_t& value, Serializer& serializer)
250 {
251 serializer.serialize_i32(value);
252 }
253};
254
255// i64
256template <> struct Serializable<int64_t> {
257 template <typename Serializer> static void serialize(const int64_t& value, Serializer& serializer)
258 {
259 serializer.serialize_i64(value);
260 }
261};
262
263// i128
264template <> struct Serializable<int128_t> {
265 template <typename Serializer> static void serialize(const int128_t& value, Serializer& serializer)
266 {
267 serializer.serialize_i128(value);
268 }
269};
270
271// --- Derivation of Serializable for composite types ---
272
273// Value pointers (non-nullable)
274template <typename T> struct Serializable<value_ptr<T>> {
275 template <typename Serializer> static void serialize(const value_ptr<T>& value, Serializer& serializer)
276 {
277 Serializable<T>::serialize(*value, serializer);
278 }
279};
280
281// Options
282template <typename T> struct Serializable<std::optional<T>> {
283 template <typename Serializer> static void serialize(const std::optional<T>& option, Serializer& serializer)
284 {
285 if (option.has_value()) {
286 serializer.serialize_option_tag(true);
287 Serializable<T>::serialize(option.value(), serializer);
288 } else {
289 serializer.serialize_option_tag(false);
290 }
291 }
292};
293
294// Vectors (sequences)
295template <typename T, typename Allocator> struct Serializable<std::vector<T, Allocator>> {
296 template <typename Serializer> static void serialize(const std::vector<T, Allocator>& value, Serializer& serializer)
297 {
298 serializer.serialize_len(value.size());
299 for (const T& item : value) {
300 Serializable<T>::serialize(item, serializer);
301 }
302 }
303};
304
305// Fixed-size arrays
306template <typename T, std::size_t N> struct Serializable<std::array<T, N>> {
307 template <typename Serializer> static void serialize(const std::array<T, N>& value, Serializer& serializer)
308 {
309 for (const T& item : value) {
310 Serializable<T>::serialize(item, serializer);
311 }
312 }
313};
314
315// Maps
316template <typename K, typename V, typename Allocator> struct Serializable<std::map<K, V, Allocator>> {
317 template <typename Serializer> static void serialize(const std::map<K, V, Allocator>& value, Serializer& serializer)
318 {
319 serializer.serialize_len(value.size());
320 std::vector<size_t> offsets;
321 for (const auto& item : value) {
322 if constexpr (Serializer::enforce_strict_map_ordering) {
323 offsets.push_back(serializer.get_buffer_offset());
324 }
325 Serializable<K>::serialize(item.first, serializer);
326 Serializable<V>::serialize(item.second, serializer);
327 }
328 if constexpr (Serializer::enforce_strict_map_ordering) {
329 serializer.sort_last_entries(std::move(offsets));
330 }
331 }
332};
333
334// Tuples
335template <class... Types> struct Serializable<std::tuple<Types...>> {
336 template <typename Serializer> static void serialize(const std::tuple<Types...>& value, Serializer& serializer)
337 {
338 // Visit each of the type components.
339 std::apply([&serializer](Types const&... args) { (Serializable<Types>::serialize(args, serializer), ...); },
340 value);
341 }
342};
343
344// Enums
345template <class... Types> struct Serializable<std::variant<Types...>> {
346 template <typename Serializer> static void serialize(const std::variant<Types...>& value, Serializer& serializer)
347 {
348 // Write the variant index.
349 serializer.serialize_variant_index(value.index());
350 // Visit the inner type.
351 std::visit(
352 [&serializer](const auto& arg) {
353 using T = typename std::decay<decltype(arg)>::type;
354 Serializable<T>::serialize(arg, serializer);
355 },
356 value);
357 }
358};
359
360// Shared pointers
361template <class Type> struct Serializable<std::shared_ptr<Type>> {
362 template <typename Serializer> static void serialize(const std::shared_ptr<Type>& value, Serializer& serializer)
363 {
365 }
366};
367
368// --- Implementation of Deserializable for base types ---
369
370// string
371template <> struct Deserializable<std::string> {
372 template <typename Deserializer> static std::string deserialize(Deserializer& deserializer)
373 {
374 return deserializer.deserialize_str();
375 }
376};
377
378// unit
379template <> struct Deserializable<std::monostate> {
380 template <typename Deserializer> static std::monostate deserialize(Deserializer& deserializer)
381 {
382 return deserializer.deserialize_unit();
383 }
384};
385
386// bool
387template <> struct Deserializable<bool> {
388 template <typename Deserializer> static bool deserialize(Deserializer& deserializer)
389 {
390 return deserializer.deserialize_bool();
391 }
392};
393
394// f32
395template <> struct Deserializable<float> {
396 template <typename Deserializer> static float deserialize(Deserializer& deserializer)
397 {
398 return deserializer.deserialize_f32();
399 }
400};
401
402// f64
403template <> struct Deserializable<double> {
404 template <typename Deserializer> static double deserialize(Deserializer& deserializer)
405 {
406 return deserializer.deserialize_f64();
407 }
408};
409
410// UTF-8 char
411template <> struct Deserializable<char32_t> {
412 template <typename Deserializer> static char32_t deserialize(Deserializer& deserializer)
413 {
414 return deserializer.deserialize_char();
415 }
416};
417
418// u8
419template <> struct Deserializable<uint8_t> {
420 template <typename Deserializer> static uint8_t deserialize(Deserializer& deserializer)
421 {
422 return deserializer.deserialize_u8();
423 }
424};
425
426// u16
427template <> struct Deserializable<uint16_t> {
428 template <typename Deserializer> static uint16_t deserialize(Deserializer& deserializer)
429 {
430 return deserializer.deserialize_u16();
431 }
432};
433
434// u32
435template <> struct Deserializable<uint32_t> {
436 template <typename Deserializer> static uint32_t deserialize(Deserializer& deserializer)
437 {
438 return deserializer.deserialize_u32();
439 }
440};
441
442// u64
443template <> struct Deserializable<uint64_t> {
444 template <typename Deserializer> static uint64_t deserialize(Deserializer& deserializer)
445 {
446 return deserializer.deserialize_u64();
447 }
448};
449
450// u128
451template <> struct Deserializable<uint128_t> {
452 template <typename Deserializer> static uint128_t deserialize(Deserializer& deserializer)
453 {
454 return deserializer.deserialize_u128();
455 }
456};
457
458// i8
459template <> struct Deserializable<int8_t> {
460 template <typename Deserializer> static int8_t deserialize(Deserializer& deserializer)
461 {
462 return deserializer.deserialize_i8();
463 }
464};
465
466// i16
467template <> struct Deserializable<int16_t> {
468 template <typename Deserializer> static int16_t deserialize(Deserializer& deserializer)
469 {
470 return deserializer.deserialize_i16();
471 }
472};
473
474// i32
475template <> struct Deserializable<int32_t> {
476 template <typename Deserializer> static int32_t deserialize(Deserializer& deserializer)
477 {
478 return deserializer.deserialize_i32();
479 }
480};
481
482// i64
483template <> struct Deserializable<int64_t> {
484 template <typename Deserializer> static int64_t deserialize(Deserializer& deserializer)
485 {
486 return deserializer.deserialize_i64();
487 }
488};
489
490// i128
491template <> struct Deserializable<int128_t> {
492 template <typename Deserializer> static int128_t deserialize(Deserializer& deserializer)
493 {
494 return deserializer.deserialize_i128();
495 }
496};
497
498// --- Derivation of Deserializable for composite types ---
499
500// Value pointers
501template <typename T> struct Deserializable<value_ptr<T>> {
502 template <typename Deserializer> static value_ptr<T> deserialize(Deserializer& deserializer)
503 {
504 return value_ptr<T>(Deserializable<T>::deserialize(deserializer));
505 }
506};
507
508// Options
509template <typename T> struct Deserializable<std::optional<T>> {
510 template <typename Deserializer> static std::optional<T> deserialize(Deserializer& deserializer)
511 {
512 auto tag = deserializer.deserialize_option_tag();
513 if (!tag) {
514 return {};
515 } else {
516 return { Deserializable<T>::deserialize(deserializer) };
517 }
518 }
519};
520
521// Vectors
522template <typename T, typename Allocator> struct Deserializable<std::vector<T, Allocator>> {
523 template <typename Deserializer> static std::vector<T> deserialize(Deserializer& deserializer)
524 {
525 size_t len = deserializer.deserialize_len();
526 std::vector<T> result(len);
527 for (size_t i = 0; i < len; i++) {
528 result[i] = Deserializable<T>::deserialize(deserializer);
529 }
530 return result;
531 }
532};
533
534// Maps
535template <typename K, typename V> struct Deserializable<std::map<K, V>> {
536 template <typename Deserializer> static std::map<K, V> deserialize(Deserializer& deserializer)
537 {
538 std::map<K, V> result;
539 size_t len = deserializer.deserialize_len();
541 for (size_t i = 0; i < len; i++) {
542 if constexpr (Deserializer::enforce_strict_map_ordering) {
543 auto start = deserializer.get_buffer_offset();
544 auto key = Deserializable<K>::deserialize(deserializer);
545 auto end = deserializer.get_buffer_offset();
546 if (previous_key_slice.has_value()) {
547 deserializer.check_that_key_slices_are_increasing(previous_key_slice.value(), { start, end });
548 }
549 previous_key_slice = { start, end };
550 auto value = Deserializable<V>::deserialize(deserializer);
551 result.insert({ key, value });
552 } else {
553 auto key = Deserializable<K>::deserialize(deserializer);
554 auto value = Deserializable<V>::deserialize(deserializer);
555 result.insert({ key, value });
556 }
557 }
558 return result;
559 }
560};
561
562// Fixed-size arrays
563template <typename T, std::size_t N> struct Deserializable<std::array<T, N>> {
564 template <typename Deserializer> static std::array<T, N> deserialize(Deserializer& deserializer)
565 {
566 std::array<T, N> result;
567 for (T& item : result) {
568 item = Deserializable<T>::deserialize(deserializer);
569 }
570 return result;
571 }
572};
573
574// Tuples
575template <class... Types> struct Deserializable<std::tuple<Types...>> {
576 template <typename Deserializer> static std::tuple<Types...> deserialize(Deserializer& deserializer)
577 {
578 // Visit each of the type components. We use the constructor of `std::tuple` so
579 // that the evaluation order of arguments is specified by the C++ standard.
580 return std::tuple<Types...>{ Deserializable<Types>::deserialize(deserializer)... };
581 }
582};
583
584// Enums
585template <class... Types> struct Deserializable<std::variant<Types...>> {
586 template <typename Deserializer> static std::variant<Types...> deserialize(Deserializer& deserializer)
587 {
588 // A "case" is analog to a particular branch in switch-case over the
589 // index. Given the variant type `T` known statically, we create a
590 // closure that will deserialize a value `T` and return it as a variant.
591 using Case = std::function<std::variant<Types...>(Deserializer&)>;
592 auto make_case = [](auto tag) -> Case {
593 // Obtain the type `T` encoded in the type of `tag ==
594 // std::common_type<T>{}`.
595 using T = typename decltype(tag)::type;
596 auto f = [](Deserializer& de) { return std::variant<Types...>(Deserializable<T>::deserialize(de)); };
597 return f;
598 };
599
600 // The static array of all the cases for this variant.
601 static const std::array<Case, sizeof...(Types)> cases = { make_case(std::common_type<Types>{})... };
602
603 // Read the variant index and execute the corresponding case.
604 auto index = deserializer.deserialize_variant_index();
605 if (index > cases.size()) {
606 throw_or_abort("Unknown variant index for enum");
607 }
608 return cases.at(index)(deserializer);
609 }
610};
611
612// Shared pointers
613template <class Type> struct Deserializable<std::shared_ptr<Type>> {
614 template <typename Deserializer> static std::shared_ptr<Type> deserialize(Deserializer& serializer)
615 {
617 }
618};
619
620} // end of namespace serde
deserialization_error(const std::string &what_arg)
Definition serde.hpp:40
deserialization_error(const char *what_arg)
Definition serde.hpp:43
serialization_error(const char *what_arg)
Definition serde.hpp:33
serialization_error(const std::string &what_arg)
Definition serde.hpp:30
value_ptr & operator=(const value_ptr &other)
Definition serde.hpp:95
friend bool operator==(const value_ptr< U > &, const value_ptr< U > &)
const T *const operator->() const
Definition serde.hpp:112
value_ptr(value_ptr &&other)=default
value_ptr & operator=(value_ptr &&other)=default
T *const operator->()
Definition serde.hpp:110
std::unique_ptr< T > ptr_
Definition serde.hpp:121
const T & operator*() const
Definition serde.hpp:108
value_ptr(const value_ptr &other)
Definition serde.hpp:87
value_ptr(const T &value)
Definition serde.hpp:83
const T *const get() const
Definition serde.hpp:114
bool operator==(const uint128_t &lhs, const uint128_t &rhs)
Definition serde.hpp:56
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
uint8_t len
static bool deserialize(Deserializer &deserializer)
Definition serde.hpp:388
static char32_t deserialize(Deserializer &deserializer)
Definition serde.hpp:412
static double deserialize(Deserializer &deserializer)
Definition serde.hpp:404
static float deserialize(Deserializer &deserializer)
Definition serde.hpp:396
static int128_t deserialize(Deserializer &deserializer)
Definition serde.hpp:492
static int16_t deserialize(Deserializer &deserializer)
Definition serde.hpp:468
static int32_t deserialize(Deserializer &deserializer)
Definition serde.hpp:476
static int64_t deserialize(Deserializer &deserializer)
Definition serde.hpp:484
static int8_t deserialize(Deserializer &deserializer)
Definition serde.hpp:460
static std::array< T, N > deserialize(Deserializer &deserializer)
Definition serde.hpp:564
static std::map< K, V > deserialize(Deserializer &deserializer)
Definition serde.hpp:536
static std::monostate deserialize(Deserializer &deserializer)
Definition serde.hpp:380
static std::optional< T > deserialize(Deserializer &deserializer)
Definition serde.hpp:510
static std::shared_ptr< Type > deserialize(Deserializer &serializer)
Definition serde.hpp:614
static std::string deserialize(Deserializer &deserializer)
Definition serde.hpp:372
static std::tuple< Types... > deserialize(Deserializer &deserializer)
Definition serde.hpp:576
static std::variant< Types... > deserialize(Deserializer &deserializer)
Definition serde.hpp:586
static std::vector< T > deserialize(Deserializer &deserializer)
Definition serde.hpp:523
static uint128_t deserialize(Deserializer &deserializer)
Definition serde.hpp:452
static uint16_t deserialize(Deserializer &deserializer)
Definition serde.hpp:428
static uint32_t deserialize(Deserializer &deserializer)
Definition serde.hpp:436
static uint64_t deserialize(Deserializer &deserializer)
Definition serde.hpp:444
static uint8_t deserialize(Deserializer &deserializer)
Definition serde.hpp:420
static value_ptr< T > deserialize(Deserializer &deserializer)
Definition serde.hpp:502
static T deserialize(Deserializer &deserializer)
static void serialize(const bool &value, Serializer &serializer)
Definition serde.hpp:161
static void serialize(const char32_t &value, Serializer &serializer)
Definition serde.hpp:169
static void serialize(const double &value, Serializer &serializer)
Definition serde.hpp:185
static void serialize(const float &value, Serializer &serializer)
Definition serde.hpp:177
static void serialize(const int128_t &value, Serializer &serializer)
Definition serde.hpp:265
static void serialize(const int16_t &value, Serializer &serializer)
Definition serde.hpp:241
static void serialize(const int32_t &value, Serializer &serializer)
Definition serde.hpp:249
static void serialize(const int64_t &value, Serializer &serializer)
Definition serde.hpp:257
static void serialize(const int8_t &value, Serializer &serializer)
Definition serde.hpp:233
static void serialize(const std::array< T, N > &value, Serializer &serializer)
Definition serde.hpp:307
static void serialize(const std::map< K, V, Allocator > &value, Serializer &serializer)
Definition serde.hpp:317
static void serialize(const std::monostate &, Serializer &serializer)
Definition serde.hpp:153
static void serialize(const std::optional< T > &option, Serializer &serializer)
Definition serde.hpp:283
static void serialize(const std::shared_ptr< Type > &value, Serializer &serializer)
Definition serde.hpp:362
static void serialize(const std::string &value, Serializer &serializer)
Definition serde.hpp:145
static void serialize(const std::tuple< Types... > &value, Serializer &serializer)
Definition serde.hpp:336
static void serialize(const std::variant< Types... > &value, Serializer &serializer)
Definition serde.hpp:346
static void serialize(const std::vector< T, Allocator > &value, Serializer &serializer)
Definition serde.hpp:296
static void serialize(const uint128_t &value, Serializer &serializer)
Definition serde.hpp:225
static void serialize(const uint16_t &value, Serializer &serializer)
Definition serde.hpp:201
static void serialize(const uint32_t &value, Serializer &serializer)
Definition serde.hpp:209
static void serialize(const uint64_t &value, Serializer &serializer)
Definition serde.hpp:217
static void serialize(const uint8_t &value, Serializer &serializer)
Definition serde.hpp:193
static void serialize(const value_ptr< T > &value, Serializer &serializer)
Definition serde.hpp:275
static void serialize(const T &value, Serializer &serializer)
friend bool operator==(const int128_t &, const int128_t &)
Definition serde.hpp:69
uint64_t low
Definition serde.hpp:64
int64_t high
Definition serde.hpp:63
uint64_t low
Definition serde.hpp:51
uint64_t high
Definition serde.hpp:50
friend bool operator==(const uint128_t &, const uint128_t &)
Definition serde.hpp:56
void throw_or_abort(std::string const &err)