Skip to content

Commit

Permalink
Add serialization support for Array<T, Count> types. (#73)
Browse files Browse the repository at this point in the history
[Runtime]Add serialization support for `Array<T, Count>` types.
  • Loading branch information
JX-Master authored Sep 4, 2024
1 parent a8bccdf commit 0ba4111
Show file tree
Hide file tree
Showing 10 changed files with 429 additions and 77 deletions.
8 changes: 8 additions & 0 deletions Modules/Luna/Asset/Asset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,4 +358,12 @@ namespace Luna

struct Module;
LUNA_ASSET_API Module* module_asset();

template <> struct hash<Asset::asset_t>
{
usize operator()(Asset::asset_t val) const
{
return (usize)val.handle;
}
};
}
22 changes: 22 additions & 0 deletions Modules/Luna/Runtime/Array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "Algorithm.hpp"
#include "Memory.hpp"
#include "MemoryUtils.hpp"
#include "TypeInfo.hpp"

namespace Luna
{
Expand Down Expand Up @@ -381,5 +382,26 @@ namespace Luna
usize m_size;
};

//! Gets the type object of @ref Array.
//! @return Returns the type object of @ref Array. The returned type is a generic type that can be
//! instantiated by providing the element type.
LUNA_RUNTIME_API typeinfo_t array_type();

template <typename _Ty, usize _Size>
struct typeof_t<Array<_Ty, _Size>>
{
typeinfo_t operator()() const
{
if(_Size == DYNAMIC_ARRAY_SIZE)
{
return get_generic_instanced_type(array_type(), { typeof<_Ty>() });
}
else
{
return get_generic_instanced_type(array_type(), { typeof<_Ty>(), (i64)(_Size) });
}
}
};

//! @}
}
4 changes: 2 additions & 2 deletions Modules/Luna/Runtime/Reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ namespace Luna
//! required.
//! @param[in] generic_type The generic type to instantiate.
//! @param[in] generic_arguments Types that are used as arguments to instantiate one generic structure instanced type.
using generic_structure_instantiate_t = GenericStructureInstantiateInfo(typeinfo_t generic_type, Span<const typeinfo_t> generic_arguments);
using generic_structure_instantiate_t = GenericStructureInstantiateInfo(typeinfo_t generic_type, Span<const GenericArgument> generic_arguments);

//! Describes one generic structure type.
struct GenericStructureTypeDesc
Expand Down Expand Up @@ -792,7 +792,7 @@ namespace Luna
//! Returns one empty span if `type` is not a generic structure instanced type.
//! @par Valid Usage
//! * `type` must specify one valid type object.
LUNA_RUNTIME_API Span<const typeinfo_t> get_struct_generic_arguments(typeinfo_t type);
LUNA_RUNTIME_API Span<const GenericArgument> get_struct_generic_arguments(typeinfo_t type);

//! Gets the generic parameter names of the specified type.
//! @param[in] type The type to query.
Expand Down
2 changes: 1 addition & 1 deletion Modules/Luna/Runtime/Serialization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,4 @@ namespace Luna
}

//! @}
}
}
340 changes: 281 additions & 59 deletions Modules/Luna/Runtime/Source/BuiltInTypeInfo.cpp

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Modules/Luna/Runtime/Source/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,13 @@ namespace Luna
LUNA_RUNTIME_API R<Variant> serialize(typeinfo_t type, const void* inst)
{
SerializableTypeDesc* d = (SerializableTypeDesc*)get_type_private_data(type, serialization_data_guid);
if (!d) return BasicError::not_supported();
if (!d) return set_error(BasicError::not_supported(), "Type %s is not serializable.", get_type_name(type).c_str());
return d->serialize_func(type, inst);
}
LUNA_RUNTIME_API RV deserialize(typeinfo_t type, void* inst, const Variant& data)
{
SerializableTypeDesc* d = (SerializableTypeDesc*)get_type_private_data(type, serialization_data_guid);
if (!d) return BasicError::not_supported();
if (!d) return set_error(BasicError::not_supported(), "Type %s is not serializable.", get_type_name(type).c_str());
return d->deserialize_func(type, inst, data);
}
}
22 changes: 11 additions & 11 deletions Modules/Luna/Runtime/Source/TypeInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ namespace Luna
return (typeinfo_t)et;
}

