Skip to content

Commit

Permalink
Introduce Serializer updateEntity and loadEntity
Browse files Browse the repository at this point in the history
Linked: #150
  • Loading branch information
AndreasLrx committed Jul 16, 2024
1 parent 913eba1 commit 3ce576f
Show file tree
Hide file tree
Showing 16 changed files with 521 additions and 46 deletions.
163 changes: 154 additions & 9 deletions src/ecstasy/serialization/ComponentSerializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
#include "ecstasy/config.hpp"
#include "ecstasy/serialization/RawSerializer.hpp"
#include "util/meta/Traits.hpp"
#include "ecstasy/serialization/traits/can_load_type.hpp"
#include "ecstasy/serialization/traits/can_save_type.hpp"
#include "ecstasy/serialization/traits/can_update_type.hpp"

#ifndef ECSTASY_SERIALIZERS
#define ECSTASY_SERIALIZERS util::meta::Traits<ecstasy::serialization::RawSerializer>
Expand Down Expand Up @@ -48,9 +50,9 @@ namespace ecstasy::serialization
template <typename S1, typename... Ss>
struct ComponentSerializer<util::meta::Traits<S1, Ss...>> {
///
/// @brief Serialize a component with the given serializer.
/// @brief Save a component with the given serializer.
///
/// @note This function will try to serialize the component with each serializer in the list, stopping when the
/// @note This function will try to save the component with each serializer in the list, stopping when the
/// targeted serializer is found (using @p stype).
///
/// @tparam Comp Component type.
Expand All @@ -65,14 +67,14 @@ namespace ecstasy::serialization
/// @since 1.0.0 (2024-06-11)
///
template <typename Comp>
static ISerializer &serialize(ISerializer &serializer, const std::type_info &stype, const Comp &component)
static ISerializer &save(ISerializer &serializer, const std::type_info &stype, const Comp &component)
{
(trySerialize<S1>(serializer, stype, component) || ... || trySerialize<Ss>(serializer, stype, component));
(trySave<S1>(serializer, stype, component) || ... || trySave<Ss>(serializer, stype, component));
return serializer;
}

///
/// @brief Try to serialize a component with the given serializer. The serialization is done if S is the same as
/// @brief Try to save a component with the given serializer. The serialization is done if S is the same as
/// @p stype.
///
/// @tparam S Serializer type.
Expand All @@ -88,7 +90,7 @@ namespace ecstasy::serialization
/// @since 1.0.0 (2024-06-11)
///
template <typename S, typename Comp>
static bool trySerialize(ISerializer &serializer, const std::type_info &stype, const Comp &component)
static bool trySave(ISerializer &serializer, const std::type_info &stype, const Comp &component)
{
if constexpr (traits::can_save_type_v<S, Comp>) {
if (stype == typeid(S)) {
Expand All @@ -98,10 +100,112 @@ namespace ecstasy::serialization
}
return false;
}

///
/// @brief Update a component with the given serializer.
///
/// @tparam Comp Component type.
///
/// @param[in] serializer Serializer to use.
/// @param[in] stype Type of the serializer.
/// @param[in] component Component to update.
///
/// @return ISerializer& The serializer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-06-25)
///
template <typename Comp>
static ISerializer &update(ISerializer &serializer, const std::type_info &stype, Comp &component)
{
(tryUpdate<S1>(serializer, stype, component) || ... || tryUpdate<Ss>(serializer, stype, component));
return serializer;
}

///
/// @brief Try to update a component with the given serializer.
///
/// @tparam S Serializer type.
/// @tparam Comp Component type.
///
/// @param[in] serializer Serializer to use.
/// @param[in] stype Type of the serializer.
/// @param[in] component Component to update.
///
/// @return bool True if the component was updated, false otherwise.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-06-25)
///
template <typename S, typename Comp>
static bool tryUpdate(ISerializer &serializer, const std::type_info &stype, Comp &component)
{
if constexpr (traits::can_update_type_v<S, Comp>) {
if (stype == typeid(S)) {
dynamic_cast<S &>(serializer).update(component);
return true;
}
}
return false;
}

///
/// @brief Load a component with the given serializer for a specifc entity.
///
/// @tparam Storage Storage type.
///
/// @param[in] serializer Serializer to use.
/// @param[in] stype Type of the serializer.
/// @param[in] storage Storage to use.
/// @param[in] entityId Entity id to which the storage must be loaded.
///
/// @return ISerializer& The serializer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-06-25)
///
template <typename Storage>
static ISerializer &load(
ISerializer &serializer, const std::type_info &stype, Storage &storage, size_t entityId)
{
(tryLoad<S1>(serializer, stype, storage, entityId) || ...
|| tryLoad<Ss>(serializer, stype, storage, entityId));
return serializer;
}

///
/// @brief Try to load a component with the given serializer for a specific entity.
///
/// @tparam S Serializer type.
/// @tparam Storage Storage type.
///
/// @param[in] serializer Serializer to use.
/// @param[in] stype Type of the serializer.
/// @param[in] storage Storage to use.
/// @param[in] entityId Entity id to which the storage must be loaded.
///
/// @return bool True if the component was loaded, false otherwise.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-06-25)
///
template <typename S, typename Storage>
static bool tryLoad(ISerializer &serializer, const std::type_info &stype, Storage &storage, size_t entityId)
{
if constexpr (traits::can_load_type_v<S, typename Storage::Component>
&& std::movable<typename Storage::Component>) {
if (stype == typeid(S)) {
storage.insert(
entityId, dynamic_cast<S &>(serializer).template load<typename Storage::Component>());
return true;
}
}
return false;
}
};

///
/// @brief Serialize a component with the given serializer if possible.
/// @brief Save a component with the given serializer if possible.
///
/// @tparam C Component type.
///
Expand All @@ -115,9 +219,50 @@ namespace ecstasy::serialization
/// @since 1.0.0 (2024-06-11)
///
template <typename C>
ISerializer &serialize(ISerializer &serializer, const std::type_info &stype, const C &component)
ISerializer &save(ISerializer &serializer, const std::type_info &stype, const C &component)
{
return ComponentSerializer<Serializers>::save(serializer, stype, component);
}

///
/// @brief Update a component with the given serializer if possible.
///
/// @tparam C Component type.
///
/// @param[in] serializer Serializer to use.
/// @param[in] stype Type of the serializer.
/// @param[in] component Component to update.
///
/// @return ISerializer& The serializer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-06-25)
///
template <typename C>
ISerializer &update(ISerializer &serializer, const std::type_info &stype, C &component)
{
return ComponentSerializer<Serializers>::update(serializer, stype, component);
}

///
/// @brief Load a component with the given serializer if possible.
///
/// @tparam Storage Storage type.
///
/// @param[in] serializer Serializer to use.
/// @param[in] stype Type of the serializer.
/// @param[in] storage Storage to use.
/// @param[in] entityId Entity id to which the storage must be loaded.
///
/// @return ISerializer& The serializer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-06-25)
///
template <typename Storage>
ISerializer &load(ISerializer &serializer, const std::type_info &stype, Storage &storage, size_t entityId)
{
return ComponentSerializer<Serializers>::serialize(serializer, stype, component);
return ComponentSerializer<Serializers>::load(serializer, stype, storage, entityId);
}

} // namespace ecstasy::serialization
Expand Down
29 changes: 9 additions & 20 deletions src/ecstasy/serialization/RawSerializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,18 @@ namespace ecstasy::serialization
///
~RawSerializer() override = default;

