You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl

193 lines
5.8 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/typetraits/underlying_type.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/is_same.h>
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/RTTI/TypeSafeIntegral.h>
#include <AzCore/Name/Name.h>
#include <AzCore/Name/NameDictionary.h>
namespace AzNetworking
{
// Identifies AZStd containers
struct AzContainerHelper
{
template <typename C>
struct IsIterableContainer
{
template <class TYPE>
static AZStd::false_type Evaluate(...);
template <class TYPE>
static AZStd::true_type Evaluate(int,
typename TYPE::value_type = typename TYPE::value_type(),
typename TYPE::const_iterator = C().begin(),
typename TYPE::const_iterator = C().end(),
typename TYPE::size_type = C().size());
static constexpr bool Value = AZStd::is_same<decltype(Evaluate<C>(0)), AZStd::true_type>::value;
};
template <typename TYPE>
struct HasReserveMethod
{
template <typename U>
static decltype(U().reserve()) Evaluate(int);
template <typename U>
static AZStd::false_type Evaluate(...);
static constexpr bool value = !AZStd::is_same<AZStd::false_type, decltype(Evaluate<TYPE>(0))>::value;
};
template <typename TYPE>
static typename AZStd::Utils::enable_if_c<HasReserveMethod<TYPE>::value>::type ReserveContainer(TYPE& value, typename TYPE::size_type size)
{
value.reserve(size);
}
template<typename TYPE>
static typename AZStd::Utils::enable_if_c<!HasReserveMethod<TYPE>::value>::type ReserveContainer(TYPE&, typename TYPE::size_type)
{
;
}
};
template <typename OBJECT_TYPE>
struct SerializeType
{
static bool Serialize(ISerializer& serializer, OBJECT_TYPE& value)
{
return value.Serialize(serializer);
}
};
// Base template
template <typename TYPE, typename = void>
struct SerializeObjectHelper
{
static bool SerializeObject(ISerializer& serializer, TYPE& value)
{
return value.Serialize(serializer);
}
};
// Non-containers
template <typename TYPE>
struct SerializeObjectHelper<TYPE, AZStd::enable_if_t<!AzContainerHelper::IsIterableContainer<TYPE>::value>>
{
static bool SerializeObject(ISerializer& serializer, TYPE& value)
{
return SerializeType<TYPE>::Serialize(serializer, value);
}
};
inline bool ISerializer::IsValid() const
{
return m_serializerValid;
}
inline void ISerializer::Invalidate()
{
m_serializerValid = false;
}
template <typename TYPE>
inline bool ISerializer::Serialize(TYPE& value, const char* name)
{
enum { IsEnum = AZStd::is_enum<TYPE>::value };
enum { IsTypeSafeIntegral = AZStd::is_type_safe_integral<TYPE>::value };
return SerializeHelper<IsEnum, IsTypeSafeIntegral>::Serialize(*this, value, name);
}
// SerializeHelper for objects and structures
template <>
struct ISerializer::SerializeHelper<false, false>
{
template <typename TYPE>
static bool Serialize(ISerializer& serializer, TYPE& value, const char* name)
{
if (serializer.BeginObject(name, "Type name unknown"))
{
if (SerializeObjectHelper<TYPE>::SerializeObject(serializer, value))
{
return serializer.EndObject(name, "Type name unknown");
}
}
return false;
}
};
template <>
struct ISerializer::SerializeHelper<true, false>
{
template <typename TYPE>
static bool Serialize(ISerializer& serializer, TYPE& value, const char* name)
{
using SizeType = typename AZStd::underlying_type<TYPE>::type;
SizeType& integralValue = reinterpret_cast<SizeType&>(value);
if (!serializer.Serialize(integralValue, name))
{
return false;
}
//auto enumMembers = AzEnumTraits<TYPE>::Members;
//if (AZStd::find(enumMembers.begin(), enumMembers.end(), static_cast<Type>(integralValue)) == enumMembers.end())
//{
// return false;
//}
return true;
}
};
template <>
struct ISerializer::SerializeHelper<true, true>
{
template <typename TYPE>
static bool Serialize(ISerializer& serializer, TYPE& value, const char* name)
{
using RawType = typename AZStd::underlying_type<TYPE>::type;
RawType& rawValue = reinterpret_cast<RawType&>(value);
if (!serializer.Serialize(rawValue, name))
{
return false;
}
return true;
}
};
template<>
struct SerializeObjectHelper<AZ::Name>
{
static bool SerializeObject(ISerializer& serializer, AZ::Name& value)
{
AZ::Name::Hash nameHash = value.GetHash();
bool result = serializer.Serialize(nameHash, "NameHash");
if (result && serializer.GetSerializerMode() == SerializerMode::WriteToObject)
{
value = AZ::NameDictionary::Instance().FindName(nameHash);
}
return result;
}
};
}
#include <AzNetworking/Serialization/AzContainerSerializers.h>