Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
schema_impl.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "schema_name.hpp"
4#include <array>
5#include <concepts>
6#include <memory>
7#include <string>
8
10
11// Forward declare for MsgpackSchemaPacker
12template <typename T> inline void _msgpack_schema_pack(MsgpackSchemaPacker& packer, const T& obj);
13
18struct MsgpackSchemaPacker : msgpack::packer<msgpack::sbuffer> {
19 MsgpackSchemaPacker(msgpack::sbuffer& stream)
20 : packer<msgpack::sbuffer>(stream)
21 {}
22 // For tracking emitted types
23 std::set<std::string> emitted_types;
24 // Returns if already was emitted
25 bool set_emitted(const std::string& type) { return !emitted_types.insert(type).second; }
26
33 void pack_alias(const std::string& schema_name, const std::string& msgpack_name)
34 {
35 // We will pack a size 2 tuple
36 pack_array(2);
37 pack("alias");
38 // That has a size 2 tuple as its 2nd arg
39 pack_array(2);
40 pack(schema_name);
41 pack(msgpack_name);
42 }
43
49 template <typename T> void pack_schema(const T& obj) { _msgpack_schema_pack(*this, obj); }
50
51 // Recurse over any templated containers
52 // Outputs e.g. ['vector', ['sub-type']]
53 template <typename... Args> void pack_template_type(const std::string& schema_name)
54 {
55 // We will pack a size 2 tuple
56 pack_array(2);
57 pack(schema_name);
58 pack_array(sizeof...(Args));
59
60 // Note: if this fails to compile, check first in list of template Arg's
61 // it may need a msgpack_schema_pack specialization (particularly if it doesn't define SERIALIZATION_FIELDS).
62 (_msgpack_schema_pack(*this, *std::make_unique<Args>()), ...); /* pack schemas of all template Args */
63 }
71 template <msgpack_concepts::HasMsgPack T> void pack_with_name(const std::string& type, T const& object)
72 {
73 if (set_emitted(type)) {
74 pack(type);
75 return; // already emitted
76 }
78 // Encode as map
79 const_cast<T&>(object).msgpack([&](auto&... args) {
80 size_t kv_size = sizeof...(args);
81 // Calculate the number of entries in our map (half the size of keys + values, plus the typename)
82 pack_map(uint32_t(1 + kv_size / 2));
83 pack("__typename");
84 pack(type);
85 // Pack the map content based on the args to msgpack
86 _schema_pack_map_content(*this, args...);
87 });
88 }
89};
90
91// Helper for packing (key, value, key, value, ...) arguments
93{
94 // base case
95}
96
97namespace msgpack_concepts {
98template <typename T>
99concept SchemaPackable = requires(T value, MsgpackSchemaPacker packer) { msgpack_schema_pack(packer, value); };
100} // namespace msgpack_concepts
101
102// Helper for packing (key, value, key, value, ...) arguments
103template <typename Value, typename... Rest>
105 const std::string& key,
106 const Value& value,
107 const Rest&... rest)
108{
109 static_assert(
111 "see the first type argument in the error trace, it might require a specialization of msgpack_schema_pack");
112 packer.pack(key);
113 msgpack_schema_pack(packer, value);
114 _schema_pack_map_content(packer, rest...);
115}
116
117template <typename T>
119inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, T const& obj)
120{
121 packer.pack(msgpack_schema_name(obj));
122}
123
129template <msgpack_concepts::HasMsgPackSchema T>
130inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, T const& obj)
131{
132 obj.msgpack_schema(packer);
133}
134
142template <msgpack_concepts::HasMsgPack T>
144inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, T const& object)
145{
146 std::string type = msgpack_schema_name(object);
147 packer.pack_with_name(type, object);
148}
149
153template <typename T> inline void _msgpack_schema_pack(MsgpackSchemaPacker& packer, const T& obj)
154{
156 "see the first type argument in the error trace, it might need a msgpack_schema method!");
157 msgpack_schema_pack(packer, obj);
158}
159
160template <typename... Args> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::tuple<Args...> const&)
161{
162 packer.pack_template_type<Args...>("tuple");
163}
164
165template <typename K, typename V> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::map<K, V> const&)
166{
167 packer.pack_template_type<K, V>("map");
168}
169
170template <typename T> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::optional<T> const&)
171{
172 packer.pack_template_type<T>("optional");
173}
174
175template <typename T> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::vector<T> const&)
176{
177 packer.pack_template_type<T>("vector");
178}
179
180template <typename... Args> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::variant<Args...> const&)
181{
182 packer.pack_template_type<Args...>("variant");
183}
184
185template <typename T> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::shared_ptr<T> const&)
186{
187 packer.pack_template_type<T>("shared_ptr");
188}
189
190// Outputs e.g. ['array', ['array-type', 'N']]
191template <typename T, std::size_t N>
193{
194 // We will pack a size 2 tuple
195 packer.pack_array(2);
196 packer.pack("array");
197 // That has a size 2 tuple as its 2nd arg
198 packer.pack_array(2); /* param list format for consistency*/
199 // To avoid WASM problems with large stack objects, we use a heap allocation.
200 // Small note: This works because make_unique goes of scope only when the whole line is done.
202 packer.pack(N);
203}
204
211inline std::string msgpack_schema_to_string(const auto& obj)
212{
213 msgpack::sbuffer output;
214 MsgpackSchemaPacker printer{ output };
215 _msgpack_schema_pack(printer, obj);
216 msgpack::object_handle oh = msgpack::unpack(output.data(), output.size());
217 std::stringstream pretty_output;
218 pretty_output << oh.get() << std::endl;
219 return pretty_output.str();
220}
constexpr size_t N
void check_msgpack_usage(const auto &object)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
void _msgpack_schema_pack(MsgpackSchemaPacker &packer, const T &obj)
Helper method for better error reporting. Clang does not give the best errors for argument lists.
void msgpack_schema_pack(MsgpackSchemaPacker &packer, T const &obj)
void _schema_pack_map_content(MsgpackSchemaPacker &)
std::string msgpack_schema_to_string(const auto &obj)
Print's an object's derived msgpack schema as a string.
std::string msgpack_schema_name(T const &)
void pack_alias(const std::string &schema_name, const std::string &msgpack_name)
bool set_emitted(const std::string &type)
void pack_with_name(const std::string &type, T const &object)
Encode a type that defines msgpack based on its key value pairs.
MsgpackSchemaPacker(msgpack::sbuffer &stream)
std::set< std::string > emitted_types
void pack_template_type(const std::string &schema_name)
void pack_schema(const T &obj)