9 #ifndef EAGINE_SERIALIZE_WRITE_HPP
10 #define EAGINE_SERIALIZE_WRITE_HPP
12 #include "../assert.hpp"
13 #include "../bitfield.hpp"
14 #include "../nothing.hpp"
15 #include "../reflect/data_members.hpp"
16 #include "../reflect/enumerators.hpp"
17 #include "../valid_if/decl.hpp"
24 #include <type_traits>
30 class fragment_serialize_wrapper<
span<const T>> {
32 constexpr fragment_serialize_wrapper() noexcept = default;
34 fragment_serialize_wrapper(
span<const T> src) noexcept
37 auto remaining() const noexcept {
38 return skip(_src, _offset);
41 auto offset() const noexcept {
49 auto is_done() const noexcept ->
bool {
62 struct serializer<T&> : serializer<T> {};
65 struct serializer<const T&> : serializer<T> {};
68 struct plain_serializer {
69 template <
typename Backend>
70 static auto write(T value, Backend& backend) {
72 auto errors = backend.write(view_one(value), written);
73 if(EAGINE_UNLIKELY(written < 1)) {
79 template <
typename Backend>
80 static auto write(span<const T> values, Backend& backend) {
82 auto errors = backend.write(values, written);
83 if(EAGINE_UNLIKELY(written < 1)) {
85 }
else if(EAGINE_UNLIKELY(written < values.size())) {
96 struct serializer<bool> : plain_serializer<bool> {};
98 struct serializer<char> : plain_serializer<char> {};
100 struct serializer<std::int8_t> : plain_serializer<std::int8_t> {};
102 struct serializer<short> : plain_serializer<short> {};
104 struct serializer<int> : plain_serializer<int> {};
106 struct serializer<long> : plain_serializer<long> {};
108 struct serializer<long long> : plain_serializer<long long> {};
110 struct serializer<std::uint8_t> : plain_serializer<std::uint8_t> {};
112 struct serializer<unsigned short> : plain_serializer<unsigned short> {};
114 struct serializer<unsigned> : plain_serializer<unsigned> {};
116 struct serializer<unsigned long> : plain_serializer<unsigned long> {};
118 struct serializer<unsigned long long> : plain_serializer<unsigned long long> {};
120 struct serializer<float> : plain_serializer<float> {};
122 struct serializer<double> : plain_serializer<double> {};
124 struct serializer<
identifier> : plain_serializer<identifier> {};
126 struct serializer<decl_name> : plain_serializer<decl_name> {};
128 struct serializer<
string_view> : plain_serializer<string_view> {};
130 template <
typename T>
131 struct common_serializer {
133 template <
typename Backend>
134 auto write(span<const T> values, Backend& backend)
const {
137 auto& sink =
extract(backend.sink());
140 for(
auto& elem : values) {
141 auto th = sink.begin_work();
142 errors |= backend.begin_element(i);
143 if(EAGINE_LIKELY(!errors)) {
145 static_cast<const serializer<T>*
>(
this)->write(elem, backend);
146 errors |= backend.finish_element(i++);
147 if(EAGINE_LIKELY(!errors)) {
149 }
else if(errors.has_at_most(tmd)) {
157 }
else if(errors.has_only(tmd)) {
170 template <
typename... T>
171 struct serializer<std::tuple<T...>> : common_serializer<std::tuple<T...>> {
173 using common_serializer<std::tuple<T...>>::write;
175 template <
typename Backend>
176 auto write(
const std::tuple<T...>& values, Backend& backend)
const {
178 errors |= backend.begin_list(
span_size(
sizeof...(T)));
179 if(EAGINE_LIKELY(!errors)) {
181 errors, values, backend, std::make_index_sequence<
sizeof...(T)>());
182 errors |= backend.finish_list();
188 template <
typename Tuple,
typename Backend, std::size_t... I>
189 void _write_elements(
193 std::index_sequence<I...>)
const {
196 errors, I, std::get<I>(values), backend, std::get<I>(_serializers)));
199 template <
typename Elem,
typename Backend,
typename Serializer>
200 static void _write_element(
205 Serializer& serial) {
206 if(EAGINE_LIKELY(!errors)) {
207 errors |= backend.begin_element(
span_size(index));
208 if(EAGINE_LIKELY(!errors)) {
209 errors |= serial.write(elem, backend);
210 errors |= backend.finish_element(
span_size(index));
215 std::tuple<serializer<T>...> _serializers{};
218 template <
typename... T>
219 struct serializer<std::tuple<std::pair<string_view, T>...>>
220 : common_serializer<std::tuple<std::pair<string_view, T>...>> {
222 template <
typename Backend>
224 const std::tuple<std::pair<string_view, T>...>& members,
227 errors |= backend.begin_struct(
span_size(
sizeof...(T)));
228 if(EAGINE_LIKELY(!errors)) {
233 std::make_index_sequence<
sizeof...(T)>());
234 errors |= backend.finish_struct();
240 template <
typename Tuple,
typename Backend, std::size_t... I>
245 std::index_sequence<I...>) {
249 std::get<0>(std::get<I>(members)),
250 std::get<1>(std::get<I>(members)),
252 std::get<I>(_serializers)));
255 template <
typename Memb,
typename Backend,
typename Serializer>
256 static void _write_member(
261 Serializer& serial) {
262 if(EAGINE_LIKELY(!errors)) {
263 errors |= backend.begin_member(name);
264 if(EAGINE_LIKELY(!errors)) {
265 errors |= serial.write(value, backend);
266 errors |= backend.finish_member(name);
271 std::tuple<serializer<T>...> _serializers{};
274 template <
typename Bit>
275 struct serializer<bitfield<Bit>> : common_serializer<bitfield<Bit>> {
277 template <
typename Backend>
278 auto write(bitfield<Bit> value, Backend& backend)
const {
279 return _serializer.write(value.bits(), backend);
286 template <std::
size_t N>
287 struct serializer<char[N]> : serializer<string_view> {};
289 template <
typename Char,
typename Traits,
typename Alloc>
290 struct serializer<std::basic_string<Char, Traits, Alloc>>
291 : common_serializer<std::basic_string<Char, Traits, Alloc>> {
293 using common_serializer<std::basic_string<Char, Traits, Alloc>>::write;
295 template <
typename Backend>
297 const std::basic_string<Char, Traits, Alloc>& value,
299 return _serializer.write(value, backend);
303 serializer<string_view> _serializer{};
306 template <
typename T>
307 struct serializer<
span<const T>> : common_serializer<span<const T>> {
309 using common_serializer<span<const T>>::write;
311 template <
typename Backend>
312 auto write(span<const T> values, Backend& backend) {
314 errors |= backend.begin_list(values.size());
315 if(EAGINE_LIKELY(!errors)) {
316 errors |= _elem_serializer.write(values, backend);
317 errors |= backend.finish_list();
323 serializer<T> _elem_serializer{};
326 template <
typename T>
327 struct serializer<
span<T>> : serializer<span<const T>> {};
329 template <
typename T>
330 struct serializer<fragment_serialize_wrapper<
span<const T>>>
331 : common_serializer<fragment_serialize_wrapper<span<const T>>> {
333 using common_serializer<fragment_serialize_wrapper<span<const T>>>::write;
335 template <
typename Backend>
337 write(fragment_serialize_wrapper<span<const T>>& frag, Backend& backend) {
339 errors |= _size_serializer.write(frag.offset(), backend);
340 if(EAGINE_LIKELY(!errors)) {
341 auto todo = frag.remaining();
342 errors |= _size_serializer.write(todo.size(), backend);
343 if(EAGINE_LIKELY(!errors)) {
345 errors |= backend.write(todo, written);
346 if(EAGINE_LIKELY(errors.has_at_most(
348 frag.advance(written);
355 serializer<span_size_t> _size_serializer{};
358 template <
typename T, std::
size_t N>
359 struct serializer<std::array<T, N>> : common_serializer<std::array<T, N>> {
361 using common_serializer<std::array<T, N>>::write;
363 template <
typename Backend>
364 auto write(
const std::array<T, N>& values, Backend& backend)
const {
366 errors |= backend.begin_list(
span_size(N));
367 if(EAGINE_LIKELY(!errors)) {
368 errors |= _elem_serializer.write(
view(values), backend);
369 errors |= backend.finish_list();
375 serializer<T> _elem_serializer{};
378 template <
typename T,
typename A>
379 struct serializer<std::vector<T, A>> : common_serializer<std::vector<T, A>> {
381 using common_serializer<std::vector<T, A>>::write;
383 template <
typename Backend>
384 auto write(
const std::vector<T, A>& values, Backend& backend) {
386 errors |= backend.begin_list(values.size());
387 if(EAGINE_LIKELY(!errors)) {
388 errors |= _elem_serializer.write(
view(values), backend);
389 errors |= backend.finish_list();
395 serializer<T> _elem_serializer{};
398 template <
typename Rep>
399 struct serializer<std::chrono::duration<Rep>>
400 : common_serializer<std::chrono::duration<Rep>> {
402 template <
typename Backend>
403 auto write(std::chrono::duration<Rep> value, Backend& backend) {
404 return _serializer.write(value.count(), backend);
408 serializer<Rep> _serializer{};
411 template <
typename T,
typename P>
412 struct serializer<valid_if<T, P>> : common_serializer<valid_if<T, P>> {
414 template <
typename Backend>
415 auto write(
const valid_if<T, P>& value, Backend& backend) {
417 const bool is_valid = value.is_valid();
418 errors |= backend.begin_list(is_valid ? 1 : 0);
419 if(EAGINE_LIKELY(!errors)) {
421 errors |= _serializer.write(value.value_anyway(), backend);
423 errors |= backend.finish_list();
429 serializer<T> _serializer{};
432 template <
typename T>
433 struct enum_serializer {
434 template <
typename Backend>
435 auto write(T enumerator, Backend& backend)
const {
437 if(backend.enum_as_string()) {
439 _name_serializer.write(enumerator_name(enumerator), backend);
442 _value_serializer.write(enumerator_value(enumerator), backend);
448 serializer<std::underlying_type_t<T>> _value_serializer{};
449 serializer<decl_name> _name_serializer{};
452 template <
typename T>
453 struct struct_serializer {
455 template <
typename Backend>
456 auto write(
const T& instance, Backend& backend) {
457 auto member_map = map_data_members(instance);
458 return _serializer.write(member_map, backend);
462 serializer<decltype(map_data_members(std::declval<T>()))> _serializer{};
465 template <
typename T>
467 : std::conditional_t<
468 has_enumerator_mapping_v<T>,
471 has_data_member_mapping_v<T>,
472 struct_serializer<T>,
479 template <
typename T,
typename Backend>
480 auto serialize(T& value, Backend& backend) -> std::enable_if_t<
481 std::is_base_of_v<serializer_backend, Backend>,
484 errors |= backend.begin();
485 if(EAGINE_LIKELY(!errors)) {
486 serializer<std::remove_cv_t<T>> writer;
487 errors |= writer.write(value, backend);
488 errors |= backend.finish();
490 errors |=
extract(backend.sink()).finalize();
496 #endif // EAGINE_SERIALIZE_WRITE_HPP