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