barretenberg
Loading...
Searching...
No Matches
serde.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 "barretenberg/common/throw_or_abort.hpp"
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:
73 value_ptr()
74 : ptr_(nullptr)
75 {}
76
77 value_ptr(const T& value)
78 : ptr_(new T{ value })
79 {}
80
81 value_ptr(const value_ptr& other)
82 : ptr_(nullptr)
83 {
84 if (other) {
85 ptr_ = std::unique_ptr<T>{ new T{ *other } };
86 }
87 }
88
89 value_ptr& operator=(const value_ptr& other)
90 {
91 value_ptr temp{ other };
92 std::swap(ptr_, temp.ptr_);
93 return *this;
94 }
95
96 value_ptr(value_ptr&& other) = default;
97
98 value_ptr& operator=(value_ptr&& other) = default;
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:
115 std::unique_ptr<T> ptr_;
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// --- Implementation of Deserializable for base types ---
355
356// string
357template <> struct Deserializable<std::string> {
358 template <typename Deserializer> static std::string deserialize(Deserializer& deserializer)
359 {
360 return deserializer.deserialize_str();
361 }
362};
363
364// unit
365template <> struct Deserializable<std::monostate> {
366 template <typename Deserializer> static std::monostate deserialize(Deserializer& deserializer)
367 {
368 return deserializer.deserialize_unit();
369 }
370};
371
372// bool
373template <> struct Deserializable<bool> {
374 template <typename Deserializer> static bool deserialize(Deserializer& deserializer)
375 {
376 return deserializer.deserialize_bool();
377 }
378};
379
380// f32
381template <> struct Deserializable<float> {
382 template <typename Deserializer> static float deserialize(Deserializer& deserializer)
383 {
384 return deserializer.deserialize_f32();
385 }
386};
387
388// f64
389template <> struct Deserializable<double> {
390 template <typename Deserializer> static double deserialize(Deserializer& deserializer)
391 {
392 return deserializer.deserialize_f64();
393 }
394};
395
396// UTF-8 char
397template <> struct Deserializable<char32_t> {
398 template <typename Deserializer> static char32_t deserialize(Deserializer& deserializer)
399 {
400 return deserializer.deserialize_char();
401 }
402};
403
404// u8
405template <> struct Deserializable<uint8_t> {
406 template <typename Deserializer> static uint8_t deserialize(Deserializer& deserializer)
407 {
408 return deserializer.deserialize_u8();
409 }
410};
411
412// u16
413template <> struct Deserializable<uint16_t> {
414 template <typename Deserializer> static uint16_t deserialize(Deserializer& deserializer)
415 {
416 return deserializer.deserialize_u16();
417 }
418};
419
420// u32
421template <> struct Deserializable<uint32_t> {
422 template <typename Deserializer> static uint32_t deserialize(Deserializer& deserializer)
423 {
424 return deserializer.deserialize_u32();
425 }
426};
427
428// u64
429template <> struct Deserializable<uint64_t> {
430 template <typename Deserializer> static uint64_t deserialize(Deserializer& deserializer)
431 {
432 return deserializer.deserialize_u64();
433 }
434};
435
436// u128
437template <> struct Deserializable<uint128_t> {
438 template <typename Deserializer> static uint128_t deserialize(Deserializer& deserializer)
439 {
440 return deserializer.deserialize_u128();
441 }
442};
443
444// i8
445template <> struct Deserializable<int8_t> {
446 template <typename Deserializer> static int8_t deserialize(Deserializer& deserializer)
447 {
448 return deserializer.deserialize_i8();
449 }
450};
451
452// i16
453template <> struct Deserializable<int16_t> {
454 template <typename Deserializer> static int16_t deserialize(Deserializer& deserializer)
455 {
456 return deserializer.deserialize_i16();
457 }
458};
459
460// i32
461template <> struct Deserializable<int32_t> {
462 template <typename Deserializer> static int32_t deserialize(Deserializer& deserializer)
463 {
464 return deserializer.deserialize_i32();
465 }
466};
467
468// i64
469template <> struct Deserializable<int64_t> {
470 template <typename Deserializer> static int64_t deserialize(Deserializer& deserializer)
471 {
472 return deserializer.deserialize_i64();
473 }
474};
475
476// i128
477template <> struct Deserializable<int128_t> {
478 template <typename Deserializer> static int128_t deserialize(Deserializer& deserializer)
479 {
480 return deserializer.deserialize_i128();
481 }
482};
483
484// --- Derivation of Deserializable for composite types ---
485
486// Value pointers
487template <typename T> struct Deserializable<value_ptr<T>> {
488 template <typename Deserializer> static value_ptr<T> deserialize(Deserializer& deserializer)
489 {
490 return value_ptr<T>(Deserializable<T>::deserialize(deserializer));
491 }
492};
493
494// Options
495template <typename T> struct Deserializable<std::optional<T>> {
496 template <typename Deserializer> static std::optional<T> deserialize(Deserializer& deserializer)
497 {
498 auto tag = deserializer.deserialize_option_tag();
499 if (!tag) {
500 return {};
501 } else {
502 return { Deserializable<T>::deserialize(deserializer) };
503 }
504 }
505};
506
507// Vectors
508template <typename T, typename Allocator> struct Deserializable<std::vector<T, Allocator>> {
509 template <typename Deserializer> static std::vector<T> deserialize(Deserializer& deserializer)
510 {
511 std::vector<T> result;
512 size_t len = deserializer.deserialize_len();
513 for (size_t i = 0; i < len; i++) {
514 result.push_back(Deserializable<T>::deserialize(deserializer));
515 }
516 return result;
517 }
518};
519
520// Maps
521template <typename K, typename V> struct Deserializable<std::map<K, V>> {
522 template <typename Deserializer> static std::map<K, V> deserialize(Deserializer& deserializer)
523 {
524 std::map<K, V> result;
525 size_t len = deserializer.deserialize_len();
526 std::optional<std::tuple<size_t, size_t>> previous_key_slice;
527 for (size_t i = 0; i < len; i++) {
528 if constexpr (Deserializer::enforce_strict_map_ordering) {
529 auto start = deserializer.get_buffer_offset();
530 auto key = Deserializable<K>::deserialize(deserializer);
531 auto end = deserializer.get_buffer_offset();
532 if (previous_key_slice.has_value()) {
533 deserializer.check_that_key_slices_are_increasing(previous_key_slice.value(), { start, end });
534 }
535 previous_key_slice = { start, end };
536 auto value = Deserializable<V>::deserialize(deserializer);
537 result.insert({ key, value });
538 } else {
539 auto key = Deserializable<K>::deserialize(deserializer);
540 auto value = Deserializable<V>::deserialize(deserializer);
541 result.insert({ key, value });
542 }
543 }
544 return result;
545 }
546};
547
548// Fixed-size arrays
549template <typename T, std::size_t N> struct Deserializable<std::array<T, N>> {
550 template <typename Deserializer> static std::array<T, N> deserialize(Deserializer& deserializer)
551 {
552 std::array<T, N> result;
553 for (T& item : result) {
554 item = Deserializable<T>::deserialize(deserializer);
555 }
556 return result;
557 }
558};
559
560// Tuples
561template <class... Types> struct Deserializable<std::tuple<Types...>> {
562 template <typename Deserializer> static std::tuple<Types...> deserialize(Deserializer& deserializer)
563 {
564 // Visit each of the type components. We use the constructor of `std::tuple` so
565 // that the evaluation order of arguments is specified by the C++ standard.
566 return std::tuple<Types...>{ Deserializable<Types>::deserialize(deserializer)... };
567 }
568};
569
570// Enums
571template <class... Types> struct Deserializable<std::variant<Types...>> {
572 template <typename Deserializer> static std::variant<Types...> deserialize(Deserializer& deserializer)
573 {
574 // A "case" is analog to a particular branch in switch-case over the
575 // index. Given the variant type `T` known statically, we create a
576 // closure that will deserialize a value `T` and return it as a variant.
577 using Case = std::function<std::variant<Types...>(Deserializer&)>;
578 auto make_case = [](auto tag) -> Case {
579 // Obtain the type `T` encoded in the type of `tag ==
580 // std::common_type<T>{}`.
581 using T = typename decltype(tag)::type;
582 auto f = [](Deserializer& de) { return std::variant<Types...>(Deserializable<T>::deserialize(de)); };
583 return f;
584 };
585
586 // The static array of all the cases for this variant.
587 static const std::array<Case, sizeof...(Types)> cases = { make_case(std::common_type<Types>{})... };
588
589 // Read the variant index and execute the corresponding case.
590 auto index = deserializer.deserialize_variant_index();
591 if (index > cases.size()) {
592 throw_or_abort("Unknown variant index for enum");
593 }
594 return cases.at(index)(deserializer);
595 }
596};
597
598} // end of namespace serde
Definition: serde.hpp:32
Definition: serde.hpp:22
Definition: serde.hpp:71
Definition: serde.hpp:131
Definition: serde.hpp:125
Definition: serde.hpp:56
Definition: serde.hpp:43