Foundation
Loading...
Searching...
No Matches
Serialization.hpp
Go to the documentation of this file.
1#pragma once
2#include <Core/Container.hpp>
4#include <Core/UUID.hpp>
5#include <concepts>
6#include <cstdint>
7#include <cstring>
8#include <type_traits>
9#if !defined(_WIN32)
10#include <sys/types.h>
11#endif
12using namespace Foundation::Core;
13constexpr uint32_t fourCC(const char a, const char b, const char c, const char d)
14{
15 return (a << 0) | (b << 8) | (c << 16) | (d << 24);
16}
17constexpr uint32_t fourCC(char const str[5])
18{
19 return fourCC(str[0], str[1], str[2], str[3]);
20}
21enum class FBlobCodec : uint32_t
22{
23 None = 0,
24 LZ4 = 1,
25};
27{
28 uint64_t offset{0};
29 uint64_t storedSize{0};
30 uint64_t decodedSize{0};
31 uint32_t count{0};
32 uint32_t stride{0};
34};
35// RW primitives
36struct FWriter
37{
38 virtual ~FWriter() = default;
39 virtual size_t write(const void* data, size_t size) = 0;
40 virtual bool seek(uint64_t offset) { return false; }
41 virtual uint64_t tell() const { return 0; }
42 virtual size_t operator()(const void* data, size_t size) { return write(data, size); }
43};
44struct FReader
45{
46 virtual ~FReader() = default;
47 virtual size_t read(void* dest, size_t size) = 0;
48 virtual bool seek(uint64_t offset) { return false; }
49 virtual uint64_t tell() const { return 0; }
50 virtual size_t operator()(void* dest, size_t size) { return read(dest, size); }
51};
52
54{
56 uint64_t offset{0};
57
58 explicit MemoryWriter(Vector<unsigned char>& data, uint64_t offset = 0);
59
60 size_t write(const void* src, size_t size) override;
61 bool seek(uint64_t offset) override;
62 uint64_t tell() const override { return offset; }
63};
64
66{
68 uint64_t offset{0};
69
70 explicit MemoryReader(Span<const unsigned char> data, uint64_t offset = 0);
71 explicit MemoryReader(Vector<unsigned char> const& data, uint64_t offset = 0);
72
73 size_t read(void* dest, size_t size) override;
74 bool seek(uint64_t offset) override;
75 uint64_t tell() const override { return offset; }
76};
77
79{
81 uint64_t offset{0};
82
83 explicit SpanWriter(Span<unsigned char> data, uint64_t offset = 0);
84
85 size_t write(const void* src, size_t size) override;
86 bool seek(uint64_t offset) override;
87 uint64_t tell() const override { return offset; }
88};
89
90uint64_t AlignUpU64(uint64_t value, uint64_t alignment);
91void EnsureMappedFileSize(MemoryMappedFile& file, uint64_t requiredSize);
92
94{
96 uint64_t& writeOffset;
97 uint64_t baseOffset{0};
99
100 explicit FBlobSerializer(MemoryMappedFile& file, uint64_t& writeOffset, uint64_t baseOffset = 0,
102
103 Span<unsigned char> Allocate(uint64_t size, uint64_t alignment, uint64_t& outPayloadOffset);
104
105 FBlobRef AppendBytes(const void* data, size_t size, uint32_t count, uint32_t stride,
106 FBlobCodec codec = FBlobCodec::None, uint64_t alignment = 16);
107
108 template <typename T>
110 {
111 static_assert(std::is_trivially_copyable_v<T>);
112 CHECK_MSG(values.size() <= UINT32_MAX, "FScene blob count exceeds uint32_t");
113 return AppendBytes(values.data(), values.size() * sizeof(T),
114 static_cast<uint32_t>(values.size()), sizeof(T), codec);
115 }
116};
117
119{
121
123
125 bool ReadBytes(FBlobRef const& blob, void* dst, size_t size, Allocator* scratchAlloc) const;
126
127 template <typename T>
128 bool ReadArray(FBlobRef const& blob, Vector<T>& values, Allocator* scratchAlloc) const
129 {
130 static_assert(std::is_trivially_copyable_v<T>);
131 CHECK(blob.stride == sizeof(T));
132 CHECK_MSG(blob.count <= SIZE_MAX / sizeof(T), "FScene blob count exceeds size_t");
133 values.resize(static_cast<size_t>(blob.count));
134 return ReadBytes(blob, values.data(), values.size() * sizeof(T), scratchAlloc);
135 }
136
137 template <typename T>
138 Vector<T> ReadArray(FBlobRef const& blob, Allocator* alloc = GLOBAL_ALLOC) const
139 {
140 Vector<T> values(alloc);
141 CHECK(ReadArray(blob, values, alloc));
142 return values;
143 }
144};
145
146// In-memory counterpart to FBlobSerializer. FBlobSerializer is the on-disk asset path
147// (MemoryMappedFile-backed, optional LZ4); this one appends trivially-copyable arrays to a
148// caller-owned byte vector and returns matching FBlobRefs, for code that serializes a
149// resource straight into memory and hands it to a consumer that wants a payload + blobs
150// (e.g. GPUScene::Upload in demos/tests). Blobs are stored verbatim (FBlobCodec::None), so
151// the payload reads back without a scratch allocator.
153{
155
160
161 FBlobRef AppendBytes(const void* data, size_t size, uint32_t count, uint32_t stride, uint64_t alignment = 16);
162
163 template <typename T>
164 FBlobRef AppendArray(Vector<T> const& values, uint64_t alignment = 16)
165 {
166 static_assert(std::is_trivially_copyable_v<T>);
167 CHECK_MSG(values.size() <= UINT32_MAX, "Blob count exceeds uint32_t");
168 return AppendBytes(values.data(), values.size() * sizeof(T),
169 static_cast<uint32_t>(values.size()), sizeof(T), alignment);
170 }
171
172 [[nodiscard]] FBlobDeserializer Deserializer() const
173 {
175 }
176};
177
178// Serialize
179template <typename T>
180void FSerialize(FWriter& w, const T& obj);
181template <typename T>
182void FDeserialize(FReader& r, T& obj);
183// POD Data
184template <typename T>
185void FSerialize(FWriter& writer, const T& obj)
186 requires std::is_trivially_copyable_v<T>
187{
188 writer(&obj, sizeof(T));
189}
190template <typename T>
191void FDeserialize(FReader& reader, T& obj)
192 requires std::is_trivially_copyable_v<T>
193{
194 reader(&obj, sizeof(T));
195}
196// Length-prefixed UTF-8 string.
197inline void FSerialize(FWriter& writer, String const& str)
198{
199 uint64_t count = str.size();
200 writer(&count, sizeof(uint64_t));
201 if (count)
202 writer(str.data(), static_cast<size_t>(count));
203}
204inline void FDeserialize(FReader& reader, String& str)
205{
206 uint64_t count = 0;
207 reader(&count, sizeof(uint64_t));
208 str.clear();
209 str.resize(static_cast<size_t>(count));
210 if (count)
211 CHECK(reader.read(str.data(), static_cast<size_t>(count)) == static_cast<size_t>(count));
212}
213// Custom serialization
214template <typename T>
215void FSerialize(FWriter& writer, const Vector<T>& vec)
216{
217 uint64_t count = vec.size();
218 writer(&count, sizeof(uint64_t));
219 if constexpr (std::is_trivially_copyable_v<T>)
220 writer(vec.data(), count * sizeof(T));
221 else
222 {
223 for (const auto& item : vec)
224 FSerialize(writer, item);
225 }
226}
227template <typename T, typename... Args>
228void FDeserialize(FReader& reader, Vector<T>& vec, Args const&... args)
229{
230 uint64_t count = 0;
231 reader(&count, sizeof(uint64_t));
232 CHECK_MSG(count <= SIZE_MAX, "Vector is too large for this platform");
233 vec.clear();
234 vec.reserve(static_cast<size_t>(count));
235 if constexpr (std::is_trivially_copyable_v<T> && sizeof...(Args) == 0)
236 {
237 vec.resize(static_cast<size_t>(count));
238 reader(vec.data(), static_cast<size_t>(count) * sizeof(T));
239 }
240 else
241 {
242 for (size_t i = 0; i < static_cast<size_t>(count); i++)
243 {
244 T& item = vec.emplace_back(args...);
245 FDeserialize(reader, item);
246 }
247 }
248}
249// Optional<T>
250template <typename T>
251void FSerialize(FWriter& writer, const Optional<T>& opt)
252{
253 uint8_t hasValue = opt.has_value() ? 1 : 0;
254 FSerialize(writer, hasValue);
255 if (hasValue)
256 FSerialize(writer, *opt);
257}
258template <typename T, typename... Args>
259void FDeserialize(FReader& reader, Optional<T>& opt, Args const&... args)
260{
261 uint8_t hasValue = 0;
262 FDeserialize(reader, hasValue);
263 if (hasValue)
264 {
265 opt.emplace(args...);
266 FDeserialize(reader, *opt);
267 }
268 else
269 {
270 opt = std::nullopt;
271 }
272}
#define CHECK_MSG(expr, format_str,...)
#define GLOBAL_ALLOC
Definition Allocator.hpp:240
#define CHECK(expr)
Definition Logging.hpp:92
void EnsureMappedFileSize(MemoryMappedFile &file, uint64_t requiredSize)
Definition Serialization.cpp:77
FBlobCodec
Definition Serialization.hpp:22
uint64_t AlignUpU64(uint64_t value, uint64_t alignment)
Definition Serialization.cpp:7
void FDeserialize(FReader &r, T &obj)
Definition Serialization.hpp:191
constexpr uint32_t fourCC(const char a, const char b, const char c, const char d)
Definition Serialization.hpp:13
void FSerialize(FWriter &w, const T &obj)
Definition Serialization.hpp:185
Allocator interface (noexcept)
Definition Allocator.hpp:29
Definition MemoryMapped.hpp:15
Lock-free atomic primitives and implementations of data structures.
Definition Allocator.hpp:6
std::vector< T, StlAllocator< T > > Vector
std::vector with explicit Foundation::Core::StlAllocator constructor
Definition Container.hpp:149
std::basic_string< char, std::char_traits< char >, StlDefaultAllocator< char > > String
Alias for std::basic_string<char>, without an explicit allocator constructor.
Definition Container.hpp:120
std::span< T > Span
Alias for std::span
Definition Container.hpp:62
Definition Serialization.hpp:119
Span< const unsigned char > payload
Definition Serialization.hpp:120
bool ReadBytes(FBlobRef const &blob, void *dst, size_t size, Allocator *scratchAlloc) const
Definition Serialization.cpp:230
Span< const unsigned char > StoredBytes(FBlobRef const &blob) const
Definition Serialization.cpp:223
Vector< T > ReadArray(FBlobRef const &blob, Allocator *alloc=GLOBAL_ALLOC) const
Definition Serialization.hpp:138
bool ReadArray(FBlobRef const &blob, Vector< T > &values, Allocator *scratchAlloc) const
Definition Serialization.hpp:128
Definition Serialization.hpp:27
uint32_t stride
Definition Serialization.hpp:32
uint64_t decodedSize
Definition Serialization.hpp:30
uint64_t offset
Definition Serialization.hpp:28
uint32_t count
Definition Serialization.hpp:31
uint64_t storedSize
Definition Serialization.hpp:29
FBlobCodec codec
Definition Serialization.hpp:33
Definition Serialization.hpp:94
Allocator * scratchAlloc
Definition Serialization.hpp:98
FBlobRef AppendArray(Vector< T > const &values, FBlobCodec codec=FBlobCodec::None)
Definition Serialization.hpp:109
uint64_t baseOffset
Definition Serialization.hpp:97
Span< unsigned char > Allocate(uint64_t size, uint64_t alignment, uint64_t &outPayloadOffset)
Definition Serialization.cpp:129
MemoryMappedFile & file
Definition Serialization.hpp:95
FBlobRef AppendBytes(const void *data, size_t size, uint32_t count, uint32_t stride, FBlobCodec codec=FBlobCodec::None, uint64_t alignment=16)
Definition Serialization.cpp:149
uint64_t & writeOffset
Definition Serialization.hpp:96
Definition Serialization.hpp:45
virtual ~FReader()=default
virtual uint64_t tell() const
Definition Serialization.hpp:49
virtual bool seek(uint64_t offset)
Definition Serialization.hpp:48
virtual size_t operator()(void *dest, size_t size)
Definition Serialization.hpp:50
virtual size_t read(void *dest, size_t size)=0
Definition Serialization.hpp:37
virtual size_t write(const void *data, size_t size)=0
virtual uint64_t tell() const
Definition Serialization.hpp:41
virtual bool seek(uint64_t offset)
Definition Serialization.hpp:40
virtual ~FWriter()=default
virtual size_t operator()(const void *data, size_t size)
Definition Serialization.hpp:42
std::optional with convenience Get()/GetIf() methods.
Definition Container.hpp:256
Definition Serialization.hpp:153
MemoryBlobSerializer(Vector< unsigned char > &payload)
Definition Serialization.hpp:156
FBlobDeserializer Deserializer() const
Definition Serialization.hpp:172
FBlobRef AppendBytes(const void *data, size_t size, uint32_t count, uint32_t stride, uint64_t alignment=16)
Definition Serialization.cpp:192
Vector< unsigned char > & payload
Definition Serialization.hpp:154
FBlobRef AppendArray(Vector< T > const &values, uint64_t alignment=16)
Definition Serialization.hpp:164
Definition Serialization.hpp:66
Span< const unsigned char > data
Definition Serialization.hpp:67
size_t read(void *dest, size_t size) override
Definition Serialization.cpp:54
uint64_t tell() const override
Definition Serialization.hpp:75
uint64_t offset
Definition Serialization.hpp:68
bool seek(uint64_t offset) override
Definition Serialization.cpp:69
Definition Serialization.hpp:54
bool seek(uint64_t offset) override
Definition Serialization.cpp:36
size_t write(const void *src, size_t size) override
Definition Serialization.cpp:19
Vector< unsigned char > & data
Definition Serialization.hpp:55
uint64_t tell() const override
Definition Serialization.hpp:62
uint64_t offset
Definition Serialization.hpp:56
Definition Serialization.hpp:79
Span< unsigned char > data
Definition Serialization.hpp:80
size_t write(const void *src, size_t size) override
Definition Serialization.cpp:98
uint64_t offset
Definition Serialization.hpp:81
bool seek(uint64_t offset) override
Definition Serialization.cpp:112
uint64_t tell() const override
Definition Serialization.hpp:87