/// @copydoc Serializer::save
using Serializer<RawSerializer>::save;

/// @copydoc save
// clang-format off
template <typename T,
typename = std::enable_if<
typename = typename std::enable_if<
(std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>) || // String
std::is_bounded_array_v<T> || // Bounded array
util::meta::is_std_vector<T>::value || // std::vector
std::is_same_v<T, std::type_info> // std::type_info
, int>::type >
requires(!std::is_fundamental_v<T>)
// clang-format on
RawSerializer &save(const T &object)
RawSerializer &saveImpl(const T &object)
{
if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>) {
save(static_cast<uint32_t>(object.size()));
Expand All @@ -91,28 +88,25 @@ namespace ecstasy::serialization
/// @copydoc save
template <typename U>
requires std::is_fundamental_v<U>
RawSerializer &save(U object)
RawSerializer &saveImpl(U object)
{
write(reinterpret_cast<const char *>(&object), sizeof(object));
return *this;
}

/// @copydoc Serializer::update
using Serializer<RawSerializer>::update;

// clang-format off
/// @copydoc update
template <typename U,
typename = std::enable_if<(
(std::is_fundamental_v<U> || std::is_same_v<U, std::string>) || // Load
typename = typename std::enable_if<(
std::is_same_v<U, std::string> || // Load
std::is_bounded_array_v<U> || // Bounded array
util::meta::is_std_vector<U>::value) // std::vector
,
int>::type>
// clang-format on
RawSerializer &update(U &object)
RawSerializer &updateImpl(U &object)
{
if constexpr (std::is_fundamental_v<U> || std::is_same_v<U, std::string>)
if constexpr (std::is_same_v<U, std::string>)
object = load<U>();
else if constexpr (std::is_bounded_array_v<U>)
for (size_t i = 0; i < std::extent_v<U>; i++)
Expand All @@ -132,13 +126,10 @@ namespace ecstasy::serialization
return *this;
}

/// @copydoc Serializer::load
using Serializer<RawSerializer>::load;

/// @copydoc load
template <typename U>
requires std::is_fundamental_v<U> || std::is_same_v<U, std::string>
U load()
U loadImpl()
{
if constexpr (std::is_fundamental_v<U>)
return loadRaw<U>();
Expand All @@ -148,8 +139,6 @@ namespace ecstasy::serialization
_stream.seekg(pos + std::streamoff(size));

return std::string(_stream.view().data() + pos, size);
} else {
return Parent::load<U>();
}
}

Expand Down Expand Up @@ -185,7 +174,7 @@ namespace ecstasy::serialization
///
void write(const char *bytes, size_t size)
{
_stream.write(bytes, size);
_stream.write(bytes, static_cast<std::streamsize>(size));
}

///
Expand Down
Loading

0 comments on commit 3ce576f

Please sign in to comment.