Added SerializeContext Reflection of FixedMaxPath class (#4453)
* Added SerializeContext Reflection of FixedMaxPath class Added UnitTest for validating path clas reflection Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the paths loaded during the serialization to use test path separator Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
56904d1799
commit
ca94e58399
@@ -45,6 +45,7 @@
|
||||
#include <AzCore/Module/Module.h>
|
||||
#include <AzCore/Module/ModuleManager.h>
|
||||
|
||||
#include <AzCore/IO/Path/PathReflect.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
#include <AzCore/Driller/Driller.h>
|
||||
@@ -1547,7 +1548,7 @@ namespace AZ
|
||||
// reflect name dictionary.
|
||||
Name::Reflect(context);
|
||||
// reflect path
|
||||
IO::PathReflection::Reflect(context);
|
||||
IO::PathReflect(context);
|
||||
|
||||
// reflect the SettingsRegistryInterface, SettignsRegistryImpl and the global Settings Registry
|
||||
// instance (AZ::SettingsRegistry::Get()) into the Behavior Context
|
||||
|
||||
@@ -50,13 +50,4 @@ namespace AZ::IO
|
||||
const PathIterator<Path>& rhs);
|
||||
template bool operator!=<FixedMaxPath>(const PathIterator<FixedMaxPath>& lhs,
|
||||
const PathIterator<FixedMaxPath>& rhs);
|
||||
|
||||
void PathReflection::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AZ::IO::Path>()
|
||||
->Field("m_path", &AZ::IO::Path::m_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +321,6 @@ namespace AZ::IO
|
||||
using const_iterator = const PathIterator<BasicPath>;
|
||||
using iterator = const_iterator;
|
||||
friend PathIterator<BasicPath>;
|
||||
friend struct PathReflection;
|
||||
|
||||
// constructors and destructor
|
||||
constexpr BasicPath() = default;
|
||||
@@ -665,6 +664,7 @@ namespace AZ::IO
|
||||
namespace AZ
|
||||
{
|
||||
AZ_TYPE_INFO_SPECIALIZE(AZ::IO::Path, "{88E0A40F-3085-4CAB-8B11-EF5A2659C71A}");
|
||||
AZ_TYPE_INFO_SPECIALIZE(AZ::IO::FixedMaxPath, "{FA6CA49F-376A-417C-9767-DD50744DF203}");
|
||||
}
|
||||
|
||||
namespace AZ::IO
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
template <typename PathType>
|
||||
struct PathSerializer
|
||||
: public SerializeContext::IDataSerializer
|
||||
{
|
||||
public:
|
||||
/// Convert binary data to text
|
||||
size_t DataToText(IO::GenericStream& in, IO::GenericStream& out, bool) override
|
||||
{
|
||||
PathType outPath;
|
||||
outPath.Native().resize_no_construct(in.GetLength());
|
||||
in.Read(outPath.Native().size(), outPath.Native().data());
|
||||
|
||||
return static_cast<size_t>(out.Write(outPath.Native().size(), outPath.Native().c_str()));
|
||||
}
|
||||
|
||||
size_t TextToData(const char* text, unsigned int, IO::GenericStream& stream, bool) override
|
||||
{
|
||||
return static_cast<size_t>(stream.Write(strlen(text), reinterpret_cast<const void*>(text)));
|
||||
}
|
||||
|
||||
size_t Save(const void* classPtr, IO::GenericStream& stream, bool) override
|
||||
{
|
||||
/// Save paths out using the PosixPathSeparator
|
||||
PathType path(reinterpret_cast<const PathType*>(classPtr)->Native(), AZ::IO::PosixPathSeparator);
|
||||
path.MakePreferred();
|
||||
|
||||
return static_cast<size_t>(stream.Write(path.Native().size(), path.c_str()));
|
||||
}
|
||||
|
||||
bool Load(void* classPtr, IO::GenericStream& stream, unsigned int, bool) override
|
||||
{
|
||||
// Normalize the path load
|
||||
auto path = reinterpret_cast<PathType*>(classPtr);
|
||||
|
||||
path->Native().resize_no_construct(stream.GetLength());
|
||||
stream.Read(path->Native().size(), path->Native().data());
|
||||
*path = path->LexicallyNormal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompareValueData(const void* lhs, const void* rhs) override
|
||||
{
|
||||
return SerializeContext::EqualityCompareHelper<Path>::CompareValues(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
void PathReflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<SerializeContext*>(context); serializeContext != nullptr)
|
||||
{
|
||||
serializeContext->Class<Path>()
|
||||
->Serializer(AZ::SerializeContext::IDataSerializerPtr{ new PathSerializer<Path>{},
|
||||
AZ::SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter() })
|
||||
;
|
||||
|
||||
serializeContext->Class<FixedMaxPath>()
|
||||
->Serializer(AZ::SerializeContext::IDataSerializerPtr{ new PathSerializer<FixedMaxPath>{},
|
||||
AZ::SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter() })
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
void PathReflect(AZ::ReflectContext* context);
|
||||
}
|
||||
@@ -57,11 +57,6 @@ namespace AZ::IO
|
||||
// It depends on the path type
|
||||
template <typename PathType>
|
||||
class PathIterator;
|
||||
|
||||
struct PathReflection
|
||||
{
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
}
|
||||
|
||||
namespace AZStd
|
||||
|
||||
@@ -187,6 +187,8 @@ set(FILES
|
||||
IO/Path/Path.inl
|
||||
IO/Path/PathIterable.inl
|
||||
IO/Path/PathParser.inl
|
||||
IO/Path/PathReflect.cpp
|
||||
IO/Path/PathReflect.h
|
||||
IO/Path/Path_fwd.h
|
||||
IO/SystemFile.cpp
|
||||
IO/SystemFile.h
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/IO/ByteContainerStream.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/Path/PathReflect.h>
|
||||
#include <AzCore/IO/Streamer/StreamerComponent.h>
|
||||
|
||||
#include <AzCore/RTTI/AttributeReader.h>
|
||||
@@ -8151,5 +8152,98 @@ namespace UnitTest
|
||||
m_serializeContext->Class<TestClassWithEnumFieldThatSpecializesTypeInfo>();
|
||||
m_serializeContext->DisableRemoveReflection();
|
||||
}
|
||||
|
||||
template <typename ParamType>
|
||||
class PathSerializationParamFixture
|
||||
: public ScopedAllocatorSetupFixture
|
||||
, public ::testing::WithParamInterface<ParamType>
|
||||
{
|
||||
public:
|
||||
PathSerializationParamFixture()
|
||||
: ScopedAllocatorSetupFixture(
|
||||
[]() { AZ::SystemAllocator::Descriptor desc; desc.m_stackRecordLevels = 30; return desc; }()
|
||||
)
|
||||
{}
|
||||
|
||||
// We must expose the class for serialization first.
|
||||
void SetUp() override
|
||||
{
|
||||
m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
|
||||
AZ::IO::PathReflect(m_serializeContext.get());
|
||||
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_serializeContext->EnableRemoveReflection();
|
||||
AZ::IO::PathReflect(m_serializeContext.get());
|
||||
m_serializeContext->DisableRemoveReflection();
|
||||
|
||||
m_serializeContext.reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
|
||||
};
|
||||
|
||||
struct PathSerializationParams
|
||||
{
|
||||
const char m_preferredSeparator{};
|
||||
const char* m_testPath{};
|
||||
};
|
||||
using PathSerializationFixture = PathSerializationParamFixture<PathSerializationParams>;
|
||||
|
||||
TEST_P(PathSerializationFixture, PathSerializer_SerializesStringBackedPath_Succeeds)
|
||||
{
|
||||
const auto& testParams = GetParam();
|
||||
{
|
||||
// Path serialization
|
||||
AZ::IO::Path testPath{ testParams.m_testPath, testParams.m_preferredSeparator };
|
||||
|
||||
AZStd::vector<char> byteBuffer;
|
||||
AZ::IO::ByteContainerStream byteStream(&byteBuffer);
|
||||
auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
|
||||
objStream->WriteClass(&testPath);
|
||||
objStream->Finalize();
|
||||
|
||||
byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
|
||||
|
||||
AZ::IO::Path loadPath{ testParams.m_preferredSeparator };
|
||||
EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadPath, m_serializeContext.get()));
|
||||
EXPECT_EQ(testPath.LexicallyNormal(), loadPath);
|
||||
}
|
||||
|
||||
{
|
||||
// FixedMaxPath serialization
|
||||
AZ::IO::FixedMaxPath testFixedMaxPath{ testParams.m_testPath, testParams.m_preferredSeparator };
|
||||
|
||||
AZStd::vector<char> byteBuffer;
|
||||
AZ::IO::ByteContainerStream byteStream(&byteBuffer);
|
||||
auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
|
||||
objStream->WriteClass(&testFixedMaxPath);
|
||||
objStream->Finalize();
|
||||
|
||||
byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
|
||||
|
||||
AZ::IO::FixedMaxPath loadPath{ testParams.m_preferredSeparator };
|
||||
EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadPath, m_serializeContext.get()));
|
||||
EXPECT_EQ(testFixedMaxPath.LexicallyNormal(), loadPath);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
PathSerialization,
|
||||
PathSerializationFixture,
|
||||
::testing::Values(
|
||||
PathSerializationParams{ AZ::IO::PosixPathSeparator, "" },
|
||||
PathSerializationParams{ AZ::IO::PosixPathSeparator, "test" },
|
||||
PathSerializationParams{ AZ::IO::PosixPathSeparator, "/test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "/test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "D:test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "D:/test" },
|
||||
PathSerializationParams{ AZ::IO::WindowsPathSeparator, "test/foo/../bar" }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user