24class EndianBufferWriter {
32 EndianBufferWriter &operator <<(
const std::string &data) {
return *
this << std::string_view{ data }; }
33 EndianBufferWriter &operator <<(
const EncodedString &data) {
return *
this << data.
string; }
34 EndianBufferWriter &operator <<(std::string_view data) { this->
Write(data);
return *
this; }
35 EndianBufferWriter &operator <<(
bool data) {
return *this << static_cast<uint8_t>(data ? 1 : 0); }
37 template <
typename... Targs>
38 EndianBufferWriter &operator <<(
const std::tuple<Targs...> &data)
40 this->
WriteTuple(data, std::index_sequence_for<Targs...>{});
44 template <
typename... Targs>
45 EndianBufferWriter &operator <<(
const std::variant<Targs...> &variant)
47 this->WriteVariant(variant);
51 EndianBufferWriter &operator <<(
const std::monostate &)
56 EndianBufferWriter &operator <<(
const ConvertibleThroughBase
auto data)
58 this->
Write(data.base());
62 template <
class T>
requires (!std::is_class_v<T>)
63 EndianBufferWriter &
operator <<(
const T data)
65 if constexpr (std::is_enum_v<T>) {
73 template <
typename Tvalue,
typename Tbuf = std::vector<u
int8_t>>
74 static Tbuf FromValue(
const Tvalue &data)
77 EndianBufferWriter writer{
buffer };
87 template <
class Ttuple,
size_t... Tindices>
88 void WriteTuple(
const Ttuple &values, std::index_sequence<Tindices...>)
90 ((*this << std::get<Tindices>(values)), ...);
93 template <
typename T, std::
size_t I = 0>
94 void WriteVariant(
const T &variant )
96 if constexpr (I < std::variant_size_v<T>) {
97 if (I == variant.index()) {
98 static_assert(std::variant_size_v<T> < std::numeric_limits<uint8_t>::max());
99 this->
Write(
static_cast<uint8_t
>(variant.index()));
100 *this << std::get<I>(variant);
104 WriteVariant<T, I + 1>(variant);
114 for (
auto c : value) {
117 this->buffer++ =
'\0';
127 static_assert(
sizeof(T) <= 8,
"Value can't be larger than 8 bytes");
129 if constexpr (
sizeof(T) > 1) {
130 this->buffer++ =
GB(value, 0, 8);
131 this->buffer++ =
GB(value, 8, 8);
132 if constexpr (
sizeof(T) > 2) {
133 this->buffer++ =
GB(value, 16, 8);
134 this->buffer++ =
GB(value, 24, 8);
136 if constexpr (
sizeof(T) > 4) {
137 this->buffer++ =
GB(value, 32, 8);
138 this->buffer++ =
GB(value, 40, 8);
139 this->buffer++ =
GB(value, 48, 8);
140 this->buffer++ =
GB(value, 56, 8);
143 this->buffer++ = value;
154class EndianBufferReader {
163 void rewind() { this->read_pos = 0; }
165 EndianBufferReader &operator >>(std::string &data) { data = this->
ReadStr();
return *
this; }
166 EndianBufferReader &operator >>(EncodedString &data) { data = EncodedString{this->
ReadStr()};
return *
this; }
167 EndianBufferReader &operator >>(
bool &data) { data = this->
Read<uint8_t>() != 0;
return *
this; }
169 template <
typename... Targs>
170 EndianBufferReader &operator >>(std::tuple<Targs...> &data)
172 this->
ReadTuple(data, std::index_sequence_for<Targs...>{});
176 template <
typename... Targs>
177 EndianBufferReader &operator >>(std::variant<Targs...> &variant)
183 EndianBufferReader &operator >>(
const std::monostate &)
188 template <ConvertibleThroughBase T>
189 EndianBufferReader &operator >>(T &data)
195 template <
class T>
requires (!std::is_class_v<T>)
196 EndianBufferReader &
operator >>(T &data)
198 if constexpr (std::is_enum_v<T>) {
206 template <
typename Tvalue>
207 static Tvalue ToValue(std::span<const uint8_t>
buffer)
210 EndianBufferReader reader{
buffer };
220 template <
class Ttuple,
size_t... Tindices>
221 void ReadTuple(Ttuple &values, std::index_sequence<Tindices...>)
223 ((*
this >> std::get<Tindices>(values)), ...);
226 template <
typename T, std::
size_t I = 0>
227 void ReadVariant(uint8_t index, T &variant)
229 if constexpr (I < std::variant_size_v<T>) {
231 ReadVariant<T, I + 1>(index, variant);
235 std::variant_alternative_t<I, T> data;
250 if (ch ==
'\0')
break;
263 static_assert(!std::is_const_v<T>,
"Can't read into const variables");
264 static_assert(
sizeof(T) <= 8,
"Value can't be larger than 8 bytes");
266 if (
read_pos +
sizeof(T) > this->buffer.size())
return {};
268 T value =
static_cast<T
>(this->buffer[this->read_pos++]);
269 if constexpr (
sizeof(T) > 1) {
270 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 8;
272 if constexpr (
sizeof(T) > 2) {
273 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 16;
274 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 24;
276 if constexpr (
sizeof(T) > 4) {
277 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 32;
278 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 40;
279 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 48;
280 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 56;
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.