inline bool generic_arguments_equal(const typeinfo_t* lhs_generic_arguments, usize lhs_num_generic_arguments,
const typeinfo_t* rhs_generic_arguments, usize rhs_num_generic_arguments)
inline bool generic_arguments_equal(const GenericArgument* lhs_generic_arguments, usize lhs_num_generic_arguments,
const GenericArgument* rhs_generic_arguments, usize rhs_num_generic_arguments)
{
if (lhs_num_generic_arguments != rhs_num_generic_arguments) return false;
for (usize i = 0; i < lhs_num_generic_arguments; ++i)
Expand All @@ -308,7 +308,7 @@ namespace Luna
return true;
}

static typeinfo_t new_instanced_type(GenericStructureTypeInfo* generic_type, Span<const typeinfo_t> generic_arguments)
static typeinfo_t new_instanced_type(GenericStructureTypeInfo* generic_type, Span<const GenericArgument> generic_arguments)
{
UniquePtr<TypeInfo> t(memnew<GenericStructureInstancedTypeInfo>());
auto gt = (GenericStructureInstancedTypeInfo*)t.get();
Expand Down Expand Up @@ -375,7 +375,7 @@ namespace Luna
if (iter == g_type_guid_map.end()) return nullptr;
return (typeinfo_t)(iter->second);
}
LUNA_RUNTIME_API typeinfo_t get_generic_instanced_type(typeinfo_t generic_type, Span<const typeinfo_t> generic_arguments)
LUNA_RUNTIME_API typeinfo_t get_generic_instanced_type(typeinfo_t generic_type, Span<const GenericArgument> generic_arguments)
{
OSMutexGuard guard(g_type_registry_lock);
if (((TypeInfo*)generic_type)->kind != TypeKind::generic_structure) return nullptr;
Expand Down Expand Up @@ -458,23 +458,23 @@ namespace Luna
}
return nullptr;
}
LUNA_RUNTIME_API Span<const typeinfo_t> get_struct_generic_arguments(typeinfo_t type)
LUNA_RUNTIME_API Span<const GenericArgument> get_struct_generic_arguments(typeinfo_t type)
{
TypeInfo* t = (TypeInfo*)type;
switch (t->kind)
{
case TypeKind::generic_structure_instanced:
{
GenericStructureInstancedTypeInfo* src = ((GenericStructureInstancedTypeInfo*)t);
return Span<const typeinfo_t>(src->generic_arguments.data(), src->generic_arguments.size());
return Span<const GenericArgument>(src->generic_arguments.data(), src->generic_arguments.size());
}
case TypeKind::primitive: return Span<const typeinfo_t>();
case TypeKind::structure: return Span<const typeinfo_t>();
case TypeKind::enumeration: return Span<const typeinfo_t>();
case TypeKind::generic_structure: return Span<const typeinfo_t>();
case TypeKind::primitive: return Span<const GenericArgument>();
case TypeKind::structure: return Span<const GenericArgument>();
case TypeKind::enumeration: return Span<const GenericArgument>();
case TypeKind::generic_structure: return Span<const GenericArgument>();
default: lupanic();
}
return Span<const typeinfo_t>();
return Span<const GenericArgument>();
}
LUNA_RUNTIME_API usize count_struct_generic_parameters(typeinfo_t type)
{
Expand Down
2 changes: 1 addition & 1 deletion Modules/Luna/Runtime/Source/TypeInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ namespace Luna
struct GenericStructureInstancedTypeInfo : public TypeInfo
{
GenericStructureTypeInfo* generic_type;
Array<typeinfo_t> generic_arguments;
Array<GenericArgument> generic_arguments;
usize size;
usize alignment;
TypeInfo* base_type;
Expand Down
56 changes: 55 additions & 1 deletion Modules/Luna/Runtime/TypeInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,66 @@ namespace Luna
LUNA_RUNTIME_API typeinfo_t pair_type();
template <typename _Ty1, typename _Ty2> struct typeof_t<Pair<_Ty1, _Ty2>>
{ typeinfo_t operator()() const { return get_generic_instanced_type(pair_type(), {typeof<_Ty1>(), typeof<_Ty2>()}); } };

//! Specifies the type of one generic argument.
enum class GenericArgumentType : u8
{
//! This argument is not set.
none = 0,
//! This argument is a type.
type = 1,
//! This argument is a integer.
integer = 2,
};

//! Specifies one generic argument.
struct GenericArgument
{
//! The type of the argument.
GenericArgumentType argument_type;
union
{
//! The value of the argument if argument is a type.
typeinfo_t type;
//! The value of the argument if argument is an integer.
i64 integer;
};

GenericArgument() :
argument_type(GenericArgumentType::none),
type(nullptr) {}
GenericArgument(typeinfo_t type) :
argument_type(GenericArgumentType::type),
type(type) {}
GenericArgument(i64 integer) :
argument_type(GenericArgumentType::integer),
integer(integer) {}
GenericArgument(const GenericArgument&) = default;
GenericArgument(GenericArgument&&) = default;
GenericArgument& operator=(const GenericArgument&) = default;
GenericArgument& operator=(GenericArgument&&) = default;
bool operator==(const GenericArgument& rhs) const
{
if(argument_type != rhs.argument_type) return false;
switch(argument_type)
{
case GenericArgumentType::type: return type == rhs.type;
case GenericArgumentType::integer: return integer == rhs.integer;
default: lupanic();
}
return false;
}
bool operator!=(const GenericArgument& rhs) const
{
return !(*this == rhs);
}
};

//! Gets one instanced type of one generic type.
//! @param[in] generic_type The generic type.
//! @param[in] generic_arguments The type arguments that are used to query the instanced type.
//! @return Returns the instanced type requested.
LUNA_RUNTIME_API typeinfo_t get_generic_instanced_type(typeinfo_t generic_type, Span<const typeinfo_t> generic_arguments);
LUNA_RUNTIME_API typeinfo_t get_generic_instanced_type(typeinfo_t generic_type, Span<const GenericArgument> generic_arguments);

template <typename _Ty>
struct EnumTypeInfo {};
Expand Down
46 changes: 46 additions & 0 deletions Tests/RuntimeTest/Source/SerializeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <Luna/Runtime/Serialization.hpp>
#include <Luna/Runtime/HashMap.hpp>
#include <Luna/Runtime/Tuple.hpp>
#include <Luna/Runtime/Array.hpp>

namespace Luna
{
Expand Down Expand Up @@ -88,5 +89,50 @@ namespace Luna
lutest(v1[i] == v2[i]);
}
}

{
Array<i32> arr1 = { 1, 4, 2, 5, 3, 8, 6, 9, 0 };
Variant var = serialize(arr1).get();
Array<i32> arr2;
lupanic_if_failed(deserialize(arr2, var));
lutest(arr1.size() == arr2.size());
for (usize i = 0; i < arr1.size(); ++i)
{
lutest(arr1[i] == arr2[i]);
}
}

{
Array<i32, 9> arr1;
arr1[0] = 1;
arr1[1] = 4;
arr1[2] = 2;
arr1[3] = 5;
arr1[4] = 3;
arr1[5] = 8;
arr1[6] = 6;
arr1[7] = 9;
arr1[8] = 0;
Variant var = serialize(arr1).get();
Array<i32, 9> arr2;
lupanic_if_failed(deserialize(arr2, var));
lutest(arr1.size() == arr2.size());
for (usize i = 0; i < arr1.size(); ++i)
{
lutest(arr1[i] == arr2[i]);
}
}

{
Array<i32> arr1 = { 1, 4, 2, 5, 3, 8, 6, 9, 0 };
Variant var = serialize(arr1).get();
Array<i32, 9> arr2;
lupanic_if_failed(deserialize(arr2, var));
lutest(arr1.size() == arr2.size());
for (usize i = 0; i < arr1.size(); ++i)
{
lutest(arr1[i] == arr2[i]);
}
}
}
}

0 comments on commit 0ba4111

Please sign in to comment.