Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 29 additions & 68 deletions OloEngine/src/OloEngine/Serialization/StreamReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vector>
#include <string>
#include <span>
#include <type_traits>

namespace OloEngine
{
Expand Down Expand Up @@ -53,94 +54,54 @@ namespace OloEngine
T::Deserialize(this, obj);
}

template<typename Key, typename Value>
void ReadMap(std::map<Key, Value>& map, u32 size = 0)
/// @brief Reads any associative container (std::map / std::unordered_map).
/// @note Each key and value is read via ReadElement, mirroring StreamWriter::WriteMap:
/// std::string keys/values come from ReadString, trivially-copyable elements are
/// raw, the rest use their static Deserialize. A size of 0 means "read the u32
/// count first"; pass a non-zero size to skip the prefix.
template<typename Map>
void ReadMap(Map& map, u32 size = 0)
{
if (size == 0)
ReadRaw<u32>(size);

using KeyType = typename Map::key_type;
for (u32 i = 0; i < size; ++i)
{
Key key;
if constexpr (std::is_trivially_copyable_v<Key>)
ReadRaw<Key>(key);
else
ReadObject<Key>(key);

if constexpr (std::is_trivially_copyable_v<Value>)
ReadRaw<Value>(map[key]);
else
ReadObject<Value>(map[key]);
KeyType key;
ReadElement(key);
ReadElement(map[key]);
}
}

template<typename Key, typename Value>
void ReadMap(std::unordered_map<Key, Value>& map, u32 size = 0)
/// @brief Reads a vector. Each element is read via ReadElement (see ReadMap).
/// @note A size of 0 means "read the u32 count first"; pass a non-zero size to skip it.
template<typename T>
void ReadArray(std::vector<T>& array, u32 size = 0)
{
if (size == 0)
ReadRaw<u32>(size);

for (u32 i = 0; i < size; ++i)
{
Key key;
if constexpr (std::is_trivially_copyable_v<Key>)
ReadRaw<Key>(key);
else
ReadObject<Key>(key);

if constexpr (std::is_trivially_copyable_v<Value>)
ReadRaw<Value>(map[key]);
else
ReadObject<Value>(map[key]);
}
}

template<typename Value>
void ReadMap(std::unordered_map<std::string, Value>& map, u32 size = 0)
{
if (size == 0)
ReadRaw<u32>(size);
array.resize(size);

for (u32 i = 0; i < size; ++i)
{
std::string key;
ReadString(key);

if constexpr (std::is_trivially_copyable_v<Value>)
ReadRaw<Value>(map[key]);
else
ReadObject<Value>(map[key]);
}
ReadElement(array[i]);
}

private:
/// @brief Reads a single container element with the right primitive: std::string →
/// ReadString (length-prefixed), trivially-copyable → ReadRaw (raw bytes),
/// otherwise ReadObject (static Deserialize).
template<typename T>
void ReadArray(std::vector<T>& array, u32 size = 0)
void ReadElement(T& element)
{
if (size == 0)
ReadRaw<u32>(size);

array.resize(size);

for (u32 i = 0; i < size; ++i)
{
if constexpr (std::is_trivially_copyable_v<T>)
ReadRaw<T>(array[i]);
else
ReadObject<T>(array[i]);
}
if constexpr (std::is_same_v<T, std::string>)
ReadString(element);
else if constexpr (std::is_trivially_copyable_v<T>)
ReadRaw<T>(element);
else
ReadObject<T>(element);
}
};

template<>
inline void StreamReader::ReadArray(std::vector<std::string>& array, u32 size)
{
if (size == 0)
ReadRaw<u32>(size);

array.resize(size);

for (u32 i = 0; i < size; ++i)
ReadString(array[i]);
}

} // namespace OloEngine
94 changes: 29 additions & 65 deletions OloEngine/src/OloEngine/Serialization/StreamWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <unordered_map>
#include <vector>
#include <string>
#include <type_traits>

