-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
148 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#pragma once | ||
|
||
#include <algorithm> // IWYU pragma: keep | ||
#include <array> | ||
#include <cstddef> | ||
|
||
#include "upd/detail/always_false.hpp" | ||
#include "upd/detail/is_bounded_array.hpp" // IWYU pragma: keep | ||
#include "upd/upd.hpp" | ||
|
||
namespace upd { | ||
|
||
template<typename Consumer_T, typename Serializer_T> | ||
class basic_obytestream { | ||
public: | ||
basic_obytestream(Consumer_T consumer, Serializer_T serializer) noexcept | ||
: m_consumer{UPD_FWD(consumer)}, m_serializer{UPD_FWD(serializer)} {} | ||
|
||
template<typename... Args> | ||
void encode(const Args &...args) { | ||
if constexpr (sizeof...(args) > 1) { | ||
(encode(UPD_FWD(args)), ...); | ||
} else { | ||
encode_one(UPD_FWD(args)...); | ||
} | ||
} | ||
|
||
private: | ||
template<typename T> | ||
void encode_one(const T &x) { | ||
if constexpr (std::is_signed_v<T>) { | ||
encode_signed(UPD_FWD(x)); | ||
} else if constexpr (std::is_unsigned_v<T>) { | ||
encode_unsigned(UPD_FWD(x)); | ||
} else if constexpr (detail::is_bounded_array_v<T>) { | ||
encode_bounded_array(UPD_FWD(x)); | ||
} else { | ||
static_assert(UPD_ALWAYS_FALSE, "`T` cannot be serialized"); | ||
} | ||
} | ||
|
||
template<typename T> | ||
void encode_signed(const T &value) { | ||
auto buf = std::array<std::byte, sizeof value>{}; | ||
|
||
m_serializer.serialize_signed(UPD_FWD(value), buf.size(), buf.data()); | ||
m_consumer = std::copy(buf.begin(), buf.end(), m_consumer); | ||
}; | ||
|
||
template<typename T> | ||
void encode_unsigned(const T &value) { | ||
auto buf = std::array<std::byte, sizeof value>{}; | ||
|
||
m_serializer.serialize_unsigned(UPD_FWD(value), buf.size(), buf.data()); | ||
m_consumer = std::copy(buf.begin(), buf.end(), m_consumer); | ||
}; | ||
|
||
template<typename T> | ||
void encode_bounded_array(const T &array) { | ||
for (const auto &value : array) { | ||
encode_one(value); | ||
} | ||
}; | ||
|
||
Consumer_T m_consumer; | ||
Serializer_T m_serializer; | ||
}; | ||
|
||
} // namespace upd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) | ||
#define UPD_ASSERT(...) \ | ||
if (!(__VA_ARGS__)) { \ | ||
throw std::exception{}; \ | ||
} | ||
|
||
#include <any> | ||
#include <iterator> | ||
#include <optional> | ||
#include <utility> | ||
#include <variant> | ||
|
||
#include "mock/serializer_interface.hpp" | ||
#include "utility/generators.hpp" | ||
#include "utility/mocking.hpp" | ||
#include <catch2/catch_test_macros.hpp> | ||
#include <catch2/generators/catch_generators_all.hpp> | ||
#include <fakeit.hpp> | ||
#include <upd/basic_ibytestream.hpp> | ||
#include <upd/basic_obytestream.hpp> | ||
#include <upd/basic_tuple.hpp> | ||
#include <upd/detail/assertion.hpp> | ||
#include <upd/detail/variadic/map.hpp> | ||
#include <upd/detail/variadic/max.hpp> | ||
#include <upd/static_vector.hpp> | ||
|
||
using namespace fakeit; | ||
|
||
// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) | ||
|
||
TEST_CASE("Serializing a packet...") { | ||
auto storage = std::vector<std::byte>{}; | ||
auto mock_serializer = Mock<serializer_interface>{}; | ||
|
||
auto consumer = std::back_inserter(storage); | ||
auto &serializer = mock_serializer.get(); | ||
auto bstream = upd::basic_obytestream<decltype(consumer), decltype(serializer)>{consumer, serializer}; | ||
|
||
When(Method(mock_serializer, serialize_signed)).AlwaysReturn(); | ||
When(Method(mock_serializer, serialize_unsigned)).AlwaysReturn(); | ||
|
||
SECTION("...containing integers and array of integer") { | ||
int int_array[] = {-1, 2, -3, 4}; | ||
unsigned long ulong_array[] = {100, 200}; | ||
bstream.encode(int{-64}, (unsigned int)48, int_array, (unsigned short)16, ulong_array, char{1}); | ||
|
||
Verify(Method(mock_serializer, serialize_signed).Using(-64, sizeof(int), _), | ||
Method(mock_serializer, serialize_unsigned).Using(48, sizeof(unsigned int), _), | ||
Method(mock_serializer, serialize_signed).Using(-1, sizeof(int), _), | ||
Method(mock_serializer, serialize_signed).Using(2, sizeof(int), _), | ||
Method(mock_serializer, serialize_signed).Using(-3, sizeof(int), _), | ||
Method(mock_serializer, serialize_signed).Using(4, sizeof(int), _), | ||
Method(mock_serializer, serialize_unsigned).Using(16, sizeof(unsigned short), _), | ||
Method(mock_serializer, serialize_unsigned).Using(100, sizeof(unsigned long), _), | ||
Method(mock_serializer, serialize_unsigned).Using(200, sizeof(unsigned long), _), | ||
Method(mock_serializer, serialize_signed).Using(1, sizeof(char), _)); | ||
} | ||
} | ||
|
||
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
|
||
struct serializer_interface { | ||
serializer_interface(const serializer_interface &) = delete; | ||
auto operator=(const serializer_interface &) -> serializer_interface & = delete; | ||
|
||
serializer_interface(serializer_interface &&) = delete; | ||
auto operator=(serializer_interface &&) -> serializer_interface & = delete; | ||
|
||
virtual void serialize_unsigned(std::uintmax_t value, std::size_t size, std::byte *output) = 0; | ||
virtual void serialize_signed(std::intmax_t value, std::size_t size, std::byte *output) = 0; | ||
virtual auto deserialize_unsigned(const std::byte *input, std::size_t size) -> std::uintmax_t = 0; | ||
virtual auto deserialize_signed(const std::byte *input, std::size_t size) -> std::intmax_t = 0; | ||
virtual ~serializer_interface() = default; | ||
}; |