Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
ser_rt.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 struct ISerializer {
14 ISerializer() = default;
15 virtual ~ISerializer() = default;
16 ISerializer(const ISerializer&) = default;
17 ISerializer(ISerializer&&) = default;
18 ISerializer& operator=(const ISerializer&) = default;
19 ISerializer& operator=(ISerializer&&) = default;
20
21 template <typename T>
22 void save(const T& arg) {
23 using U = core::raw_t<T>;
24
25 // Custom save() has precedence
26 if constexpr (has_func_save<U, ISerializer&>::value) {
27 arg.save(*this);
28 } else if constexpr (has_tag_save<ISerializer, U>::value) {
29 tag_invoke(save_v, *this, static_cast<const U&>(arg));
30 }
31 // Trivially serializable types
32 else if constexpr (is_trivially_serializable<U>::value) {
33 this->save_raw(arg);
34 }
35 // Types which have size(), begin() and end() member functions
36 else if constexpr (core::has_size_begin_end<U>::value) {
37 const auto size = arg.size();
38 this->save_raw(size);
39
40 for (const auto& e: std::as_const(arg))
41 save(e);
42 }
43 // Classes
44 else if constexpr (std::is_class_v<U>) {
45 meta::each_member(GAIA_FWD(arg), [&](auto&&... items) {
46 // TODO: Handle contiguous blocks of trivially copyable types
47 (save(items), ...);
48 });
49 } else
50 static_assert(!sizeof(U), "Type is not supported for serialization, yet");
51 }
52
53 template <typename T>
54 void load(T& arg) {
55 using U = core::raw_t<T>;
56
57 // Custom load() has precedence
58 if constexpr (has_func_load<U, ISerializer&>::value) {
59 arg.load(*this);
60 } else if constexpr (has_tag_load<ISerializer, U>::value) {
61 tag_invoke(load_v, *this, static_cast<U&>(arg));
62 }
63 // Trivially serializable types
64 else if constexpr (is_trivially_serializable<U>::value) {
65 this->load_raw(arg);
66 }
67 // Types which have size(), begin() and end() member functions
68 else if constexpr (core::has_size_begin_end<U>::value) {
69 auto size = arg.size();
70 this->load_raw(size);
71
72 if constexpr (has_func_resize<U, size_t>::value) {
73 // If resize is present, use it
74 arg.resize(size);
75
76 // NOTE: We can't do it this way. If there are containers with the overloaded
77 // operator=, the result might not be what one would expect.
78 // E.g., in our case, SoA containers need specific handling.
79 // for (auto&& e: arg)
80 // load(e);
81
82 uint32_t i = 0;
83 for (auto e: arg) {
84 load(e);
85 arg[i] = std::move(e);
86 ++i;
87 }
88 } else {
89 // With no resize present, write directly into memory
90 GAIA_FOR(size) {
91 using arg_type = typename std::remove_pointer<decltype(arg.data())>::type;
92 arg_type val;
93 load(val);
94 arg[i] = val;
95 }
96 }
97 }
98 // Classes
99 else if constexpr (std::is_class_v<U>) {
100 meta::each_member(GAIA_FWD(arg), [&](auto&&... items) {
101 // TODO: Handle contiguous blocks of trivially copyable types
102 (load(items), ...);
103 });
104 } else
105 static_assert(!sizeof(U), "Type is not supported for serialization, yet");
106 }
107
108#if GAIA_ASSERT_ENABLED
109 template <typename T>
110 void check(const T& arg) {
111 T tmp{};
112
113 // Make sure that we write just as many bytes as we read.
114 // If positions are the same there is a good chance that save and load match.
115 const auto pos0 = tell();
116 save(arg);
117 const auto pos1 = tell();
118 seek(pos0);
119 load(tmp);
120 const auto pos2 = tell();
121 GAIA_ASSERT(pos2 == pos1);
122
123 // Return back to the original position in the buffer.
124 seek(pos0);
125 }
126#endif
127
128 template <typename T>
129 void save_raw(const T& value) {
130 save_raw(&value, sizeof(value), ser::type_id<T>());
131 }
132
133 template <typename T>
134 void load_raw(T& value) {
135 load_raw(&value, sizeof(value), ser::type_id<T>());
136 }
137
138 virtual void save_raw(const void* src, uint32_t size, serialization_type_id id) {
139 (void)id;
140 (void)src;
141 (void)size;
142 }
143
144 virtual void load_raw(void* src, uint32_t size, serialization_type_id id) {
145 (void)id;
146 (void)src;
147 (void)size;
148 }
149
150 virtual const char* data() const {
151 return nullptr;
152 }
153
154 virtual void reset() {}
155
156 virtual uint32_t tell() const {
157 return 0;
158 }
159
160 virtual uint32_t bytes() const {
161 return 0;
162 }
163
164 virtual void seek(uint32_t pos) {
165 (void)pos;
166 }
167 };
168 } // namespace ser
169} // namespace gaia
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition utility.h:153
Definition ser_rt.h:13
Definition ser_common.h:92