Sane C++ Libraries
C++ Platform Abstraction Libraries
SerializationBinary.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "Internal/SerializationBinaryBuffer.h"
5#include "Internal/SerializationBinaryReadVersioned.h"
6#include "Internal/SerializationBinaryReadWriteExact.h"
7
8#include "SerializationBinaryOptions.h"
9
10namespace SC
11{
18
21
24{
41
49 template <typename T>
50 [[nodiscard]] static bool write(T& value, Buffer& buffer, size_t* numberOfWrites = nullptr)
51 {
52 SerializationBinaryBufferWriter writer(buffer);
53 using Writer = Serialization::SerializerBinaryReadWriteExact<SerializationBinaryBufferWriter, T>;
54 if (not Writer::serialize(value, writer))
55 return false;
56 if (numberOfWrites)
57 *numberOfWrites = writer.numberOfOperations;
58 return true;
59 }
60
76
95 template <typename T>
96 [[nodiscard]] static bool loadExact(T& value, Span<const char> buffer, size_t* numberOfReads = nullptr)
97 {
98 SerializationBinaryBufferReader bufferReader(buffer);
99 using Reader = Serialization::SerializerBinaryReadWriteExact<SerializationBinaryBufferReader, T>;
100 if (not Reader::serialize(value, bufferReader))
101 return false;
102 if (numberOfReads)
103 *numberOfReads = bufferReader.numberOfOperations;
104 return bufferReader.positionIsAtEnd();
105 }
106
108 //
127
142 template <typename T>
143 [[nodiscard]] static bool loadVersioned(T& value, Span<const char> buffer, Span<const Reflection::TypeInfo> schema,
144 SerializationBinaryOptions options = {}, size_t* numberOfReads = nullptr)
145 {
146 SerializationBinaryBufferReader readerBuffer(buffer);
147 using Reader = Serialization::SerializerBinaryReadVersioned<SerializationBinaryBufferReader, T>;
148 SerializationSchema versionSchema(schema);
149 versionSchema.options = options;
150 if (not Reader::readVersioned(value, readerBuffer, versionSchema))
151 return false;
152 if (numberOfReads)
153 *numberOfReads = readerBuffer.numberOfOperations;
154 return readerBuffer.positionIsAtEnd();
155 }
156
162 template <typename T>
163 [[nodiscard]] static bool writeWithSchema(T& value, Buffer& buffer, size_t* numberOfWrites = nullptr)
164 {
165 constexpr auto typeInfos = Reflection::Schema::template compile<T>().typeInfos;
166 constexpr uint32_t numInfos = typeInfos.size;
167 static_assert(alignof(Reflection::TypeInfo) == sizeof(uint32_t), "Alignof TypeInfo");
168 // Implying same endianness when reading here
169 SC_TRY(buffer.append(Span<const char>::reinterpret_bytes(&numInfos, sizeof(numInfos))));
170 SC_TRY(buffer.append(
171 Span<const char>::reinterpret_bytes(typeInfos.values, typeInfos.size * sizeof(Reflection::TypeInfo))));
172 return write(value, buffer, numberOfWrites);
173 }
174
180 template <typename T>
181 [[nodiscard]] static bool loadVersionedWithSchema(T& value, Span<const char> buffer,
182 SerializationBinaryOptions options = {},
183 size_t* numberOfReads = nullptr)
184 {
185 uint32_t numInfos = 0;
186 // Read number of type info
187 Span<const char> numInfosSlice;
188 SC_TRY(buffer.sliceStartLength(0, sizeof(numInfos), numInfosSlice));
189 memcpy(&numInfos, numInfosSlice.data(), sizeof(numInfos));
190
191 // Cast first part of the buffer to a Span of TypeInfo.
192 // It's possible as we've been serializing it with correct alignment (currently 32 bits).
193 static_assert(alignof(Reflection::TypeInfo) == sizeof(uint32_t), "Alignof TypeInfo");
194 Span<const char> typeInfos;
195 SC_TRY(buffer.sliceStartLength(sizeof(numInfos), numInfos * sizeof(Reflection::TypeInfo), typeInfos));
196 Span<const Reflection::TypeInfo> serializedSchema =
198
199 constexpr auto sourceSchema = Reflection::Schema::template compile<T>().typeInfos;
200
201 // Get the slice of bytes where actual serialization data has been written by writeWithSchema
202 Span<const char> serializedDataSlice;
203 SC_TRY(buffer.sliceStart(sizeof(numInfos) + numInfos * sizeof(Reflection::TypeInfo), serializedDataSlice));
204 if (sourceSchema.equals(serializedSchema))
205 {
206 // If the serialized schema matches current object schema, we can run the fast "loadExact" path
207 return loadExact(value, serializedDataSlice);
208 }
209 else
210 {
211 // The two schemas differs, so resort to the "slower" versioned loader that tries to match field order
212 return loadVersioned(value, serializedDataSlice, serializedSchema, options, numberOfReads);
213 }
214 }
215};
216
218
219} // 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:48
An heap allocated byte buffer that can optionally use an inline buffer.
Definition: Buffer.h:25
[reflectionSnippet3]
Definition: Reflection.h:64
bool append(Span< const T > span)
Appends a Span to the end of the segment.
Loads or writes binary data with its associated reflection schema from or into a C++ object.
Definition: SerializationBinary.h:24
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:181
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:96
static bool write(T &value, Buffer &buffer, size_t *numberOfWrites=nullptr)
Writes object T to a binary buffer.
Definition: SerializationBinary.h:50
static bool writeWithSchema(T &value, Buffer &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:163
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:143
Conversion options for the binary versioned deserializer.
Definition: SerializationBinaryOptions.h:12
View over a contiguous sequence of items (pointer + size in elements).
Definition: Span.h:24
constexpr const Type * data() const
Returns pointer to first element of the span.
Definition: Span.h:99
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:127
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:144
Span< const T > reinterpret_as_array_of() const
Reinterprets the current span as an array of the specified type.
Definition: Span.h:77