Skip to content

Commit

Permalink
Implemented JsonSerializer entity serialization
Browse files Browse the repository at this point in the history
Also fixed Serializer updateEntity and introduced new before/afterUpdate/SaveEntity virtual methods

Linked: #164
  • Loading branch information
AndreasLrx committed Oct 13, 2024
1 parent be7e08a commit 3a3645a
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 50 deletions.
7 changes: 4 additions & 3 deletions doc/Tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -551,9 +551,10 @@ struct Position {
Serializer should support fundamental and container types by default but it depends on the serializer implementation.
| Serializer | Fundamental (integers, floats, doubles...) | strings | containers |
| ------------------------------------------ | ------------------------------------------ | ------- | ---------- |
| @ref ecstasy::serialization::RawSerializer | Ok | OK | Ok |
| Serializer | Fundamental (integers, floats, doubles...) | strings | containers |
| ------------------------------------------- | ------------------------------------------ | ------- | ---------- |
| @ref ecstasy::serialization::RawSerializer | Ok | OK | Ok |
| @ref ecstasy::serialization::JsonSerializer | Ok | OK | Ok |
**1. Saving**
Expand Down
34 changes: 31 additions & 3 deletions src/ecstasy/serialization/EntityComponentSerializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ namespace ecstasy::serialization
{
}

///
/// @brief Construct a new Component Rtti with a custom name.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-10-04)
///
EntityComponentSerializer(std::string_view name) : IEntityComponentSerializer(), _name(name)
{
}

///
/// @brief Destroy the Component Rtti
///
Expand Down Expand Up @@ -72,11 +82,29 @@ namespace ecstasy::serialization
.template update<Component>(dynamic_cast<StorageType &>(storage).at(entity.getIndex()));
}

/// @copydoc IEntityComponentSerializer::getStorageTypeIndex
std::type_index getStorageTypeIndex() const override final
/// @copydoc IEntityComponentSerializer::getStorageTypeInfo
const std::type_info &getStorageTypeInfo() const override final
{
return std::type_index(typeid(StorageType));
return typeid(StorageType);
}

/// @copydoc IEntityComponentSerializer::getComponentTypeInfo
const std::type_info &getComponentTypeInfo() const override final
{
return typeid(Component);
}

/// @copydoc IEntityComponentSerializer::getTypeName
std::string_view getTypeName() const override final
{
if (_name.empty())
return typeid(Component).name();
return _name;
}

private:
/// Name of the component type.
std::string_view _name;
};

} // namespace ecstasy::serialization
Expand Down
28 changes: 25 additions & 3 deletions src/ecstasy/serialization/IEntityComponentSerializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,36 @@ namespace ecstasy
virtual ISerializer &load(ISerializer &serializer, IStorage &storage, RegistryEntity &entity) const = 0;

///
/// @brief Get the Storage Type Index of the component.
/// @brief Get the type info of the component storage.
///
/// @return std::type_index Type index of the storage.
/// @return const std::type_info& Type info of the component storage.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-10-04)
///
virtual std::type_index getStorageTypeIndex() const = 0;
virtual const std::type_info &getStorageTypeInfo() const = 0;

///
/// @brief Get the type info of the component.
///
/// @return const std::type_info& Type info of the component.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-10-11)
///
virtual const std::type_info &getComponentTypeInfo() const = 0;

////
/// @brief Get the Component Type Name
///
/// @note Return the explicit name of the component if any and fallback on the type name.
///
/// @return std::string_view Name of the component type.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-10-11)
///
virtual std::string_view getTypeName() const = 0;
};

} // namespace serialization
Expand Down
64 changes: 57 additions & 7 deletions src/ecstasy/serialization/JsonSerializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,16 @@ namespace ecstasy::serialization
array.PushBack(elem, _document.GetAllocator());
addValue(std::move(array.Move()));
} else if constexpr (std::is_same_v<T, std::type_info>) {
save(object.hash_code());
if (getWriteCursor().IsObject()) {
// Use name if the type is registered
auto componentSerializer = tryGetEntityComponentSerializer(object.hash_code());

if (componentSerializer)
save(componentSerializer->get().getTypeName());
else
save(std::to_string(object.hash_code()));
} else
save(object.hash_code());
} else if constexpr (std::is_fundamental_v<T>) {
addValue(rapidjson::Value(object));
} else {
Expand Down Expand Up @@ -364,12 +373,6 @@ namespace ecstasy::serialization
}
}

/// @copydoc loadComponentHash
std::size_t loadComponentHash() override final
{
return 0; // loadRaw<std::size_t>();
}

///
/// @brief Open a new nested object or array context in the current object (see @ref getWriteCursor).
/// The context can be closed with @ref closeNested.
Expand Down Expand Up @@ -502,7 +505,54 @@ namespace ecstasy::serialization
rapidjson::Document _document;
std::stack<std::reference_wrapper<rapidjson::Value>> _stack;
std::stack<rapidjson::Value::ValueIterator> _arrayIterators;
std::stack<rapidjson::Value::MemberIterator> _objectIterators;
std::string _nextKey;

/// @copydoc loadComponentHash
std::size_t loadComponentHash() override final
{
if (getWriteCursor().IsObject()) {
if (_objectIterators.empty())
throw std::logic_error(
"No object iterator. This function should be called in an updateEntity context.");
if (_objectIterators.top() == getWriteCursor().MemberEnd())
return 0;
_nextKey = _objectIterators.top()->name.GetString();
++_objectIterators.top();
return getEntityComponentSerializer(_nextKey).getComponentTypeInfo().hash_code();
} else
return load<std::size_t>();
}

/// @copydoc beforeSaveEntity
void beforeSaveEntity(RegistryEntity &entity) override final
{
newNestedObject();
static_cast<void>(entity);
}

/// @copydoc afterSaveEntity
void afterSaveEntity(RegistryEntity &entity) override final
{
closeNested();
static_cast<void>(entity);
}

/// @copydoc beforeUpdateEntity
void beforeUpdateEntity(RegistryEntity &entity) override final
{
newNestedObject(false);
_objectIterators.push(getWriteCursor().MemberBegin());
static_cast<void>(entity);
}

/// @copydoc afterUpdateEntity
void afterUpdateEntity(RegistryEntity &entity) override final
{
_objectIterators.pop();
closeNested();
static_cast<void>(entity);
}
};
} // namespace ecstasy::serialization

Expand Down
20 changes: 14 additions & 6 deletions src/ecstasy/serialization/RawSerializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,6 @@ namespace ecstasy::serialization
return *result;
}

/// @copydoc loadComponentHash
std::size_t loadComponentHash() override final
{
return loadRaw<std::size_t>();
}

///
/// @brief Get the string stream of the serializer.
///
Expand All @@ -329,6 +323,20 @@ namespace ecstasy::serialization

private:
std::stringstream _stream;

/// @copydoc afterSaveEntity
void afterSaveEntity(RegistryEntity &entity) override final
{
// Notify the end of the entity
save<std::size_t>(0);
static_cast<void>(entity);
}

/// @copydoc loadComponentHash
std::size_t loadComponentHash() override final
{
return loadRaw<std::size_t>();
}
};
} // namespace ecstasy::serialization

Expand Down
Loading

0 comments on commit 3a3645a

Please sign in to comment.