30 using DecayedT = std::decay_t<T>;
79 if constexpr (std::is_trivially_copyable_v<T>) {
80 return SerializeTrivial();
81 }
else if constexpr (is_container<T>::value) {
82 return SerializeContainer();
83 }
else if constexpr (is_pair<T>::value) {
84 return SerializePair();
85 }
else if constexpr (is_optional<T>::value) {
86 return SerializeOptional();
88 return SerializeComplex();
103 if constexpr (std::is_trivially_copyable_v<T>) {
104 return DeserializeTrivial(data);
105 }
else if constexpr (is_container<T>::value) {
106 return DeserializeContainer(data);
107 }
else if constexpr (is_pair<T>::value) {
108 return DeserializePair(data);
109 }
else if constexpr (is_optional<T>::value) {
110 return DeserializeOptional(data);
112 return DeserializeComplex(data);
127 return Deserialize(std::span<const std::byte>(data.data(), data.size()));
138 static std::size_t
Size(
const DecayedT& data)
noexcept {
139 if constexpr (std::is_trivially_copyable_v<T>) {
141 }
else if constexpr (is_container<T>::value) {
142 return SizeContainer(data);
143 }
else if constexpr (is_pair<T>::value) {
144 return SizePair(data);
145 }
else if constexpr (is_optional<T>::value) {
146 return SizeOptional(data);
148 return SizeComplex(data);
153 const DecayedT& m_data;
163 std::vector<std::byte> SerializeTrivial() const noexcept {
164 DecayedT value = m_data;
166 if constexpr (std::endian::native != std::endian::little) {
167 value = swap_endian(value);
170 return {
reinterpret_cast<const std::byte*
>(&value),
171 reinterpret_cast<const std::byte*
>(&value) +
sizeof(value) };
182 std::vector<std::byte> SerializeComplex() const noexcept;
192 std::vector<std::
byte> SerializeContainer() const noexcept {
193 std::uint64_t size =
static_cast<std::uint64_t
>(m_data.size());
194 Serializable<std::uint64_t> size_serial(size);
195 std::vector<std::byte> buffer = size_serial.Serialize();
196 buffer.reserve(buffer.size() + SizeContainer(m_data));
197 for (
const auto& element: m_data) {
198 Serializable<std::decay_t<
decltype(element)>> element_serial(element);
199 auto element_data = element_serial.Serialize();
200 append_vector(buffer, std::move(element_data));
213 std::vector<std::byte> SerializePair() const noexcept {
214 Serializable<std::decay_t<typename T::first_type>> first_serial(m_data.first);
215 Serializable<std::decay_t<typename T::second_type>> second_serial(m_data.second);
216 std::vector<std::byte> buffer;
217 buffer.reserve(SizePair(m_data));
218 auto first_data = first_serial.Serialize();
219 auto second_data = second_serial.Serialize();
220 append_vector(buffer, std::move(first_data));
221 append_vector(buffer, std::move(second_data));
233 std::vector<std::byte> SerializeOptional() const noexcept {
234 bool has_value = m_data.has_value();
235 std::vector<std::byte> buffer;
236 buffer.reserve(SizeOptional(m_data));
237 auto has_value_data = Serializable<bool>(has_value).Serialize();
238 append_vector(buffer, std::move(has_value_data));
239 if (m_data.has_value()) {
240 Serializable<std::decay_t<
decltype(m_data.value())>> value_serial(m_data.value());
241 auto value_data = value_serial.Serialize();
242 append_vector(buffer, std::move(value_data));
256 static std::size_t SizeComplex(
const DecayedT& data)
noexcept;
266 static std::size_t SizeContainer(
const DecayedT& data)
noexcept {
267 std::size_t size =
sizeof(std::uint64_t);
268 for (
const auto& element: data) {
283 static std::size_t SizePair(
const DecayedT& data)
noexcept {
285 Serializable<std::decay_t<typename T::first_type>>
::Size(data.first) +
286 Serializable<std::decay_t<typename T::second_type>>
::Size(data.second);
298 static std::size_t SizeOptional(
const DecayedT& data)
noexcept {
299 std::size_t size =
sizeof(bool);
300 if (data.has_value()) {
317 if (data.size() <
sizeof(T))
318 return StormByte::Unexpected<DeserializeError>(
"Insufficient data for deserialization");
320 std::memcpy(&result, data.data(),
sizeof(T));
322 if constexpr (std::endian::native != std::endian::little) {
323 result = swap_endian(result);
340 return DeserializeTrivial(std::span<const std::byte>(data.data(), data.size()));
366 return DeserializeComplex(std::span<const std::byte>(data.data(), data.size()));
380 std::size_t offset = 0;
383 if (offset +
sizeof(std::size_t) > data.size())
384 return StormByte::Unexpected<DeserializeError>(
"Insufficient data for container size");
387 if (!expected_container_size)
390 std::size_t size = expected_container_size.value();
391 offset +=
sizeof(std::size_t);
394 if (size > data.size() - offset)
395 return StormByte::Unexpected<DeserializeError>(
"Claimed container size exceeds remaining buffer");
398 for (std::size_t i = 0; i < size; ++i) {
399 using ElementT = std::decay_t<typename T::value_type>;
401 if (offset >= data.size())
402 return StormByte::Unexpected<DeserializeError>(
"Insufficient data for container element");
405 if (!expected_element)
410 container.insert(container.end(), std::move(expected_element.value()));
411 offset += element_size;
427 return DeserializeContainer(std::span<const std::byte>(data.data(), data.size()));
441 using FirstT = std::decay_t<typename T::first_type>;
442 using SecondT = std::decay_t<typename T::second_type>;
443 std::size_t offset = 0;
453 if (offset >= data.size())
454 return StormByte::Unexpected<DeserializeError>(
"Insufficient data for pair second element");
457 if (!expected_second)
460 return T { std::move(expected_first.value()), std::move(expected_second.value()) };
474 return DeserializePair(std::span<const std::byte>(data.data(), data.size()));
488 std::size_t offset = 0;
491 if (offset +
sizeof(
bool) > data.size())
492 return StormByte::Unexpected<DeserializeError>(
"Insufficient data for optional flag");
495 if (!expected_has_value)
498 offset +=
sizeof(bool);
500 if (expected_has_value.value()) {
501 if (offset >= data.size())
502 return StormByte::Unexpected<DeserializeError>(
"Insufficient data for optional value");
504 using ValueT = std::decay_t<typename T::value_type>;
509 return T { std::move(expected_value.value()) };
526 return DeserializeOptional(std::span<const std::byte>(data.data(), data.size()));