StormByte C++ Library 0.0.9999
StormByte is a comprehensive, cross-platform C++ library aimed at easing system programming, configuration management, logging, and database handling tasks. This library provides a unified API that abstracts away the complexities and inconsistencies of different platforms (Windows, Linux).
Loading...
Searching...
No Matches
serializable.hxx
1#pragma once
2
3#include <StormByte/buffer/simple.hxx>
4#include <StormByte/exception.hxx>
5#include <StormByte/expected.hxx>
6#include <StormByte/type_traits.hxx>
7
8#include <optional>
9#include <utility>
10
18namespace StormByte {
24 template<typename T>
26 using DecayedT = std::decay_t<T>;
27
28 public:
33 Serializable(const DecayedT& data) noexcept: m_data(data) {}
34
39 Serializable(const Serializable& other) noexcept = delete;
40
45 Serializable(Serializable&& other) noexcept = delete;
46
51
58
65
72 if constexpr (std::is_trivially_copyable_v<T>) {
73 return SerializeTrivial();
74 } else if constexpr (is_container<T>::value) {
75 return SerializeContainer();
76 } else if constexpr (is_pair<T>::value) {
77 return SerializePair();
78 } else if constexpr (is_optional<T>::value) {
79 return SerializeOptional();
80 } else {
81 return SerializeComplex();
82 }
83 }
84
91 if constexpr (std::is_trivially_copyable_v<T>) {
92 return DeserializeTrivial(data);
93 } else if constexpr (is_container<T>::value) {
94 return DeserializeContainer(data);
95 } else if constexpr (is_pair<T>::value) {
96 return DeserializePair(data);
97 } else if constexpr (is_optional<T>::value) {
98 return DeserializeOptional(data);
99 } else {
100 return DeserializeComplex(data);
101 }
102 }
103
104 static std::size_t Size(const DecayedT& data) noexcept {
105 if constexpr (std::is_trivially_copyable_v<T>) {
106 return sizeof(data);
107 } else if constexpr (is_container<T>::value) {
108 return SizeContainer(data);
109 } else if constexpr (is_pair<T>::value) {
110 return SizePair(data);
111 } else if constexpr (is_optional<T>::value) {
112 return SizeOptional(data);
113 } else {
114 return SizeComplex(data);
115 }
116 }
117
118 private:
119 const DecayedT& m_data;
120
126 Buffer::Simple SerializeTrivial() const noexcept {
127 return { reinterpret_cast<const char*>(&m_data), sizeof(m_data) };
128 }
129
135 Buffer::Simple SerializeComplex() const noexcept;
136
142 Buffer::Simple SerializeContainer() const noexcept {
143 std::size_t size = m_data.size();
145 Buffer::Simple buffer(std::move(size_serial.Serialize()));
146 for (const auto& element: m_data) {
147 Serializable<std::decay_t<decltype(element)>> element_serial(element);
148 buffer << std::move(element_serial.Serialize());
149 }
150 return buffer;
151 }
152
158 Buffer::Simple SerializePair() const noexcept {
161 return first_serial.Serialize() << std::move(second_serial.Serialize());
162 }
163
169 Buffer::Simple SerializeOptional() const noexcept {
170 bool has_value = m_data.has_value();
171 Buffer::Simple buffer = std::move(Serializable<bool>(has_value).Serialize());
172 if (m_data.has_value()) {
173 Serializable<std::decay_t<decltype(m_data.value())>> value_serial(m_data.value());
174 buffer << std::move(value_serial.Serialize());
175 }
176 return buffer;
177 }
178
184 static std::size_t SizeComplex(const DecayedT& data) noexcept;
185
191 static std::size_t SizeContainer(const DecayedT& data) noexcept {
192 std::size_t size = sizeof(std::size_t);
193 for (const auto& element: data) {
194 size += Serializable<std::decay_t<decltype(element)>>::Size(element);
195 }
196 return size;
197 }
198
204 static std::size_t SizePair(const DecayedT& data) noexcept {
205 return
208 }
209
215 static std::size_t SizeOptional(const DecayedT& data) noexcept {
216 std::size_t size = sizeof(bool);
217 if (data.has_value()) {
218 size += Serializable<std::decay_t<decltype(data.value())>>::Size(data.value());
219 }
220 return size;
221 }
222
228 static StormByte::Expected<T, Buffer::BufferOverflow> DeserializeTrivial(const Buffer::Simple& data) noexcept {
229 auto expected_value = data.Read(sizeof(T));
230 if (!expected_value)
232 return T { *reinterpret_cast<const T*>(expected_value.value().data()) };
233 }
234
240 static StormByte::Expected<T, Buffer::BufferOverflow> DeserializeComplex(const Buffer::Simple& data) noexcept;
241
247 static StormByte::Expected<T, Buffer::BufferOverflow> DeserializeContainer(const Buffer::Simple& data) noexcept {
251
252 std::size_t size = expected_container_size.value();
253
254 T container;
255 for (std::size_t i = 0; i < size; ++i) {
257 if (!expected_element)
259
260 container.insert(container.end(), std::move(expected_element.value()));
261 }
262 return container;
263 }
264
270 static StormByte::Expected<T, Buffer::BufferOverflow> DeserializePair(const Buffer::Simple& data) noexcept {
271 using FirstT = std::decay_t<typename T::first_type>;
272 using SecondT = std::decay_t<typename T::second_type>;
273
275 if (!expected_first)
277
279 if (!expected_second)
281
282 return T { expected_first.value(), expected_second.value() };
283 }
284
285 static StormByte::Expected<T, Buffer::BufferOverflow> DeserializeOptional(const Buffer::Simple& data) noexcept {
289
290 if (expected_has_value.value()) {
291 auto expected_value = Serializable<std::decay_t<decltype(m_data.value())>>::Deserialize(data);
292 if (!expected_value)
294
295 return T { expected_value.value() };
296 } else {
297 return T {};
298 }
299 }
300 };
301}
A lightweight class for storing and manipulating simple byte buffers.
Definition simple.hxx:37
The class to serialize and deserialize data.
Definition serializable.hxx:25
Serializable(const DecayedT &data) noexcept
The constructor of the Serializable class.
Definition serializable.hxx:33
static StormByte::Expected< T, Buffer::BufferOverflow > Deserialize(const Buffer::Simple &data) noexcept
The function to deserialize the data.
Definition serializable.hxx:90
Serializable(const Serializable &other) noexcept=delete
The copy constructor of the Serializable class.
Serializable(Serializable &&other) noexcept=delete
The move constructor of the Serializable class.
Buffer::Simple Serialize() const noexcept
The function to serialize the data.
Definition serializable.hxx:71
~Serializable() noexcept=default
The destructor of the Serializable class.
Namespace for buffer-related components in the StormByte library.
Main namespace for the StormByte library.
auto Unexpected(std::shared_ptr< E > error_ptr)
Creates an std::unexpected with a shared pointer to the error.
Definition expected.hxx:43
std::conditional_t< is_reference< T >::value, std::expected< std::reference_wrapper< std::remove_reference_t< T > >, std::shared_ptr< E > >, std::expected< T, std::shared_ptr< E > > > Expected
Expected type with support for reference types.
Definition expected.hxx:32
Type trait to check if a type is a container.
Definition type_traits.hxx:21
Type trait to check if a type is an optional.
Definition type_traits.hxx:37
Type trait to check if a type is a pair.
Definition type_traits.hxx:54