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 "../Foundation/Compiler.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 "Internal/SerializationBinaryBuffer.h"
11#include "Internal/SerializationBinaryReadVersioned.h"
12#include "Internal/SerializationBinaryReadWriteExact.h"
13
14#include "SerializationBinaryOptions.h"
15
16namespace SC
17{
24
27
30{
47
54
55 template <typename T, typename BufferType>
56 [[nodiscard]] static bool write(T& value, BufferType& buffer, size_t* numberOfWrites = nullptr)
57 {
58 SerializationBinaryWriter<BufferType> writer(buffer);
59 using Writer = Serialization::SerializerBinaryReadWriteExact<SerializationBinaryWriter<BufferType>, T>;
60 if (not Writer::serialize(value, writer))
61 return false;
62 if (numberOfWrites)
63 *numberOfWrites = writer.numberOfOperations;
64 return true;
65 }
66
99 template <typename T>
100 [[nodiscard]] static bool loadExact(T& value, Span<const char> buffer, size_t* numberOfReads = nullptr)
101 {
102 SerializationBinaryReader bufferReader(buffer);
103 using Reader = Serialization::SerializerBinaryReadWriteExact<SerializationBinaryReader, T>;
104 if (not Reader::serialize(value, bufferReader))
105 return false;
106 if (numberOfReads)
107 *numberOfReads = bufferReader.numberOfOperations;
108 return bufferReader.positionIsAtEnd();
109 }
110
112 //
144 template <typename T>
145 [[nodiscard]] static bool loadVersioned(T& value, Span<const char> buffer, Span<const Reflection::TypeInfo> schema,
146 SerializationBinaryOptions options = {}, size_t* numberOfReads = nullptr)
147 {
148 SerializationBinaryReader readerBuffer(buffer);
149 using Reader = Serialization::SerializerBinaryReadVersioned<SerializationBinaryReader, T, void>;
150 SerializationSchema versionSchema(schema);
151 versionSchema.options = options;
152 if (not Reader::readVersioned(value, readerBuffer, versionSchema))
153 return false;
154 if (numberOfReads)
155 *numberOfReads = readerBuffer.numberOfOperations;
156 return readerBuffer.positionIsAtEnd();
157 }
158
164 template <typename T, typename BufferType>
165 [[nodiscard]] static bool writeWithSchema(T& value, BufferType& buffer, size_t* numberOfWrites = nullptr)
166 {
167 constexpr auto typeInfos = Reflection::Schema::template compile<T>().typeInfos;
168 constexpr uint32_t numInfos = typeInfos.size;
169 static_assert(alignof(Reflection::TypeInfo) == sizeof(uint32_t), "Alignof TypeInfo");
170 // Implying same endianness when reading here
171 SC_TRY(buffer.append(Span<const char>::reinterpret_bytes(&numInfos, sizeof(numInfos))));
172 SC_TRY(buffer.append(
173 Span<const char>::reinterpret_bytes(typeInfos.values, typeInfos.size * sizeof(Reflection::TypeInfo))));
174 return write(value, buffer, numberOfWrites);
175 }
176
182 template <typename T>
183 [[nodiscard]] static bool loadVersionedWithSchema(T& value, Span<const char> buffer,
184 SerializationBinaryOptions options = {},
185 size_t* numberOfReads = nullptr)
186 {
187 uint32_t numInfos = 0;
188 // Read number of type info
189 Span<const char> numInfosSlice;
190 SC_TRY(buffer.sliceStartLength(0, sizeof(numInfos), numInfosSlice));
191 memcpy(&numInfos, numInfosSlice.data(), sizeof(numInfos));
192
193 // Cast first part of the buffer to a Span of TypeInfo.
194 // It's possible as we've been serializing it with correct alignment (currently 32 bits).
195 static_assert(alignof(Reflection::TypeInfo) == sizeof(uint32_t), "Alignof TypeInfo");
196 Span<const char> typeInfos;
197 SC_TRY(buffer.sliceStartLength(sizeof(numInfos), numInfos * sizeof(Reflection::TypeInfo), typeInfos));
198 Span<const Reflection::TypeInfo> serializedSchema =
199 typeInfos.reinterpret_as_span_of<const Reflection::TypeInfo>();
200
201 constexpr auto sourceSchema = Reflection::Schema::template compile<T>().typeInfos;
202
203 // Get the slice of bytes where actual serialization data has been written by writeWithSchema
204 Span<const char> serializedDataSlice;
205 SC_TRY(buffer.sliceStart(sizeof(numInfos) + numInfos * sizeof(Reflection::TypeInfo), serializedDataSlice));
206 if (sourceSchema.equals(serializedSchema))
207 {
208 // If the serialized schema matches current object schema, we can run the fast "loadExact" path
209 return loadExact(value, serializedDataSlice);
210 }
211 else
212 {
213 // The two schemas differs, so resort to the "slower" versioned loader that tries to match field order
214 return loadVersioned(value, serializedDataSlice, serializedSchema, options, numberOfReads);
215 }
216 }
217};
218
220
221} // namespace SC
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:38
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition Result.h:49
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:30
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:183
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:100
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:165
static bool write(T &value, BufferType &buffer, size_t *numberOfWrites=nullptr)
Writes object T to a binary buffer.
Definition SerializationBinary.h:56
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:145
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
Span< const T > reinterpret_as_span_of() const
Reinterprets the current span as an array of the specified type.
Definition Span.h:84
constexpr bool sliceStart(SizeType offsetInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span, until end.
Definition Span.h:109
constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span of specified length.
Definition Span.h:121