17[[nodiscard]]
constexpr size_t padded_size(
size_t len)
noexcept
19 return (len + 3) & ~size_t(3);
37 const uint8_t* data,
size_t max_len,
size_t& offset)
39 if (offset >= max_len) {
42 const auto* start =
reinterpret_cast<const char*
>(data + offset);
43 size_t len = strnlen(start, max_len - offset);
44 std::string result(start, len);
57[[nodiscard]]
inline int32_t
read_int32(
const uint8_t* data,
size_t& offset)
60 std::memcpy(&val, data + offset, 4);
62 if constexpr (std::endian::native == std::endian::little) {
63 val =
static_cast<int32_t
>(std::byteswap(
static_cast<uint32_t
>(val)));
76[[nodiscard]]
inline float read_float(
const uint8_t* data,
size_t& offset)
79 std::memcpy(&raw, data + offset, 4);
81 if constexpr (std::endian::native == std::endian::little) {
82 raw = std::byteswap(raw);
85 std::memcpy(&val, &raw, 4);
100 const uint8_t* data,
size_t max_len,
size_t& offset)
104 || offset +
static_cast<size_t>(blob_size) > max_len) {
107 std::vector<uint8_t> result(
108 data + offset, data + offset + blob_size);
109 offset +=
padded_size(
static_cast<size_t>(blob_size));
125inline void write_string(std::vector<uint8_t>& out,
const std::string& str)
127 out.insert(out.end(), str.begin(), str.end());
129 out.resize(out.size() + (padded - str.size()), 0);
140 auto raw =
static_cast<uint32_t
>(val);
141 if constexpr (std::endian::native == std::endian::little) {
142 raw = std::byteswap(raw);
144 const auto* bytes =
reinterpret_cast<const uint8_t*
>(&raw);
145 out.insert(out.end(), bytes, bytes + 4);
157 std::memcpy(&raw, &val, 4);
158 if constexpr (std::endian::native == std::endian::little) {
159 raw = std::byteswap(raw);
161 const auto* bytes =
reinterpret_cast<const uint8_t*
>(&raw);
162 out.insert(out.end(), bytes, bytes + 4);
174 std::vector<uint8_t>& out,
const std::vector<uint8_t>& blob)
176 write_int32(out,
static_cast<int32_t
>(blob.size()));
177 out.insert(out.end(), blob.begin(), blob.end());
179 out.resize(out.size() + (padded - blob.size()), 0);
void write_int32(std::vector< uint8_t > &out, int32_t val)
Append a big-endian int32.
void write_blob(std::vector< uint8_t > &out, const std::vector< uint8_t > &blob)
Append a length-prefixed blob padded to 4-byte boundary.
std::vector< uint8_t > read_blob(const uint8_t *data, size_t max_len, size_t &offset)
Read a length-prefixed blob from a byte buffer.
int32_t read_int32(const uint8_t *data, size_t &offset)
Read a big-endian int32 from a byte buffer.
void write_string(std::vector< uint8_t > &out, const std::string &str)
Append a null-terminated string padded to 4-byte boundary.
std::string read_string(const uint8_t *data, size_t max_len, size_t &offset)
Read a null-terminated string from a byte buffer.
constexpr size_t padded_size(size_t len) noexcept
Round len up to the next 4-byte boundary.
float read_float(const uint8_t *data, size_t &offset)
Read a big-endian IEEE 754 float from a byte buffer.
void write_float(std::vector< uint8_t > &out, float val)
Append a big-endian IEEE 754 float.