Realm
A distributed, event-based tasking library
Loading...
Searching...
No Matches
serialize.h
Go to the documentation of this file.
1/*
2 * Copyright 2025 Stanford University, NVIDIA Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// serialization logic for packing/unpacking data in byte streams
19
20#ifndef REALM_SERIALIZE_H
21#define REALM_SERIALIZE_H
22
23#include "realm/realm_config.h"
24#include "realm/bytearray.h"
25#include "realm/utils.h"
26
27#include <stddef.h>
28#include <vector>
29#include <list>
30#include <set>
31#include <map>
32#include <string>
33#include <typeinfo>
34
35// To add serializability for a new data type, do one of the following:
36//
37// 1) If your type can be copied bit for bit (i.e. C++11's is_trivially_copyable), just
38// do:
39// TYPE_IS_SERIALIZABLE(my_type);
40//
41// 2) If your type is just a struct with a bunch of members, do:
42// template<typename S>
43// bool serdez(S& s, const my_type& t)
44// {
45// return (s & t.field1) && (s & t.field2) ... ;
46// }
47//
48// 3) If your type needs to serialize and deserialize in a complicated way, define them
49// separately:
50//
51// template<typename S>
52// bool serialize(S& s, const my_type& t)
53// {
54// // serialization code here...
55// }
56//
57// template<typename S>
58// bool deserialize(S& s, my_type& t)
59// {
60// // deserialization code here...
61// }
62
63// helper template tells us which types can be directly copied into serialized streams
64// (this is similar to C++11's is_trivially_copyable, but does not include pointers since
65// their values are not meaningful to other nodes)
66//
67// The implementation is a bit weird, because we need to be able to add new serializable
68// types from other namespaces. This prevents us from doing a simple specialization of a
69// base template because you can only specialize in the same namespace in which the
70// template was originally declared. Instead, we use the ability to overload operators
71// with different return types and test the sizeof() the return type to see if a given
72// type T has been specifically listed as serializable. To make it extremely unlikely
73// that it'll break any actual code, we use the comma operator and an unconstructable type
74// on the left hand side.
75//
76// Addendum: It turns out namespaces are still problematic and this particular part needs
77// to be in the
78// global namespace (unless you want to force everybody to import Realm::Serialization),
79// even though calls to TYPE_IS_SERIALIZABLE() _can_ be done from other namespaces.
81public:
82 class inner {
83 public:
84 inner(void) {}
85 };
86
87public:
88 template <typename T>
89 struct test {
90 static const bool value = sizeof(inner(), *reinterpret_cast<T *>(0)) != sizeof(char);
91 };
92};
93template <typename T>
94char operator,(const is_copy_serializable::inner &, const T &);
95
96#define TYPE_IS_SERIALIZABLE(T) \
97 void *operator,(const is_copy_serializable::inner &, const T &);
98
99#define TEMPLATE_TYPE_IS_SERIALIZABLE(P, T) \
100 template <P> \
101 void *operator,(const is_copy_serializable::inner &, const T &);
102#define TEMPLATE_TYPE_IS_SERIALIZABLE2(P1, P2, T1, T2) \
103 template <P1, P2> \
104 void *operator,(const is_copy_serializable::inner &, const T1, T2 &);
105#define TEMPLATE_TYPE_IS_SERIALIZABLE3(P1, P2, P3, T1, T2, T3) \
106 template <P1, P2, P3> \
107 void *operator,(const is_copy_serializable::inner &, const T1, T2, T3 &);
108
109namespace Realm {
110 namespace Serialization {
111 // there are three kinds of serializer we use and a single deserializer:
112 // a) FixedBufferSerializer - accepts a fixed-size buffer and fills into while
113 // preventing overflow b) DynamicBufferSerializer - serializes data into an
114 // automatically-regrowing buffer c) ByteCountSerializer - doesn't actually store
115 // data, just counts how big it would be d) FixedBufferDeserializer - deserializes
116 // from a fixed-size buffer
117
119 public:
121 FixedBufferSerializer(void *buffer, size_t size);
124
125 void reset(void *buffer, size_t size);
126 void reset(ByteArray &array);
127
128 ptrdiff_t bytes_left(void) const;
129
130 bool append_bytes(const void *data, size_t datalen);
131 template <typename T>
132 bool append_serializable(const T &data);
133
134 template <typename T>
135 bool operator<<(const T &val);
136 template <typename T>
137 bool operator&(const T &val);
138
139 protected:
140 char *pos;
141 char *limit;
142 };
143
145 public:
146 DynamicBufferSerializer(size_t initial_size);
148
149 void reset(void);
150
151 size_t bytes_used(void) const;
152 const void *get_buffer(void) const;
153 void *detach_buffer(ptrdiff_t max_wasted_bytes = 0);
154 ByteArray detach_bytearray(ptrdiff_t max_wasted_bytes = 0);
155
156 bool append_bytes(const void *data, size_t datalen);
157 template <typename T>
158 bool append_serializable(const T &data);
159
160 template <typename T>
161 bool operator<<(const T &val);
162 template <typename T>
163 bool operator&(const T &val);
164
165 protected:
166 char *base;
167 char *pos;
168 char *limit;
169 };
170
172 public:
175
176 size_t bytes_used(void) const;
177
178 bool append_bytes(const void *data, size_t datalen);
179 template <typename T>
180 bool append_serializable(const T &data);
181
182 template <typename T>
183 bool operator<<(const T &val);
184 template <typename T>
185 bool operator&(const T &val);
186
187 protected:
188 size_t count;
189 };
190
192 public:
193 FixedBufferDeserializer(const void *buffer, size_t size);
196
197 ptrdiff_t bytes_left(void) const;
198
199 bool extract_bytes(void *data, size_t datalen);
200 const void *peek_bytes(size_t datalen);
201 template <typename T>
202 bool extract_serializable(T &data);
203
204 template <typename T>
205 bool operator>>(T &val);
206 template <typename T>
207 bool operator&(const T &val);
208
209 protected:
210 const char *pos;
211 const char *limit;
212 };
213
214 // defaults if custom serializers/deserializers are not defined
215 template <typename S, typename T>
216 bool serdez(S &, const T &); // not implemented
217
218 template <typename S, typename T>
219 inline bool serialize(S &s, const T &t)
220 {
221 return serdez(s, t);
222 }
223
224 template <typename S, typename T>
225 inline bool deserialize(S &s, T &t)
226 {
227 return serdez(s, t);
228 }
229
230 template <typename T, bool IS_COPY_SERIALIZABLE>
232
233 template <typename T>
234 struct SerializationHelper<T, true> {
235 // this is the special case where we can copy bits directly, even for vectors
236 template <typename S>
237 static bool serialize_scalar(S &s, const T &data);
238 template <typename S>
239 static bool deserialize_scalar(S &s, T &data);
240 template <typename S>
241 static bool serialize_vector(S &s, const std::vector<T> &v);
242 template <typename S>
243 static bool deserialize_vector(S &s, std::vector<T> &v);
244 template <typename S, size_t Extent>
245 static bool serialize_span(S &s, span<T, Extent> sp);
246 template <typename S, size_t Extent>
247 static bool deserialize_span(S &s, span<T, Extent> &sp);
248 };
249
250 template <typename T>
251 struct SerializationHelper<T, false> {
252 // in this case, we have to fall through to custom-defined serializers
253 template <typename S>
254 static bool serialize_scalar(S &s, const T &data);
255 template <typename S>
256 static bool deserialize_scalar(S &s, T &data);
257 template <typename S>
258 static bool serialize_vector(S &s, const std::vector<T> &v);
259 template <typename S>
260 static bool deserialize_vector(S &s, std::vector<T> &v);
261 template <typename S, size_t Extent>
262 static bool serialize_span(S &s, span<T, Extent> sp);
263 // no deserialization of spans for non-copy-serializable types
264 };
265
266 // support for static arrays
267 template <typename S, typename T, size_t N>
268 bool serialize(S &s, T (&a)[N]);
269
270 template <typename S, typename T, size_t N>
271 bool deserialize(S &s, T (&a)[N]);
272
273 // support for some STL containers
274 template <typename S, typename T1, typename T2>
275 bool serialize(S &s, const std::pair<T1, T2> &p);
276
277 template <typename S, typename T1, typename T2>
278 bool deserialize(S &s, std::pair<T1, T2> &p);
279
280 template <typename S, typename T>
281 bool serialize(S &s, const std::vector<T> &v);
282
283 template <typename S, typename T>
284 bool deserialize(S &s, std::vector<T> &v);
285
286 template <typename S, typename T>
287 bool serialize(S &s, const std::list<T> &l);
288
289 template <typename S, typename T>
290 bool deserialize(S &s, std::list<T> &l);
291
292 template <typename S, typename T>
293 bool serialize(S &s, const std::set<T> &ss);
294
295 template <typename S, typename T>
296 bool deserialize(S &s, std::set<T> &ss);
297
298 template <typename S, typename T1, typename T2>
299 bool serialize(S &s, const std::map<T1, T2> &m);
300
301 template <typename S, typename T1, typename T2>
302 bool deserialize(S &s, std::map<T1, T2> &m);
303
304 template <typename S>
305 bool serialize(S &s, const std::string &str);
306
307 template <typename S>
308 bool deserialize(S &s, std::string &str);
309
310 template <typename S, typename T, size_t Extent>
312
313 template <typename S, typename T, size_t Extent>
315
316 template <typename T>
318
319 template <typename T>
321 public:
322 // not templated because we have to get through a virtual method
323 static bool serialize(FixedBufferSerializer &serializer, const T &obj);
324 static bool serialize(DynamicBufferSerializer &serializer, const T &obj);
325 static bool serialize(ByteCountSerializer &serializer, const T &obj);
326
327 static T *deserialize_new(FixedBufferDeserializer &deserializer);
328
329 protected:
330 typedef unsigned TypeTag;
331 struct SubclassMap {
332 std::map<const char *, const PolymorphicSerdezIntfc<T> *> by_typename;
333 std::map<TypeTag, const PolymorphicSerdezIntfc<T> *> by_tag;
334 };
335
336 friend class PolymorphicSerdezIntfc<T>;
337
338 template <typename T1, typename T2>
340
342 };
343
344 template <typename T>
346 public:
347 PolymorphicSerdezIntfc(const char *type_name);
349
350 virtual bool serialize(FixedBufferSerializer &serializer, const T &obj) const = 0;
351 virtual bool serialize(DynamicBufferSerializer &serializer, const T &obj) const = 0;
352 virtual bool serialize(ByteCountSerializer &serializer, const T &obj) const = 0;
353
354 virtual T *deserialize_new(FixedBufferDeserializer &deserializer) const = 0;
355
356 protected:
357 friend class PolymorphicSerdezHelper<T>;
358
360 };
361
362 template <typename T1, typename T2>
364 public:
366
367 virtual bool serialize(FixedBufferSerializer &serializer, const T1 &obj) const;
368 virtual bool serialize(DynamicBufferSerializer &serializer, const T1 &obj) const;
369 virtual bool serialize(ByteCountSerializer &serializer, const T1 &obj) const;
370
371 virtual T1 *deserialize_new(FixedBufferDeserializer &deserializer) const;
372 };
373
374 }; // namespace Serialization
375
376}; // namespace Realm
377
378// inlined method definitions
379#include "realm/serialize.inl"
380
381#endif // ifndef REALM_SERIALIZE_H
Definition bytearray.h:30
Definition bytearray.h:53
size_t count
Definition serialize.h:188
bool append_bytes(const void *data, size_t datalen)
void * detach_buffer(ptrdiff_t max_wasted_bytes=0)
char * base
Definition serialize.h:166
char * limit
Definition serialize.h:168
char * pos
Definition serialize.h:167
bool append_bytes(const void *data, size_t datalen)
ByteArray detach_bytearray(ptrdiff_t max_wasted_bytes=0)
const void * peek_bytes(size_t datalen)
const char * limit
Definition serialize.h:211
FixedBufferDeserializer(const void *buffer, size_t size)
bool extract_bytes(void *data, size_t datalen)
const char * pos
Definition serialize.h:210
FixedBufferDeserializer(const ByteArrayRef &array)
char * limit
Definition serialize.h:141
bool append_bytes(const void *data, size_t datalen)
char * pos
Definition serialize.h:140
void reset(void *buffer, size_t size)
FixedBufferSerializer(void *buffer, size_t size)
unsigned TypeTag
Definition serialize.h:330
static bool serialize(DynamicBufferSerializer &serializer, const T &obj)
static SubclassMap & get_subclasses(void)
static bool serialize(FixedBufferSerializer &serializer, const T &obj)
static T * deserialize_new(FixedBufferDeserializer &deserializer)
static bool serialize(ByteCountSerializer &serializer, const T &obj)
PolymorphicSerdezHelper< T >::TypeTag tag
Definition serialize.h:359
virtual bool serialize(DynamicBufferSerializer &serializer, const T &obj) const =0
virtual T * deserialize_new(FixedBufferDeserializer &deserializer) const =0
virtual bool serialize(FixedBufferSerializer &serializer, const T &obj) const =0
virtual bool serialize(ByteCountSerializer &serializer, const T &obj) const =0
virtual bool serialize(FixedBufferSerializer &serializer, const T1 &obj) const
virtual bool serialize(DynamicBufferSerializer &serializer, const T1 &obj) const
virtual bool serialize(ByteCountSerializer &serializer, const T1 &obj) const
virtual T1 * deserialize_new(FixedBufferDeserializer &deserializer) const
Definition utils.h:84
Definition serialize.h:82
inner(void)
Definition serialize.h:84
#define REALM_INTERNAL_API_EXTERNAL_LINKAGE
Definition compiler_support.h:218
bool deserialize(S &s, T &t)
Definition serialize.h:225
bool serdez(S &, const T &)
bool serialize(S &s, const T &t)
Definition serialize.h:219
Definition activemsg.h:38
char operator,(const is_copy_serializable::inner &, const T &)
std::map< const char *, const PolymorphicSerdezIntfc< T > * > by_typename
Definition serialize.h:332
std::map< TypeTag, const PolymorphicSerdezIntfc< T > * > by_tag
Definition serialize.h:333
static bool serialize_scalar(S &s, const T &data)
static bool serialize_vector(S &s, const std::vector< T > &v)
static bool deserialize_vector(S &s, std::vector< T > &v)
static bool serialize_span(S &s, span< T, Extent > sp)
static bool deserialize_span(S &s, span< T, Extent > &sp)
static bool serialize_vector(S &s, const std::vector< T > &v)
static bool serialize_scalar(S &s, const T &data)
static bool serialize_span(S &s, span< T, Extent > sp)
static bool deserialize_vector(S &s, std::vector< T > &v)
Definition serialize.h:89
static const bool value
Definition serialize.h:90
Definition serialize.h:80