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)
26 {
27 if (emitted_types.find(type) == emitted_types.end()) {
28 emitted_types.insert(type);
29 return false;
30 }
31 return true;
32 }
33
40 void pack_alias(const std::string& schema_name, const std::string& msgpack_name)
41 {
42 // We will pack a size 2 tuple
43 pack_array(2);
44 pack("alias");
45 // That has a size 2 tuple as its 2nd arg
46 pack_array(2);
47 pack(schema_name);
48 pack(msgpack_name);
49 }
50
56 template <typename T> void pack_schema(const T& obj) { _msgpack_schema_pack(*this, obj); }
57
58 // Recurse over any templated containers
59 // Outputs e.g. ['vector', ['sub-type']]
60 template <typename... Args> void pack_template_type(const std::string& schema_name)
61 {
62 // We will pack a size 2 tuple
63 pack_array(2);
64 pack(schema_name);
65 pack_array(sizeof...(Args));
66
67 // Note: if this fails to compile, check first in list of template Arg's
68 // it may need a msgpack_schema_pack specialization (particularly if it doesn't define MSGPACK_FIELDS).
69 (_msgpack_schema_pack(*this, *std::make_unique<Args>()), ...); /* pack schemas of all template Args */
70 }
78 template <msgpack_concepts::HasMsgPack T> void pack_with_name(const std::string& type, T const& object)
79 {
80 if (set_emitted(type)) {
81 pack(type);
82 return; // already emitted
83 }
85 // Encode as map
86 const_cast<T&>(object).msgpack([&](auto&... args) {
87 size_t kv_size = sizeof...(args);
88 // Calculate the number of entries in our map (half the size of keys + values, plus the typename)
89 pack_map(uint32_t(1 + kv_size / 2));
90 pack("__typename");
91 pack(type);
92 // Pack the map content based on the args to msgpack
93 _schema_pack_map_content(*this, args...);
94 });
95 }
96};
97
98// Helper for packing (key, value, key, value, ...) arguments
100{
101 // base case
102}
103
104namespace msgpack_concepts {
105template <typename T>
106concept SchemaPackable = requires(T value, MsgpackSchemaPacker packer) { msgpack_schema_pack(packer, value); };
107} // namespace msgpack_concepts
108
109// Helper for packing (key, value, key, value, ...) arguments
110template <typename Value, typename... Rest>
112 std::string key,
113 const Value& value,
114 const Rest&... rest)
115{
116 static_assert(
118 "see the first type argument in the error trace, it might require a specialization of msgpack_schema_pack");
119 packer.pack(key);
120 msgpack_schema_pack(packer, value);
121 _schema_pack_map_content(packer, rest...);
122}
123
124template <typename T>
126inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, T const& obj)
127{
128 packer.pack(msgpack_schema_name(obj));
129}
130
136template <msgpack_concepts::HasMsgPackSchema T>
137inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, T const& obj)
138{
139 obj.msgpack_schema(packer);
140}
141
149template <msgpack_concepts::HasMsgPack T>
151inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, T const& object)
152{
153 std::string type = msgpack_schema_name(object);
154 packer.pack_with_name(type, object);
155}
156
160template <typename T> inline void _msgpack_schema_pack(MsgpackSchemaPacker& packer, const T& obj)
161{
163 "see the first type argument in the error trace, it might need a msgpack_schema method!");
164 msgpack_schema_pack(packer, obj);
165}
166
167template <typename... Args> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::tuple<Args...> const&)
168{
169 packer.pack_template_type<Args...>("tuple");
170}
171
172template <typename K, typename V> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::map<K, V> const&)
173{
174 packer.pack_template_type<K, V>("map");
175}
176
177template <typename T> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::optional<T> const&)
178{
179 packer.pack_template_type<T>("optional");
180}
181
182template <typename T> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::vector<T> const&)
183{
184 packer.pack_template_type<T>("vector");
185}
186
187template <typename... Args> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::variant<Args...> const&)
188{
189 packer.pack_template_type<Args...>("variant");
190}
191
192template <typename T> inline void msgpack_schema_pack(MsgpackSchemaPacker& packer, std::shared_ptr<T> const&)
193{
194 packer.pack_template_type<T>("shared_ptr");
195}
196
197// Outputs e.g. ['array', ['array-type', 'N']]
198template <typename T, std::size_t N>
200{
201 // We will pack a size 2 tuple
202 packer.pack_array(2);
203 packer.pack("array");
204 // That has a size 2 tuple as its 2nd arg
205 packer.pack_array(2); /* param list format for consistency*/
206 // To avoid WASM problems with large stack objects, we use a heap allocation.
207 // Small note: This works because make_unique goes of scope only when the whole line is done.
209 packer.pack(N);
210}
211
218inline std::string msgpack_schema_to_string(const auto& obj)
219{
220 msgpack::sbuffer output;
221 MsgpackSchemaPacker printer{ output };
222 _msgpack_schema_pack(printer, obj);
223 msgpack::object_handle oh = msgpack::unpack(output.data(), output.size());
224 std::stringstream pretty_output;
225 pretty_output << oh.get() << std::endl;
226 return pretty_output.str();
227}
std::string msgpack_schema_name(bb::g1::affine_element const &)
Definition g1.hpp:39
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.
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)