Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
tagged_value.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <functional>
5#include <ostream>
6#include <string>
7#include <variant>
8
13
14namespace bb::avm2 {
15
16class TaggedValueException : public std::runtime_error {
17 public:
18 using std::runtime_error::runtime_error; // Inherit the constructor.
19};
20
22 public:
23 TagMismatchException(const std::string& msg)
24 : TaggedValueException("Mismatched tags: " + msg)
25 {}
26};
27
29 public:
30 InvalidOperationTag(const std::string& msg)
31 : TaggedValueException("InvalidOperationTag: " + msg)
32 {}
33};
34
36 public:
37 DivisionByZero(const std::string& msg)
38 : TaggedValueException("Division by zero: " + msg)
39 {}
40};
41
43 public:
44 ValueOutOfBounds(const std::string& msg)
45 : TaggedValueException("Value out of bounds: " + msg)
46 {}
47};
48
50 public:
51 CastException(const std::string& msg)
52 : TaggedValueException("CastException: " + msg)
53 {}
54};
55
56enum class ValueTag {
57 FF = MEM_TAG_FF,
58 U1 = MEM_TAG_U1,
59 U8 = MEM_TAG_U8,
64 MAX = U128,
65};
66
67inline std::ostream& operator<<(std::ostream& os, ValueTag tag)
68{
69 switch (tag) {
70 case ValueTag::FF:
71 return os << "FF";
72 case ValueTag::U1:
73 return os << "U1";
74 case ValueTag::U8:
75 return os << "U8";
76 case ValueTag::U16:
77 return os << "U16";
78 case ValueTag::U32:
79 return os << "U32";
80 case ValueTag::U64:
81 return os << "U64";
82 case ValueTag::U128:
83 return os << "U128";
84 default:
85 return os << "Unknown";
86 }
87
88 __builtin_unreachable();
89}
90
91template <typename T> ValueTag tag_for_type()
92{
93 if constexpr (std::is_same_v<T, FF>) {
94 return ValueTag::FF;
95 } else if constexpr (std::is_same_v<T, uint1_t>) {
96 return ValueTag::U1;
97 } else if constexpr (std::is_same_v<T, uint8_t>) {
98 return ValueTag::U8;
99 } else if constexpr (std::is_same_v<T, uint16_t>) {
100 return ValueTag::U16;
101 } else if constexpr (std::is_same_v<T, uint32_t>) {
102 return ValueTag::U32;
103 } else if constexpr (std::is_same_v<T, uint64_t>) {
104 return ValueTag::U64;
105 } else if constexpr (std::is_same_v<T, uint128_t>) {
106 return ValueTag::U128;
107 }
108}
109
110uint8_t get_tag_bits(ValueTag tag);
111uint8_t get_tag_bytes(ValueTag tag);
113
115 public:
116 // We are using variant to avoid heap allocations at the cost of a bigger memory footprint.
117 // Do not use this type outside of this class, except for the visitors.
118 // NOTE: Order matters, "a default-constructed variant holds a value of its first alternative".
119 // See https://en.cppreference.com/w/cpp/utility/variant.
121
122 // Default constructor. Useful for events. Note that this will be an U8.
123 TaggedValue() = default;
124
125 // Using this constructor you can specify the type explicitly via the template.
126 template <typename T> static TaggedValue from(T value) { return TaggedValue(value); }
127 // Constructs from a tag and value. Throws if the value is out of bounds for the tag.
129 // Constructs from a tag and value. Truncates the value if it is out of bounds for the tag.
130 // The truncation is equivalent to bit masking. It does not saturate to the max value of the tag.
132
133 // Arithmetic operators.
134 TaggedValue operator+(const TaggedValue& other) const;
135 TaggedValue operator-(const TaggedValue& other) const;
136 TaggedValue operator*(const TaggedValue& other) const;
137 TaggedValue operator/(const TaggedValue& other) const;
138 // Bitwise operations not valid for FF. They will throw.
139 TaggedValue operator&(const TaggedValue& other) const;
140 TaggedValue operator|(const TaggedValue& other) const;
141 TaggedValue operator^(const TaggedValue& other) const;
142 TaggedValue operator~() const;
143 // Shift operations not valid for FF. They will throw.
144 TaggedValue operator<<(const TaggedValue& other) const;
145 TaggedValue operator>>(const TaggedValue& other) const;
146 // Comparison operators. If the tags are not the same, false is returned
147 bool operator<(const TaggedValue& other) const;
148 bool operator>(const TaggedValue& other) const;
149 bool operator<=(const TaggedValue& other) const;
150 bool operator==(const TaggedValue& other) const;
151 bool operator!=(const TaggedValue& other) const;
152
153 // Converts any type to FF.
154 FF as_ff() const;
155 operator FF() const { return as_ff(); }
156 ValueTag get_tag() const;
157 std::string to_string() const;
158
159 // Use sparingly. The held type must match.
160 template <typename T> T as() const
161 {
163 return std::get<T>(value);
164 }
165 throw CastException("TaggedValue::as(): type mismatch. Wanted type " +
166 std::to_string(static_cast<uint32_t>(tag_for_type<T>())) + " but got " + to_string());
167 }
168
169 // This method try to do the smallest conversion possible.
170 // In particular, it tries to avoid going through FF.
171 // Note: truncation will happen if the value is out of bounds for the target type.
172 template <typename T> T to() const
173 {
174 switch (get_tag()) {
175 case ValueTag::U8:
176 return static_cast<T>(std::get<uint8_t>(value));
177 case ValueTag::U16:
178 return static_cast<T>(std::get<uint16_t>(value));
179 case ValueTag::U32:
180 return static_cast<T>(std::get<uint32_t>(value));
181 case ValueTag::U64:
182 return static_cast<T>(std::get<uint64_t>(value));
183 case ValueTag::U128:
184 return static_cast<T>(std::get<uint128_t>(value));
185 case ValueTag::U1:
186 return static_cast<T>(std::get<uint1_t>(value));
187 case ValueTag::FF:
188 return static_cast<T>(std::get<FF>(value));
189 }
190
191 __builtin_unreachable();
192 }
193
194 std::size_t hash() const noexcept { return std::hash<FF>{}(as_ff()); }
195
196 private:
199};
200
201} // namespace bb::avm2
202
203namespace std {
204
205std::string to_string(bb::avm2::ValueTag tag);
206std::string to_string(const bb::avm2::TaggedValue& val);
207
208} // namespace std
#define MEM_TAG_U1
#define MEM_TAG_U32
#define MEM_TAG_U16
#define MEM_TAG_U8
#define MEM_TAG_U128
#define MEM_TAG_FF
#define MEM_TAG_U64
CastException(const std::string &msg)
DivisionByZero(const std::string &msg)
InvalidOperationTag(const std::string &msg)
TagMismatchException(const std::string &msg)
TaggedValue operator>>(const TaggedValue &other) const
TaggedValue operator+(const TaggedValue &other) const
bool operator<=(const TaggedValue &other) const
static TaggedValue from(T value)
TaggedValue operator~() const
std::variant< uint8_t, uint1_t, uint16_t, uint32_t, uint64_t, uint128_t, FF > value_type
bool operator>(const TaggedValue &other) const
TaggedValue operator/(const TaggedValue &other) const
std::size_t hash() const noexcept
static TaggedValue from_tag_truncating(ValueTag tag, FF value)
TaggedValue operator-(const TaggedValue &other) const
bool operator<(const TaggedValue &other) const
TaggedValue operator<<(const TaggedValue &other) const
bool operator==(const TaggedValue &other) const
TaggedValue operator|(const TaggedValue &other) const
static TaggedValue from_tag(ValueTag tag, FF value)
TaggedValue operator^(const TaggedValue &other) const
TaggedValue operator*(const TaggedValue &other) const
TaggedValue operator&(const TaggedValue &other) const
ValueTag get_tag() const
std::string to_string() const
bool operator!=(const TaggedValue &other) const
ValueOutOfBounds(const std::string &msg)
std::ostream & operator<<(std::ostream &os, const CoarseTransactionPhase &phase)
Definition avm_io.hpp:488
uint8_t get_tag_bits(ValueTag tag)
ValueTag tag_for_type()
uint256_t get_tag_max_value(ValueTag tag)
AvmFlavorSettings::FF FF
Definition field.hpp:10
uint8_t get_tag_bytes(ValueTag tag)
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)