namespace OloEngine
{
Expand Down Expand Up @@ -47,87 +48,50 @@ namespace OloEngine
T::Serialize(this, obj);
}

template<typename Key, typename Value>
void WriteMap(const std::map<Key, Value>& map, bool writeSize = true)
/// @brief Writes any associative container (std::map / std::unordered_map).
/// @note Each key and value is written via WriteElement, so std::string keys/values go
/// through WriteString (length-prefixed) while trivially-copyable elements are raw
/// and the rest use their static Serialize. Wire format: optional u32 count, then
/// count × { key, value }.
template<typename Map>
void WriteMap(const Map& map, bool writeSize = true)
{
if (writeSize)
WriteRaw<u32>((u32)map.size());
WriteRaw<u32>(static_cast<u32>(map.size()));

for (const auto& [key, value] : map)
{
if constexpr (std::is_trivially_copyable_v<Key>)
WriteRaw<Key>(key);
else
WriteObject<Key>(key);

if constexpr (std::is_trivially_copyable_v<Value>)
WriteRaw<Value>(value);
else
WriteObject<Value>(value);
WriteElement(key);
WriteElement(value);
}
}

template<typename Key, typename Value>
void WriteMap(const std::unordered_map<Key, Value>& map, bool writeSize = true)
{
if (writeSize)
WriteRaw<u32>((u32)map.size());

for (const auto& [key, value] : map)
{
if constexpr (std::is_trivially_copyable_v<Key>)
WriteRaw<Key>(key);
else
WriteObject<Key>(key);

if constexpr (std::is_trivially_copyable_v<Value>)
WriteRaw<Value>(value);
else
WriteObject<Value>(value);
}
}

template<typename Value>
void WriteMap(const std::unordered_map<std::string, Value>& map, bool writeSize = true)
/// @brief Writes a vector. Each element is written via WriteElement (see WriteMap).
/// @note Wire format: optional u32 count, then count × element.
template<typename T>
void WriteArray(const std::vector<T>& array, bool writeSize = true)
{
if (writeSize)
WriteRaw<u32>((u32)map.size());

for (const auto& [key, value] : map)
{
WriteString(key);
WriteRaw<u32>(static_cast<u32>(array.size()));

if constexpr (std::is_trivially_copyable_v<Value>)
WriteRaw<Value>(value);
else
WriteObject<Value>(value);
}
for (const auto& element : array)
WriteElement(element);
}

private:
/// @brief Writes a single container element with the right primitive: std::string →
/// WriteString (length-prefixed), trivially-copyable → WriteRaw (raw bytes),
/// otherwise WriteObject (static Serialize).
template<typename T>
void WriteArray(const std::vector<T>& array, bool writeSize = true)
void WriteElement(const T& element)
{
if (writeSize)
WriteRaw<u32>((u32)array.size());

for (const auto& element : array)
{
if constexpr (std::is_trivially_copyable_v<T>)
WriteRaw<T>(element);
else
WriteObject<T>(element);
}
if constexpr (std::is_same_v<T, std::string>)
WriteString(element);
else if constexpr (std::is_trivially_copyable_v<T>)
WriteRaw<T>(element);
else
WriteObject<T>(element);
}
};

template<>
inline void StreamWriter::WriteArray(const std::vector<std::string>& array, bool writeSize)
{
if (writeSize)
WriteRaw<u32>((u32)array.size());

for (const auto& element : array)
WriteString(element);
}

} // namespace OloEngine
1 change: 1 addition & 0 deletions OloEngine/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ add_executable(OloEngine-Tests
ShaderGraph/ShaderGraphCommandTest.cpp
# Serialization Tests
Serialization/ArchiveExtensionsTest.cpp
Serialization/StreamHelpersTest.cpp
Serialization/MeshBinarySerializerTest.cpp
Serialization/MeshAssetSerializerTest.cpp
Serialization/SoundGraphSerializerTest.cpp
Expand Down
Loading
Loading