31export using bytes = std::vector<std::uint8_t>;
34using variant_tag = std::conditional_t<(
sizeof...(Ts) <= 256), std::uint8_t, std::uint32_t>;
46 template<std::
unsigned_
integral T>
48 if constexpr (std::same_as<T, bool>) {
49 data.push_back(value ? 1 : 0);
51 for (std::size_t i = 0; i <
sizeof(T); ++i)
52 data.push_back(
static_cast<std::uint8_t
>(value >> (i * 8)));
59 template<
class T, std::
size_t N>
60 void field(
const std::array<T, N>& value) {
61 for (
const auto& x : value)
field(x);
70 void field(
const std::variant<Ts...>& value) {
71 if (value.valueless_by_exception())
throw auth_error(
"valueless variant");
72 field(
static_cast<variant_tag<Ts...
>>(value.index()));
73 std::visit([
this](
const auto& x) { this->
field(x); }, value);
81 void field(
const std::unique_ptr<T>& value) {
82 if (!value)
throw auth_error(
"null boxed value");
90 template<
class T>
requires requires(
const T& v,
writer& s) { v.serialize(s); }
91 void field(
const T& value) { value.serialize(*
this); }
107 std::span<const std::uint8_t>
data;
114 template<std::
unsigned_
integral T>
116 constexpr auto width = std::same_as<T, bool> ? 1 :
sizeof(T);
118 if constexpr (std::same_as<T, bool>) {
120 if (
byte > 1)
throw auth_error(
"invalid boolean");
124 for (std::size_t i = 0; i <
sizeof(T); ++i)
132 template<
class T, std::
size_t N>
133 void field(std::array<T, N>& value) {
134 for (
auto& x : value)
field(x);
141 template<
class... Ts>
142 void field(std::variant<Ts...>& value) {
143 variant_tag<Ts...> tag;
145 if (tag >=
sizeof...(Ts))
throw auth_error(
"invalid variant index");
146 alternative(value, tag);
153 void field(std::unique_ptr<T>& value) {
154 auto decoded = std::make_unique<T>();
156 value = std::move(decoded);
163 template<
class T>
requires requires(T& v,
reader& s) { v.serialize(s); }
164 void field(T& value) { value.serialize(*
this); }
169 template<
class... Ts>
173 template<std::size_t I = 0,
class... Ts>
174 void alternative(std::variant<Ts...>& value, std::size_t tag) {
175 if (tag == I)
field(value.template emplace<I>());
176 else if constexpr (I + 1 <
sizeof...(Ts)) alternative<I + 1>(value, tag);
185export template<
class T>
189 return std::move(stream.
data);
201export template<
class T>
202std::pair<T, const std::uint8_t*>
decode(std::span<const std::uint8_t> data) {
206 return {std::move(value), data.subspan(stream.
position).data()};
bytes encode(const T &value)
Serializes a value to an owned byte buffer.
std::vector< std::uint8_t > bytes
An owned buffer of serialized bytes.
std::pair< T, const std::uint8_t * > decode(std::span< const std::uint8_t > data)
Decodes one value, leaving subsequent bytes for the caller.
Reports malformed input, invalid proofs, or hashing failures.
Reads checked fields from borrowed bytes, advancing a byte offset.
void field(std::variant< Ts... > &value)
Reads a variant's index and constructs and fills its selected alternative.
void field(std::array< T, N > &value)
Reads each array element in order; no length prefix is consumed.
static constexpr bool reading
Selects the reading path in serializers.
void field(std::unique_ptr< T > &value)
Allocates and reads a boxed value, replacing the pointer on success.
void operator()(Ts &... values)
Reads fields from left to right using the matching field overloads.
void field(T &value)
Reads a little-endian unsigned integer, or a one-byte boolean.
std::size_t position
Offset of the next unread byte.
std::span< const std::uint8_t > data
Borrowed input bytes.
void field(T &value)
Invokes a custom type's serialize method through a mutable reference.
Appends deterministic, byte-aligned fields to an owned buffer.
void field(const std::variant< Ts... > &value)
Writes a variant's alternative index and active value.
void operator()(const Ts &... values)
Writes fields from left to right using the matching field overloads.
void field(const std::array< T, N > &value)
Writes each array element in order, without a length prefix.
bytes data
Serialized output in field order.
static constexpr bool reading
Selects the writing path in serializers.
void field(const std::unique_ptr< T > &value)
Writes a boxed value without pointer or presence bytes.
void field(const T &value)
Invokes a custom type's serialize method through a const reference.
void field(T value)
Writes an unsigned integer in little-endian order.