Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
named_union.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <optional>
5#include <sstream>
6#include <stdexcept>
7#include <string>
8#include <string_view>
9#include <type_traits>
10#include <variant>
11
15#include "msgpack/object_fwd.hpp"
16
17namespace bb {
18
22template <typename T>
23concept HasMsgpackSchemaName = requires {
24 { T::MSGPACK_SCHEMA_NAME } -> std::convertible_to<std::string_view>;
25};
26
34template <HasMsgpackSchemaName... Types> class NamedUnion {
35 public:
37
38 private:
40
41 // Helper to get index from type name
42 template <size_t I = 0> static std::optional<size_t> get_index_from_name(std::string_view name)
43 {
44 if constexpr (I < sizeof...(Types)) {
46 if (name == CurrentType::MSGPACK_SCHEMA_NAME) {
47 return I;
48 }
49 return get_index_from_name<I + 1>(name);
50 }
51 return std::nullopt;
52 }
53
54 // Helper to construct variant by index
55 template <size_t I = 0> static VariantType construct_by_index(size_t index, auto& o)
56 {
57 if constexpr (I < sizeof...(Types)) {
58 if (I == index) {
61 o.convert(obj);
62 return obj;
63 }
65 }
66 throw_or_abort("Invalid variant index");
67 }
68
69 public:
70 NamedUnion() = default;
71
72 template <typename T>
74 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
77 {}
78
79 // Conversion operator to get the underlying variant
80 operator VariantType&() { return value_; }
81 operator const VariantType&() const { return value_; }
82
83 // Access the underlying variant
84 VariantType& get() { return value_; }
85 const VariantType& get() const { return value_; }
86
87 // Visit the variant
88 template <typename Visitor> decltype(auto) visit(Visitor&& vis) &&
89 {
90 return std::visit(std::forward<Visitor>(vis), std::move(value_));
91 }
92
93 template <typename Visitor> decltype(auto) visit(Visitor&& vis) const&
94 {
95 return std::visit(std::forward<Visitor>(vis), value_);
96 }
97
98 // Get the current type name
99 std::string_view get_type_name() const
100 {
101 return std::visit(
102 [](const auto& obj) -> std::string_view { return std::decay_t<decltype(obj)>::MSGPACK_SCHEMA_NAME; },
103 value_);
104 }
105
106 // Msgpack serialization
107 void msgpack_pack(auto& packer) const
108 {
109 packer.pack_array(2);
110 // First pack the type name
111 std::string_view type_name = get_type_name();
112 packer.pack(type_name);
113
114 // Then pack the actual object
115 std::visit([&packer](const auto& obj) { packer.pack(obj); }, value_);
116 }
117
118 // Msgpack deserialization
119 void msgpack_unpack(msgpack::object const& o)
120 {
121 constexpr size_t MAX_OUTPUT_CHARS = 100;
122 // access object assuming it is an array of size 2
123 if (o.type != msgpack::type::ARRAY || o.via.array.size != 2) {
124 throw_or_abort("Expected an array of size 2 for NamedUnion deserialization, got " +
126 }
127 const auto& arr = o.via.array;
128 if (arr.ptr[0].type != msgpack::type::STR) {
129 throw_or_abort("Expected first element to be a string (type name) in NamedUnion deserialization");
130 }
131 std::string_view type_name = std::string_view(arr.ptr[0].via.str.ptr, arr.ptr[0].via.str.size);
133 if (!index_opt.has_value()) {
134 throw_or_abort("Unknown type name in NamedUnion deserialization: " + std::string(type_name));
135 }
136 size_t index = index_opt.value();
137 // Now construct the variant using the index
139 }
140
141 // Msgpack schema
142 void msgpack_schema(auto& packer) const
143 {
144 packer.pack_array(2);
145 packer.pack("named_union");
146 packer.pack_array(sizeof...(Types));
147 (
148 [&packer]() {
149 packer.pack_array(2);
150 packer.pack(Types::MSGPACK_SCHEMA_NAME);
151 // Abitrary mutable object.
152 packer.pack_schema(*std::make_unique<Types>());
153 }(),
154 ...); /* pack schemas of all template Args */
155 }
156};
157
158// Deduction guide
159template <typename... Types> NamedUnion(std::variant<Types...>) -> NamedUnion<Types...>;
160
161} // namespace bb
A wrapper around std::variant that provides msgpack serialization based on type names.
decltype(auto) visit(Visitor &&vis) &&
VariantType value_
void msgpack_schema(auto &packer) const
void msgpack_unpack(msgpack::object const &o)
void msgpack_pack(auto &packer) const
const VariantType & get() const
VariantType & get()
static VariantType construct_by_index(size_t index, auto &o)
static std::optional< size_t > get_index_from_name(std::string_view name)
std::variant< Types... > VariantType
std::string_view get_type_name() const
decltype(auto) visit(Visitor &&vis) const &
NamedUnion()=default
Concept to check if a type has a static NAME member.
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
std::string msgpack_to_json(msgpack::object const &o, size_t max_chars)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
void throw_or_abort(std::string const &err)