mal-packet-weaver
C++20 packet serialization/deserialization library.
Loading...
Searching...
No Matches
byte-helper.hpp
Go to the documentation of this file.
1#pragma once
2#include "library-pch.hpp"
3
4#if __has_include(<boost/version.hpp>)
5#include <boost/version.hpp>
6#endif
7#ifdef BOOST_VERSION
8#include <boost/endian/conversion.hpp>
9#include <boost/serialization/base_object.hpp>
10#include <boost/serialization/serialization.hpp>
11#include <boost/serialization/vector.hpp>
12
13#else
14#pragma message "Boost wasn't found. Serialization for ByteArray is unavailable."
15#endif
16
17namespace mal_toolkit
18{
19 struct ByteView;
20 struct ByteArray;
21
28 struct ByteView : public std::span<const std::byte>
29 {
30 using std::span<const std::byte>::span;
31 using std::span<const std::byte>::operator=;
32 using std::span<const std::byte>::operator[];
33
43 template <typename T>
44 [[nodiscard]] const T *as() const
45 {
46 return reinterpret_cast<const T *>(data());
47 }
48
58 [[nodiscard]] constexpr ByteView subview(size_t from = 0) const
59 {
60 return ByteView{ data() + from, size() - from };
61 }
62
74 [[nodiscard]] constexpr ByteView subview(size_t from, size_t length) const
75 {
76 return ByteView{ data() + from, length };
77 }
78 };
79
88 struct ByteArray : public std::vector<std::byte>
89 {
90 using std::vector<std::byte>::vector;
91 using std::vector<std::byte>::operator=;
92 using std::vector<std::byte>::operator[];
93
103 template <typename T>
104 [[nodiscard]] constexpr T *as()
105 {
106 return reinterpret_cast<T *>(data());
107 }
108
118 template <typename T>
119 [[nodiscard]] constexpr const T *as() const
120 {
121 return reinterpret_cast<const T *>(data());
122 }
123
131 [[nodiscard]] constexpr ByteView as_view() const { return ByteView{ data(), size() }; }
132
145 template <typename First, typename Second, typename... Args>
146 void append(First &&first, Second &&second, Args &&...args)
147 {
148 append(std::forward<First>(first));
149 append(std::forward<Second>(second));
150 append(args...);
151 }
152
163 template <typename First, typename Second>
164 void append(First &&first, Second &&second)
165 {
166 append(std::forward<First>(first));
167 append(std::forward<Second>(second));
168 }
169
180 template <typename T>
181 requires(sizeof(T) == sizeof(std::byte)) void append(const std::vector<T> &other)
182 {
183 reserve(size() + other.size());
184 if constexpr (std::is_trivially_constructible_v<std::byte, T>)
185 {
186 insert(end(), other.begin(), other.end());
187 }
188 else
189 {
190 std::transform(other.begin(), other.end(), std::back_inserter(*this),
191 [](const T &t) { return static_cast<std::byte>(t); });
192 }
193 }
194
205 template <typename T>
206 requires(sizeof(T) == sizeof(std::byte)) void append(const std::span<T> &other)
207 {
208 reserve(size() + other.size());
209 if constexpr (std::is_trivially_constructible_v<std::byte, T>)
210 {
211 insert(end(), other.begin(), other.end());
212 }
213 else
214 {
215 std::transform(other.begin(), other.end(), std::back_inserter(*this),
216 [](const T &t) { return static_cast<std::byte>(t); });
217 }
218 }
219
230 template <typename T>
231 requires(sizeof(T) == sizeof(std::byte)) void append(const std::basic_string<T> &other)
232 {
233 reserve(size() + other.size());
234 if constexpr (std::is_trivially_constructible_v<std::byte, T>)
235 {
236 insert(end(), other.begin(), other.end());
237 }
238 else
239 {
240 std::transform(other.begin(), other.end(), std::back_inserter(*this),
241 [](const T &t) { return static_cast<std::byte>(t); });
242 }
243 }
244
254 template <typename T>
255 requires(sizeof(T) == sizeof(std::byte)) void append(const std::basic_string_view<T> &other)
256 {
257 reserve(size() + other.size());
258 if constexpr (std::is_trivially_constructible_v<std::byte, T>)
259 {
260 insert(end(), other.begin(), other.end());
261 }
262 else
263 {
264 std::transform(other.begin(), other.end(), std::back_inserter(*this),
265 [](const T &t) { return static_cast<std::byte>(t); });
266 }
267 }
268
278 template <typename... Args>
279 static ByteArray from_byte_arrays(Args &&...args)
280 {
281 ByteArray result;
282 result.append(std::forward<Args>(args)...);
283 return result;
284 }
285
302 template <std::integral Integer>
303 static ByteArray from_integral(const Integer integer)
304 {
305 ByteArray rv;
306 rv.resize(sizeof(Integer));
307 *rv.as<Integer>() = integer;
308 return rv;
309 }
310
320 [[nodiscard]] constexpr ByteView view(size_t from = 0) const
321 {
322 return ByteView{ data() + from, size() - from };
323 }
324
335 [[nodiscard]] constexpr ByteView view(size_t from, size_t length) const
336 {
337 return ByteView{ data() + from, length };
338 }
339#ifdef BOOST_VERSION
340 private:
341 friend class boost::serialization::access;
342
353 template <class Archive>
354 void serialize(Archive &ar, [[maybe_unused]] const unsigned int version)
355 {
356 ar &boost::serialization::base_object<std::vector<std::byte>>(*this);
357 }
358#endif
359 };
360
361#ifdef BOOST_VERSION
373 template <typename Integer>
374 [[nodiscard]] inline Integer bytes_to_integer(const ByteView byte_view)
375 {
376 mal_toolkit::Assert(byte_view.size() >= sizeof(Integer),
377 "The byte array is too small to be converted to the specified integer type");
378 return boost::endian::little_to_native(*reinterpret_cast<const Integer *>(byte_view.data()));
379 }
380
391 template <typename Integer>
392 [[nodiscard]] inline ByteArray integer_to_bytes(const Integer value)
393 {
394 ByteArray byte_array(sizeof(Integer));
395 *byte_array.as<Integer>() = boost::endian::native_to_little(value);
396 return byte_array;
397 }
398#endif
399
408 [[nodiscard]] inline uint16_t bytes_to_uint16(const ByteView byte_view)
409 {
410 return bytes_to_integer<uint16_t>(byte_view);
411 }
412
422 [[nodiscard]] inline ByteArray uint16_to_bytes(const uint16_t value) { return integer_to_bytes<uint16_t>(value); }
423
432 [[nodiscard]] inline uint32_t bytes_to_uint32(const ByteView byte_view)
433 {
434 return bytes_to_integer<uint32_t>(byte_view);
435 }
436
446 [[nodiscard]] inline ByteArray uint32_to_bytes(const uint32_t value) { return integer_to_bytes<uint32_t>(value); }
447
456 [[nodiscard]] inline uint64_t bytes_to_uint64(const ByteView byte_view)
457 {
458 return bytes_to_integer<uint64_t>(byte_view);
459 }
460
470 [[nodiscard]] inline ByteArray uint64_to_bytes(const uint64_t value) { return integer_to_bytes<uint64_t>(value); }
471
480 [[nodiscard]] inline int16_t bytes_to_int16(const ByteView byte_view)
481 {
482 return bytes_to_integer<int16_t>(byte_view);
483 }
484
494 [[nodiscard]] inline ByteArray int16_to_bytes(const int16_t value) { return integer_to_bytes<int16_t>(value); }
495
504 [[nodiscard]] inline int32_t bytes_to_int32(const ByteView byte_view)
505 {
506 return bytes_to_integer<int32_t>(byte_view);
507 }
508
518 [[nodiscard]] inline ByteArray int32_to_bytes(const int32_t value) { return integer_to_bytes<int32_t>(value); }
519
528 [[nodiscard]] inline int64_t bytes_to_int64(const ByteView byte_view)
529 {
530 return bytes_to_integer<int64_t>(byte_view);
531 }
532
542 [[nodiscard]] inline ByteArray int64_to_bytes(const int64_t value) { return integer_to_bytes<int64_t>(value); }
543
544} // namespace mal_toolkit
Precompiled header (PCH) file for common headers used across the library.
Contains a collection of tools and utilities provided by the MAL Toolkit library.
Definition backoffs.hpp:7
void Assert(bool value, std::string_view message="Assert failed", std::source_location location=std::source_location::current())
Asserts a condition with customizable behavior based on debug mode.
ByteArray uint32_to_bytes(const uint32_t value)
Convert a uint32_t value to a ByteArray using little-endian byte order.
int32_t bytes_to_int32(const ByteView byte_view)
Convert a byte array to an int32_t value using little-endian byte order.
int16_t bytes_to_int16(const ByteView byte_view)
Convert a byte array to an int16_t value using little-endian byte order.
ByteArray uint16_to_bytes(const uint16_t value)
Convert a uint16_t value to a ByteArray using little-endian byte order.
uint32_t bytes_to_uint32(const ByteView byte_view)
Convert a byte array to a uint32_t value using little-endian byte order.
ByteArray int32_to_bytes(const int32_t value)
Convert an int32_t value to a ByteArray using little-endian byte order.
ByteArray int64_to_bytes(const int64_t value)
Convert an int64_t value to a ByteArray using little-endian byte order.
uint16_t bytes_to_uint16(const ByteView byte_view)
Convert a byte array to a uint16_t value using little-endian byte order.
int64_t bytes_to_int64(const ByteView byte_view)
Convert a byte array to an int64_t value using little-endian byte order.
ByteArray int16_to_bytes(const int16_t value)
Convert an int16_t value to a ByteArray using little-endian byte order.
ByteArray uint64_to_bytes(const uint64_t value)
Convert a uint64_t value to a ByteArray using little-endian byte order.
uint64_t bytes_to_uint64(const ByteView byte_view)
Convert a byte array to a uint64_t value using little-endian byte order.
A dynamically resizable array of bytes.
void append(const std::vector< T > &other)
Append a vector of data to the byte array.
constexpr ByteView view(size_t from=0) const
Create a ByteView of a subsequence of the byte array.
static ByteArray from_integral(const Integer integer)
Create a byte array from an integral value.
constexpr ByteView view(size_t from, size_t length) const
Create a ByteView of a subsequence of the byte array.
void append(const std::basic_string< T > &other)
Append a string of data to the byte array.
void append(const std::basic_string_view< T > &other)
Append a string view of data to the byte array.
constexpr const T * as() const
Convert the ByteArray to a const typed pointer.
void append(First &&first, Second &&second)
Append two data sources to the byte array.
static ByteArray from_byte_arrays(Args &&...args)
Create a byte array from multiple data sources.
constexpr ByteView as_view() const
Convert the ByteArray to a ByteView.
void append(const std::span< T > &other)
Append a span of data to the byte array.
constexpr T * as()
Convert the ByteArray to a typed pointer.
void append(First &&first, Second &&second, Args &&...args)
Append multiple data sources to the byte array.
A lightweight view over a sequence of bytes.
constexpr ByteView subview(size_t from, size_t length) const
Create a subview of the ByteView with a specified length.
constexpr ByteView subview(size_t from=0) const
Create a subview of the ByteView.
const T * as() const
Convert the ByteView to a typed view.