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>
monroegm-disable-blank-issue-2
lumberyard-employee-dm 4 years ago committed by GitHub
parent 56904d1799
commit ca94e58399
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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" }
)
);
}

Loading…
Cancel
Save