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