Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SerializationBinary.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Common/CompilerMacrosExport.h"
5#ifndef SC_EXPORT_LIBRARY_SERIALIZATION_BINARY
6#define SC_EXPORT_LIBRARY_SERIALIZATION_BINARY 0
7#endif
8#define SC_SERIALIZATION_BINARY_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_SERIALIZATION_BINARY)
9
10#include "../Common/Assert.h"
11
12namespace SC
13{
14SC_DECLARE_ASSERT_PROVIDER(SerializationBinaryAssert, SC_SERIALIZATION_BINARY_EXPORT);
15
16#define SC_SERIALIZATION_BINARY_ASSERT_RELEASE(e) SC_ASSERT_PROVIDER_RELEASE(SC::SerializationBinaryAssert, e)
17#define SC_SERIALIZATION_BINARY_ASSERT_DEBUG(e) SC_ASSERT_PROVIDER_DEBUG(SC::SerializationBinaryAssert, e)
18#define SC_SERIALIZATION_BINARY_TRUST_RESULT(expression) SC_SERIALIZATION_BINARY_ASSERT_RELEASE(expression)
19} // namespace SC
20
21#include "Internal/SerializationBinaryBuffer.h"
22#include "Internal/SerializationBinaryReadVersioned.h"
23#include "Internal/SerializationBinaryReadWriteExact.h"
24
25#include "SerializationBinaryOptions.h"
26
27namespace SC
28{
35
38
41{
58
65
66 template <typename T, typename BufferType>
67 [[nodiscard]] static bool write(T& value, BufferType& buffer, size_t* numberOfWrites = nullptr)
68 {
69 SerializationBinaryWriter<BufferType> writer(buffer);
70 using Writer = Serialization::SerializerBinaryReadWriteExact<SerializationBinaryWriter<BufferType>, T>;
71 if (not Writer::serialize(value, writer))
72 return false;
73 if (numberOfWrites)
74 *numberOfWrites = writer.numberOfOperations;
75 return true;
76 }
77
111 template <typename T>
112 [[nodiscard]] static bool loadExact(T& value, Span<const char> buffer, size_t* numberOfReads = nullptr)
113 {
114 SerializationBinaryReader bufferReader(buffer);
115 using Reader = Serialization::SerializerBinaryReadWriteExact<SerializationBinaryReader, T>;
116 if (not Reader::serialize(value, bufferReader))
117 return false;
118 if (numberOfReads)
119 *numberOfReads = bufferReader.numberOfOperations;
120 return bufferReader.positionIsAtEnd();
121 }
122
124 //
156 template <typename T>
157 [[nodiscard]] static bool loadVersioned(T& value, Span<const char> buffer, Span<const Reflection::TypeInfo> schema,
158 SerializationBinaryOptions options = {}, size_t* numberOfReads = nullptr)
159 {
160 SerializationBinaryReader readerBuffer(buffer);
161 using Reader = Serialization::SerializerBinaryReadVersioned<SerializationBinaryReader, T, void>;
162 SerializationSchema versionSchema(schema);
163 versionSchema.options = options;
164 if (not Reader::readVersioned(value, readerBuffer, versionSchema))
165 return false;
166 if (numberOfReads)
167 *numberOfReads = readerBuffer.numberOfOperations;
168 return readerBuffer.positionIsAtEnd();
169 }
170
176 template <typename T, typename BufferType>
177 [[nodiscard]] static bool writeWithSchema(T& value, BufferType& buffer, size_t* numberOfWrites = nullptr)
178 {
179 constexpr auto typeInfos = Reflection::Schema::template compile<T>().typeInfos;
180 constexpr uint32_t numInfos = typeInfos.size;
181 static_assert(alignof(Reflection::TypeInfo) == sizeof(uint32_t), "Alignof TypeInfo");
182 // Implying same endianness when reading here
183 SC_TRY(buffer.append(Span<const char>::reinterpret_bytes(&numInfos, sizeof(numInfos))));
184 SC_TRY(buffer.append(
185 Span<const char>::reinterpret_bytes(typeInfos.values, typeInfos.size * sizeof(Reflection::TypeInfo))));
186 return write(value, buffer, numberOfWrites);
187 }
188
194 template <typename T>
195 [[nodiscard]] static bool loadVersionedWithSchema(T& value, Span<const char> buffer,
196 SerializationBinaryOptions options = {},
197 size_t* numberOfReads = nullptr)
198 {
199 uint32_t numInfos = 0;
200 // Read number of type info
201 Span<const char> numInfosSlice;
202 SC_TRY(buffer.sliceStartLength(0, sizeof(numInfos), numInfosSlice));
203#if SC_COMPILER_MSVC
204 ::memcpy(&numInfos, numInfosSlice.data(), sizeof(numInfos));
205#else
206 __builtin_memcpy(&numInfos, numInfosSlice.data(), sizeof(numInfos));
207#endif
208
209 // Cast first part of the buffer to a Span of TypeInfo.
210 // It's possible as we've been serializing it with correct alignment (currently 32 bits).
211 static_assert(alignof(Reflection::TypeInfo) == sizeof(uint32_t), "Alignof TypeInfo");
212 Span<const char> typeInfos;
213 SC_TRY(buffer.sliceStartLength(sizeof(numInfos), numInfos * sizeof(Reflection::TypeInfo), typeInfos));
214 Span<const Reflection::TypeInfo> serializedSchema =
215 typeInfos.reinterpret_as_span_of<const Reflection::TypeInfo>();
216
217 constexpr auto sourceSchema = Reflection::Schema::template compile<T>().typeInfos;
218
219 // Get the slice of bytes where actual serialization data has been written by writeWithSchema
220 Span<const char> serializedDataSlice;
221 SC_TRY(buffer.sliceStart(sizeof(numInfos) + numInfos * sizeof(Reflection::TypeInfo), serializedDataSlice));
222 if (sourceSchema.equals(serializedSchema))
223 {
224 // If the serialized schema matches current object schema, we can run the fast "loadExact" path
225 return loadExact(value, serializedDataSlice);
226 }
227 else
228 {
229 // The two schemas differs, so resort to the "slower" versioned loader that tries to match field order
230 return loadVersioned(value, serializedDataSlice, serializedSchema, options, numberOfReads);
231 }
232 }
233};
234
236
237} // namespace SC
Conversion options for the binary versioned deserializer.
Definition SerializationBinaryOptions.h:12
Loads or writes binary data with its associated reflection schema from or into a C++ object.
Definition SerializationBinary.h:41
static bool loadVersionedWithSchema(T &value, Span< const char > buffer, SerializationBinaryOptions options={}, size_t *numberOfReads=nullptr)
Loads object T using the schema information that has been prepended by SerializationBinary::writeWith...
Definition SerializationBinary.h:195
static bool loadExact(T &value, Span< const char > buffer, size_t *numberOfReads=nullptr)
Loads object T from binary buffer as written by SerializationBinary::write.
Definition SerializationBinary.h:112
static bool writeWithSchema(T &value, BufferType &buffer, size_t *numberOfWrites=nullptr)
Writes the reflection schema of object T followed by contents of object T to a binary buffer.
Definition SerializationBinary.h:177
static bool write(T &value, BufferType &buffer, size_t *numberOfWrites=nullptr)
Writes object T to a binary buffer.
Definition SerializationBinary.h:67
static bool loadVersioned(T &value, Span< const char > buffer, Span< const Reflection::TypeInfo > schema, SerializationBinaryOptions options={}, size_t *numberOfReads=nullptr)
Deserialize object T from a Binary buffer with a reflection schema not matching T schema.
Definition SerializationBinary.h:157