Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
ser_dispatch.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <type_traits>
5#include <utility>
6
7#include "gaia/core/utility.h"
8#include "gaia/meta/reflection.h"
9#include "gaia/ser/ser_common.h"
10
11namespace gaia {
12 namespace ser {
13 namespace detail {
15 template <typename Serializer, typename T, typename SaveTrivial>
16 void save_dispatch(Serializer& s, const T& arg, SaveTrivial&& saveTrivial) {
17 using U = core::raw_t<T>;
18
19 // Custom save() has precedence
20 if constexpr (has_func_save<U, Serializer&>::value) {
21 arg.save(s);
22 } else if constexpr (has_tag_save<Serializer, U>::value) {
23 tag_invoke(save_v, s, static_cast<const U&>(arg));
24 }
25 // Trivially serializable types
26 else if constexpr (is_trivially_serializable<U>::value) {
27 saveTrivial(s, arg);
28 }
29 // Types which have size(), begin() and end() member functions
30 else if constexpr (core::has_size_begin_end<U>::value) {
31 const auto size = arg.size();
32 saveTrivial(s, size);
33
34 for (const auto& e: std::as_const(arg))
35 save_dispatch(s, e, saveTrivial);
36 }
37 // Classes
38 else if constexpr (std::is_class_v<U>) {
39 meta::each_member(GAIA_FWD(arg), [&s, &saveTrivial](auto&&... items) {
40 // TODO: Handle contiguous blocks of trivially copyable types
41 (save_dispatch(s, items, saveTrivial), ...);
42 });
43 } else
44 static_assert(!sizeof(U), "Type is not supported for serialization, yet");
45 }
46
47 template <typename Serializer, typename T, typename LoadTrivial>
48 void load_dispatch(Serializer& s, T& arg, LoadTrivial&& loadTrivial) {
49 using U = core::raw_t<T>;
50
51 // Custom load() has precedence
52 if constexpr (has_func_load<U, Serializer&>::value) {
53 arg.load(s);
54 } else if constexpr (has_tag_load<Serializer, U>::value) {
55 tag_invoke(load_v, s, static_cast<U&>(arg));
56 }
57 // Trivially serializable types
58 else if constexpr (is_trivially_serializable<U>::value) {
59 loadTrivial(s, arg);
60 }
61 // Types which have size(), begin() and end() member functions
62 else if constexpr (core::has_size_begin_end<U>::value) {
63 auto size = arg.size();
64 loadTrivial(s, size);
65
66 if constexpr (has_func_resize<U, size_t>::value) {
67 // If resize is present, use it
68 arg.resize(size);
69
70 // NOTE: We can't do it this way. If there are containers with the overloaded
71 // operator=, the result might not be what one would expect.
72 // E.g., in our case, SoA containers need specific handling.
73 // for (auto&& e: arg)
74 // load_dispatch(s, e, loadTrivial);
75
76 uint32_t i = 0;
77 for (auto e: arg) {
78 load_dispatch(s, e, loadTrivial);
79 arg[i] = GAIA_MOV(e);
80 ++i;
81 }
82 } else {
83 // With no resize present, write directly into memory
84 GAIA_FOR(size) {
85 using arg_type = typename std::remove_pointer<decltype(arg.data())>::type;
86 arg_type val;
87 load_dispatch(s, val, loadTrivial);
88 arg[i] = val;
89 }
90 }
91 }
92 // Classes
93 else if constexpr (std::is_class_v<U>) {
94 meta::each_member(GAIA_FWD(arg), [&s, &loadTrivial](auto&&... items) {
95 // TODO: Handle contiguous blocks of trivially copyable types
96 (load_dispatch(s, items, loadTrivial), ...);
97 });
98 } else
99 static_assert(!sizeof(U), "Type is not supported for serialization, yet");
100 }
102 } // namespace detail
103 } // namespace ser
104} // namespace gaia
static constexpr bool value
True when the type can be serialized trivially.
Definition ser_common.h:117