Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,58 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/std/string/string.h>
namespace AbstractValue
{
class BaseValue {};
template <typename T>
class ValueT
: public BaseValue
{
public:
ValueT() : m_value() {}
ValueT(const T& value) : m_value(value) {}
const T& GetValue() const { return m_value; }
private:
T m_value;
};
template <>
class ValueT<char*>
: public BaseValue
{
public:
ValueT() : m_value() {}
ValueT(const char* value) : m_value(value) {}
const char* GetValue() const { return m_value.c_str(); }
private:
AZStd::string m_value;
};
using Bool = ValueT<bool>;
using Char = ValueT<char>;
using Float = ValueT<float>;
using Double = ValueT<double>;
using String = ValueT<char*>;
using Int8 = ValueT<int8_t>;
using Int16 = ValueT<int16_t>;
using Int32 = ValueT<int32_t>;
using Int64 = ValueT<int64_t>;
using UInt8 = ValueT<uint8_t>;
using UInt16 = ValueT<uint16_t>;
using UInt32 = ValueT<uint32_t>;
using UInt64 = ValueT<uint64_t>;
}
@@ -0,0 +1,241 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzNetworking/Serialization/ISerializer.h>
#include <AzNetworking/Utilities/NetworkCommon.h>
#include <AzCore/std/containers/stack.h>
#include <AzCore/std/containers/array.h>
#include <AzCore/std/containers/fixed_unordered_map.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/string/string.h>
#include <limits>
namespace AzNetworking
{
// Generic AZ Containers
template <typename TYPE>
struct SerializeAzContainer
{
static bool Serialize(ISerializer& serializer, TYPE& container)
{
using ValueType = typename TYPE::value_type;
constexpr uint32_t max = std::numeric_limits<uint32_t>::max(); // Limit to uint32 max elements
const bool write = (serializer.GetSerializerMode() == SerializerMode::WriteToObject);
uint32_t size = static_cast<uint32_t>(container.size());
bool success = serializer.Serialize(size, "Size");
// Dynamic containers require different read/write serialization interfaces
if (write)
{
container.clear();
AzNetworking::AzContainerHelper::ReserveContainer<TYPE>(container, size);
ValueType element;
for (uint32_t i = 0; i < size; ++i)
{
success &= serializer.Serialize(element, GenerateIndexLabel<max>(i).c_str());
container.insert(container.end(), element);
}
}
else
{
uint32_t i = 0;
for (auto it = container.begin(); it != container.end(); ++it, ++i)
{
success &= serializer.Serialize(*it, GenerateIndexLabel<max>(i).c_str());
}
}
return success;
}
};
// fixed size array
template <typename TYPE, AZStd::size_t Size>
struct SerializeAzContainer<AZStd::array<TYPE, Size>>
{
static bool Serialize(ISerializer& serializer, AZStd::array<TYPE, Size>& container)
{
constexpr uint32_t max = static_cast<uint32_t>(Size);
static_assert(Size <= max, "Array size must be less than max.\n");
bool success = true;
int i = 0;
for (auto &elem : container)
{
success &= serializer.Serialize(elem, GenerateIndexLabel<max>(i++).c_str());
}
return success;
}
};
// fixed_unordered_map
template <typename Key, typename MappedType, AZStd::size_t FixedNumBuckets, AZStd::size_t FixedNumElements, class Hasher, class EqualKey>
struct SerializeAzContainer<AZStd::fixed_unordered_map<Key, MappedType, FixedNumBuckets, FixedNumElements, Hasher, EqualKey>>
{
using TYPE = AZStd::fixed_unordered_map<Key, MappedType, FixedNumBuckets, FixedNumElements, Hasher, EqualKey>;
static bool Serialize(ISerializer& serializer, TYPE& container)
{
using SizeType = typename TYPE::size_type;
using ValueType = typename TYPE::value_type;
static_assert(FixedNumElements >= FixedNumBuckets, "fixed_unordered_map buckets is less than elements.");
constexpr uint32_t max = static_cast<uint32_t>(FixedNumElements); // Elements is > Buckets
const bool write = (serializer.GetSerializerMode() == SerializerMode::WriteToObject);
SizeType size = container.size();
bool success = serializer.Serialize(size, "Size");
if (write)
{
container.clear();
ValueType element;
for (uint32_t i = 0; i < size; ++i)
{
success &= serializer.Serialize(element, GenerateIndexLabel<max>(i).c_str());
container.insert(element);
}
}
else
{
uint32_t i = 0;
for (auto it = container.begin(); it != container.end(); ++it, ++i)
{
success &= serializer.Serialize(*it, GenerateIndexLabel<max>(i).c_str());
}
}
return success;
}
};
// fixed_unordered_multimap
template <typename Key, typename MappedType, AZStd::size_t FixedNumBuckets, AZStd::size_t FixedNumElements, class Hasher, class EqualKey>
struct SerializeAzContainer<AZStd::fixed_unordered_multimap<Key, MappedType, FixedNumBuckets, FixedNumElements, Hasher, EqualKey>>
{
using TYPE = AZStd::fixed_unordered_multimap<Key, MappedType, FixedNumBuckets, FixedNumElements, Hasher, EqualKey>;
static bool Serialize(ISerializer& serializer, TYPE& container)
{
using SizeType = typename TYPE::size_type;
using ValueType = typename TYPE::value_type;
static_assert(FixedNumElements >= FixedNumBuckets, "fixed_unordered_multimap buckets is less than elements.");
constexpr uint32_t max = static_cast<uint32_t>(FixedNumElements); // Elements is > Buckets
const bool write = (serializer.GetSerializerMode() == SerializerMode::WriteToObject);
SizeType size = container.size();
bool success = serializer.Serialize(size, "Size");
if (write)
{
container.clear();
ValueType element;
for (uint32_t i = 0; i < size; ++i)
{
success &= serializer.Serialize(element, GenerateIndexLabel<max>(i).c_str());
container.insert(element);
}
}
else
{
uint32_t i = 0;
for (auto it = container.begin(); it != container.end(); ++it, ++i)
{
success &= serializer.Serialize(*it, GenerateIndexLabel<max>(i).c_str());
}
}
return success;
}
};
// multimap
template <class Key, class MappedType, class Compare, class Allocator>
struct SerializeAzContainer<AZStd::multimap<Key, MappedType, Compare, Allocator>>
{
using TYPE = AZStd::multimap<Key, MappedType, Compare, Allocator>;
static bool Serialize(ISerializer& serializer, TYPE& container)
{
using SizeType = typename TYPE::size_type;
using ValueType = typename TYPE::value_type;
constexpr uint32_t max = std::numeric_limits<uint32_t>::max(); // Limit to uint32 max elements
const bool write = (serializer.GetSerializerMode() == SerializerMode::WriteToObject);
SizeType size = static_cast<uint32_t>(container.size());
bool success = serializer.Serialize(size, "Size");
if (write)
{
container.clear();
ValueType element;
for (uint32_t i = 0; i < size; ++i)
{
success &= serializer.Serialize(element, GenerateIndexLabel<max>(i).c_str());
container.insert(element);
}
}
else
{
uint32_t i = 0;
for (auto it = container.begin(); it != container.end(); ++it, ++i)
{
success &= serializer.Serialize(*it, GenerateIndexLabel<max>(i).c_str());
}
}
return success;
}
};
// String
template<>
struct SerializeAzContainer<AZStd::string>
{
static bool Serialize(ISerializer& serializer, AZStd::string& value)
{
uint32_t size = aznumeric_cast<uint32_t>(value.length());
uint32_t outBytes = size;
bool success = serializer.Serialize(size, "Size");
value.resize_no_construct(size);
success &= serializer.SerializeBytes(reinterpret_cast<uint8_t*>(value.data()), size, true, outBytes, "String");
return success && outBytes == size;
}
};
// fixed_string
template <AZStd::size_t MaxElementCount>
struct SerializeAzContainer<AZStd::fixed_string<MaxElementCount>>
{
static bool Serialize(ISerializer& serializer, AZStd::fixed_string<MaxElementCount>& value)
{
using SizeType = typename AZ::SizeType<AZ::RequiredBytesForValue<MaxElementCount>(), false>::Type;
SizeType size = aznumeric_cast<SizeType>(value.length());
uint32_t outBytes = static_cast<uint32_t>(size);
bool success = serializer.Serialize(size, "Size");
value.resize_no_construct(size);
success &= serializer.SerializeBytes(reinterpret_cast<uint8_t*>(value.data()), static_cast<uint32_t>(size), true, outBytes, "String");
return success && outBytes == size;
}
};
// Az Containers
template <typename TYPE>
struct SerializeObjectHelper<TYPE, AZStd::enable_if_t<AzContainerHelper::IsIterableContainer<TYPE>::Value>>
{
static bool SerializeObject(ISerializer& serializer, TYPE& container)
{
return SerializeAzContainer<TYPE>::Serialize(serializer, container);
}
};
}
@@ -0,0 +1,430 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzNetworking/Serialization/DeltaSerializer.h>
#include <AzNetworking/Serialization/NetworkInputSerializer.h>
#include <AzNetworking/Serialization/NetworkOutputSerializer.h>
#include <AzCore/std/string/conversions.h>
namespace AzNetworking
{
SerializerDelta::SerializerDelta()
: m_dirtyBits()
, m_deltaBytes()
{
;
}
uint32_t SerializerDelta::GetNumDirtyBits() const
{
return m_dirtyBits.GetSize();
}
bool SerializerDelta::GetDirtyBit(uint32_t index) const
{
return m_dirtyBits.GetBit(index);
}
bool SerializerDelta::InsertDirtyBit(bool dirtyBit)
{
return m_dirtyBits.PushBack(dirtyBit);
}
uint8_t* SerializerDelta::GetBufferPtr()
{
return m_deltaBytes.GetBuffer();
}
uint32_t SerializerDelta::GetBufferSize() const
{
return static_cast<uint32_t>(m_deltaBytes.GetSize());
}
uint32_t SerializerDelta::GetBufferCapacity() const
{
return static_cast<uint32_t>(m_deltaBytes.GetCapacity());
}
void SerializerDelta::SetBufferSize(uint32_t size)
{
m_deltaBytes.Resize(size);
}
bool SerializerDelta::Serialize(ISerializer& serializer)
{
return serializer.Serialize(m_dirtyBits, "DirtyBits")
&& serializer.Serialize(m_deltaBytes, "DeltaBytes");
}
DeltaSerializerCreate::DeltaSerializerCreate(SerializerDelta& delta)
: m_delta(delta)
, m_dataSerializer(m_delta.GetBufferPtr(), m_delta.GetBufferCapacity())
{
m_namePrefix.reserve(128);
}
DeltaSerializerCreate::~DeltaSerializerCreate()
{
// Delete any left over records that might be hanging around
for (auto iter : m_records)
{
delete iter.second;
}
m_records.clear();
}
SerializerMode DeltaSerializerCreate::GetSerializerMode() const
{
return SerializerMode::ReadFromObject;
}
bool DeltaSerializerCreate::Serialize(bool& value, const char* name)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(char& value, const char* name, [[maybe_unused]] char minValue, [[maybe_unused]] char maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(int8_t& value, const char* name, [[maybe_unused]] int8_t minValue, [[maybe_unused]] int8_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(int16_t& value, const char* name, [[maybe_unused]] int16_t minValue, [[maybe_unused]] int16_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(int32_t& value, const char* name, [[maybe_unused]] int32_t minValue, [[maybe_unused]] int32_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(int64_t& value, const char* name, [[maybe_unused]] int64_t minValue, [[maybe_unused]] int64_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(uint8_t& value, const char* name, [[maybe_unused]] uint8_t minValue, [[maybe_unused]] uint8_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(uint16_t& value, const char* name, [[maybe_unused]] uint16_t minValue, [[maybe_unused]] uint16_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(uint32_t& value, const char* name, [[maybe_unused]] uint32_t minValue, [[maybe_unused]] uint32_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(uint64_t& value, const char* name, [[maybe_unused]] uint64_t minValue, [[maybe_unused]] uint64_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(float& value, const char* name, [[maybe_unused]] float minValue, [[maybe_unused]] float maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::Serialize(double& value, const char* name, [[maybe_unused]] double minValue, [[maybe_unused]] double maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerCreate::SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name)
{
return SerializeHelper(buffer, bufferCapacity, isString, outSize, name);
}
AZStd::string DeltaSerializerCreate::GetNextObjectName(const char* name)
{
AZStd::string objectName = name;
objectName += ".";
objectName += AZStd::to_string(m_objectCounter);
++m_objectCounter;
return objectName;
}
bool DeltaSerializerCreate::BeginObject(const char* name, [[maybe_unused]] const char* typeName)
{
m_nameLengthStack.push_back(m_namePrefix.length());
m_namePrefix += GetNextObjectName(name);
m_namePrefix += ".";
return true;
}
bool DeltaSerializerCreate::EndObject([[maybe_unused]] const char* name, [[maybe_unused]] const char* typeName)
{
const size_t prevLen = m_nameLengthStack.back();
m_nameLengthStack.pop_back();
m_namePrefix.resize(prevLen);
return true;
}
const uint8_t* DeltaSerializerCreate::GetBuffer() const
{
return nullptr;
}
uint32_t DeltaSerializerCreate::GetCapacity() const
{
return 0;
}
uint32_t DeltaSerializerCreate::GetSize() const
{
return 0;
}
template <typename T>
bool DeltaSerializerCreate::SerializeHelper(T& value, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name)
{
typedef AbstractValue::ValueT<T> ValueType;
const size_t prevLen = m_namePrefix.length();
m_namePrefix += GetNextObjectName(name);
const AZ::HashValue32 nameHash = AZ::TypeHash32(m_namePrefix.c_str());
m_namePrefix.resize(prevLen);
AbstractValue::BaseValue*& baseValue = m_records[nameHash];
// If we are in the gather records phase, just save off the value records
if (m_gatheringRecords)
{
if (baseValue != nullptr)
{
AZ_Assert(false, "Duplicate name encountered in delta serializer. This will cause data to be serialized incorrectly.");
return false;
}
baseValue = new ValueType(value);
}
else // If we are not gathering records, then we are comparing them
{
bool different = false;
if (baseValue)
{
// This record must match the same type that was pushed into the list during the gathering phase
ValueType* typedValue = static_cast<ValueType*>(baseValue);
// Are the two values different?
different = typedValue->GetValue() != value;
}
else
{
// No record? Then definitely different
different = true;
}
// Record a bit to track this information
if (!m_delta.InsertDirtyBit(different))
{
AZ_Assert(false, "Ran out of bits in DeltaSerializerCreate. You are probably trying to serialize an object with too many fields. Consider resizing the bitset in DeltaSerializerCreate");
return false;
}
// If different, also write the data into the delta's buffer
if (different)
{
if (!SerializeHelperImpl(value, bufferCapacity, isString, outSize, name))
{
return false;
}
}
}
return true;
}
template <typename T>
bool DeltaSerializerCreate::SerializeHelperImpl(T& value, uint32_t, bool, uint32_t&, const char* name)
{
ISerializer& ser = m_dataSerializer; // Use interface since it fills in defaulted type info parameters
return ser.Serialize(value, name);
}
bool DeltaSerializerCreate::SerializeHelperImpl(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name)
{
ISerializer& ser = m_dataSerializer; // Use interface since it fills in defaulted type info parameters
return ser.SerializeBytes(buffer, bufferCapacity, isString, outSize, name);
}
DeltaSerializerApply::DeltaSerializerApply(SerializerDelta& delta)
: m_delta(delta)
, m_dataSerializer(m_delta.GetBufferPtr(), m_delta.GetBufferSize())
{
;
}
SerializerMode DeltaSerializerApply::GetSerializerMode() const
{
return SerializerMode::WriteToObject;
}
bool DeltaSerializerApply::Serialize(bool& value, const char* name)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(char& value, const char* name, [[maybe_unused]] char minValue, [[maybe_unused]] char maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(int8_t& value, const char* name, [[maybe_unused]] int8_t minValue, [[maybe_unused]] int8_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(int16_t& value, const char* name, [[maybe_unused]] int16_t minValue, [[maybe_unused]] int16_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(int32_t& value, const char* name, [[maybe_unused]] int32_t minValue, [[maybe_unused]] int32_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(int64_t& value, const char* name, [[maybe_unused]] int64_t minValue, [[maybe_unused]] int64_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(uint8_t& value, const char* name, [[maybe_unused]] uint8_t minValue, [[maybe_unused]] uint8_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(uint16_t& value, const char* name, [[maybe_unused]] uint16_t minValue, [[maybe_unused]] uint16_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(uint32_t& value, const char* name, [[maybe_unused]] uint32_t minValue, [[maybe_unused]] uint32_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(uint64_t& value, const char* name, [[maybe_unused]] uint64_t minValue, [[maybe_unused]] uint64_t maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(float& value, const char* name, [[maybe_unused]] float minValue, [[maybe_unused]] float maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::Serialize(double& value, const char* name, [[maybe_unused]] double minValue, [[maybe_unused]] double maxValue)
{
uint32_t unused = 0;
return SerializeHelper(value, 0, false, unused, name);
}
bool DeltaSerializerApply::SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name)
{
return SerializeHelper(buffer, bufferCapacity, isString, outSize, name);
}
bool DeltaSerializerApply::BeginObject([[maybe_unused]] const char *name, [[maybe_unused]] const char* typeName)
{
return true;
}
bool DeltaSerializerApply::EndObject([[maybe_unused]] const char *name, [[maybe_unused]] const char* typeName)
{
return true;
}
const uint8_t* DeltaSerializerApply::GetBuffer() const
{
return nullptr;
}
uint32_t DeltaSerializerApply::GetCapacity() const
{
return 0;
}
uint32_t DeltaSerializerApply::GetSize() const
{
return 0;
}
template <typename T>
bool DeltaSerializerApply::SerializeHelper(T& value, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name)
{
// If we have run out of delta records, something has gone wrong
if (m_nextDirtyBit >= m_delta.GetNumDirtyBits())
{
return false;
}
const bool hasRecord = m_delta.GetDirtyBit(m_nextDirtyBit);
++m_nextDirtyBit;
// No record in the delta for this field, just skip it
if (!hasRecord)
{
return true; // This isn't an error
}
// There is a record, so serialize the value out of the delta
return SerializeHelperImpl(value, bufferCapacity, isString, outSize, name);
}
template <typename T>
bool DeltaSerializerApply::SerializeHelperImpl(T& value, uint32_t, bool, uint32_t&, const char* name)
{
ISerializer& ser = m_dataSerializer; // Use interface since it fills in defaulted type info parameters
return ser.Serialize(value, name);
}
bool DeltaSerializerApply::SerializeHelperImpl(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name)
{
ISerializer& ser = m_dataSerializer; // Use interface since it fills in defaulted type info parameters
return ser.SerializeBytes(buffer, bufferCapacity, isString, outSize, name);
}
}
@@ -0,0 +1,175 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzNetworking/Serialization/ISerializer.h>
#include <AzNetworking/Serialization/AbstractValue.h>
#include <AzNetworking/Serialization/NetworkInputSerializer.h>
#include <AzNetworking/Serialization/NetworkOutputSerializer.h>
#include <AzNetworking/DataStructures/FixedSizeVectorBitset.h>
#include <AzNetworking/DataStructures/ByteBuffer.h>
#include <AzCore/Utils/TypeHash.h>
#include <AzCore/std/containers/unordered_map.h>
namespace AzNetworking
{
//! SerializerDelta
//! Encodes information used by DeltaSerializer to create and apply serialization deltas
class SerializerDelta
{
public:
SerializerDelta();
uint32_t GetNumDirtyBits() const;
bool GetDirtyBit(uint32_t index) const;
bool InsertDirtyBit(bool dirtyBit);
uint8_t* GetBufferPtr();
uint32_t GetBufferSize() const;
uint32_t GetBufferCapacity() const;
void SetBufferSize(uint32_t size);
bool Serialize(ISerializer& serializer);
private:
FixedSizeVectorBitset<255> m_dirtyBits;
ByteBuffer<1024> m_deltaBytes;
};
//! A serializer that is used to produce a SerializerDelta between two objects.
//! This delta can be reapplied to the same base object to reconstruct the second object using
//! the DeltaSerializerApply serializer
//! NOTE: The objects serialized must have a consistent serialization footprint i.e. no changes in branches during serialization
class DeltaSerializerCreate
: public ISerializer
{
public:
DeltaSerializerCreate(SerializerDelta& delta);
~DeltaSerializerCreate();
template <typename TYPE>
bool CreateDelta(TYPE& base, TYPE& current);
// ISerializer interfaces
SerializerMode GetSerializerMode() const override;
bool Serialize( bool& value, const char* name) override;
bool Serialize( char& value, const char* name, char minValue, char maxValue) override;
bool Serialize( int8_t& value, const char* name, int8_t minValue, int8_t maxValue) override;
bool Serialize( int16_t& value, const char* name, int16_t minValue, int16_t maxValue) override;
bool Serialize( int32_t& value, const char* name, int32_t minValue, int32_t maxValue) override;
bool Serialize( int64_t& value, const char* name, int64_t minValue, int64_t maxValue) override;
bool Serialize( uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue) override;
bool Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue) override;
bool Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue) override;
bool Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue) override;
bool Serialize( float& value, const char* name, float minValue, float maxValue) override;
bool Serialize( double& value, const char* name, double minValue, double maxValue) override;
bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) override;
bool BeginObject(const char *name, const char* typeName) override;
bool EndObject(const char *name, const char* typeName) override;
const uint8_t* GetBuffer() const override;
uint32_t GetCapacity() const override;
uint32_t GetSize() const override;
void ClearTrackedChangesFlag() override {}
bool GetTrackedChangesFlag() const override { return false; }
// ISerializer interfaces
private:
DeltaSerializerCreate(const DeltaSerializerCreate&) = delete;
DeltaSerializerCreate& operator=(const DeltaSerializerCreate&) = delete;
AZStd::string GetNextObjectName(const char* name);
template <typename T>
bool SerializeHelper(T& value, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name);
template <typename T>
bool SerializeHelperImpl(T& value, uint32_t, bool, uint32_t&, const char* name);
bool SerializeHelperImpl(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name);
private:
SerializerDelta& m_delta;
bool m_gatheringRecords = false;
uint32_t m_objectCounter = 0;
AZStd::string m_namePrefix;
AZStd::vector<size_t> m_nameLengthStack;
AZStd::unordered_map<AZ::HashValue32, AbstractValue::BaseValue*> m_records;
NetworkInputSerializer m_dataSerializer;
};
//! A serializer that is used to apply a SerializerDelta to a base object in order to reconstruct the second object.
//! NOTE: The objects serialized must have a consistent serialization footprint i.e. no changes in branches during serialization
class DeltaSerializerApply
: public ISerializer
{
public:
DeltaSerializerApply(SerializerDelta& delta);
template <typename TYPE>
bool ApplyDelta(TYPE& output);
// ISerializer interfaces
SerializerMode GetSerializerMode() const override;
bool Serialize( bool& value, const char* name) override;
bool Serialize( char& value, const char* name, char minValue, char maxValue) override;
bool Serialize( int8_t& value, const char* name, int8_t minValue, int8_t maxValue) override;
bool Serialize( int16_t& value, const char* name, int16_t minValue, int16_t maxValue) override;
bool Serialize( int32_t& value, const char* name, int32_t minValue, int32_t maxValue) override;
bool Serialize( int64_t& value, const char* name, int64_t minValue, int64_t maxValue) override;
bool Serialize( uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue) override;
bool Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue) override;
bool Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue) override;
bool Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue) override;
bool Serialize( float& value, const char* name, float minValue, float maxValue) override;
bool Serialize( double& value, const char* name, double minValue, double maxValue) override;
bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) override;
bool BeginObject(const char *name, const char* typeName) override;
bool EndObject(const char *name, const char* typeName) override;
const uint8_t* GetBuffer() const override;
uint32_t GetCapacity() const override;
uint32_t GetSize() const override;
void ClearTrackedChangesFlag() override {}
bool GetTrackedChangesFlag() const override { return false; }
// ISerializer interfaces
private:
DeltaSerializerApply(const DeltaSerializerApply&) = delete;
DeltaSerializerApply& operator=(const DeltaSerializerApply&) = delete;
template <typename T>
bool SerializeHelper(T& value, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name);
template <typename T>
bool SerializeHelperImpl(T& value, uint32_t, bool, uint32_t&, const char* name);
bool SerializeHelperImpl(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name);
private:
SerializerDelta& m_delta;
uint32_t m_nextDirtyBit = 0;
NetworkOutputSerializer m_dataSerializer;
};
}
#include <AzNetworking/Serialization/DeltaSerializer.inl>
@@ -0,0 +1,45 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace AzNetworking
{
template <typename TYPE>
bool DeltaSerializerCreate::CreateDelta(TYPE& base, TYPE& current)
{
// Gather value records from the base object
m_gatheringRecords = true;
if (!base.Serialize(*this))
{
return false;
}
m_objectCounter = 0;
// Compile deltas from the new object
m_gatheringRecords = false;
if (!current.Serialize(*this))
{
return false;
}
// Update the delta buffer size based on how much data was serialized
m_delta.SetBufferSize(m_dataSerializer.GetSize());
return true;
}
template <typename TYPE>
bool DeltaSerializerApply::ApplyDelta(TYPE& output)
{
return output.Serialize(*this);
}
}
@@ -0,0 +1,141 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzNetworking/Serialization/HashSerializer.h>
#include <AzNetworking/Utilities/QuantizedValues.h>
namespace AzNetworking
{
// This gives us a hash sensitivity of around 1/128th of a unit, and will detect errors within a range of -16,777,216 to +16,777,216
static const int32_t FloatHashMinValue = (INT_MIN >> 7);
static const int32_t FloatHashMaxValue = (INT_MAX >> 7);
AZ::HashValue64 HashSerializer::GetHash() const
{
return m_hash;
}
SerializerMode HashSerializer::GetSerializerMode() const
{
return SerializerMode::ReadFromObject;
}
bool HashSerializer::Serialize(bool& value, const char*)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(char& value, [[maybe_unused]] const char* name, [[maybe_unused]] char minValue, [[maybe_unused]] char maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(int8_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] int8_t minValue, [[maybe_unused]] int8_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(int16_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] int16_t minValue, [[maybe_unused]] int16_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(int32_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] int32_t minValue, [[maybe_unused]] int32_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(int64_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] int64_t minValue, [[maybe_unused]] int64_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(uint8_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] uint8_t minValue, [[maybe_unused]] uint8_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(uint16_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] uint16_t minValue, [[maybe_unused]] uint16_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(uint32_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] uint32_t minValue, [[maybe_unused]] uint32_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(uint64_t& value, [[maybe_unused]] const char* name, [[maybe_unused]] uint64_t minValue, [[maybe_unused]] uint64_t maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::Serialize(float& value, [[maybe_unused]] const char* name, [[maybe_unused]] float minValue, [[maybe_unused]] float maxValue)
{
// This hashing serializer is used to detect desyncs between the predicted and authoritative state of all predictive values
// If either of these asserts triggers, it means desyncs *will not* be detected for the value being serialized
// You should consider using a quantized float for the failing value, or potentially adjust the min/max quantized values
AZ_Assert(value > FloatHashMinValue, "Out of range float value passed to hashing serializer, this will clamp the float value");
AZ_Assert(value < FloatHashMaxValue, "Out of range float value passed to hashing serializer, this will clamp the float value");
QuantizedValues<1, 4, FloatHashMinValue, FloatHashMaxValue> quantizedValue(value);
const int32_t hashableValue = quantizedValue.GetQuantizedIntegralValues()[0];
m_hash = AZ::TypeHash64(hashableValue, m_hash);
return true;
}
bool HashSerializer::Serialize(double& value, [[maybe_unused]] const char* name, [[maybe_unused]] double minValue, [[maybe_unused]] double maxValue)
{
m_hash = AZ::TypeHash64(value, m_hash);
return true;
}
bool HashSerializer::SerializeBytes(uint8_t* buffer, uint32_t , bool, uint32_t& outSize, [[maybe_unused]] const char* name)
{
m_hash = AZ::TypeHash64(buffer, outSize, m_hash);
return true;
}
bool HashSerializer::BeginObject([[maybe_unused]] const char* name, [[maybe_unused]] const char* typeName)
{
return true;
}
bool HashSerializer::EndObject([[maybe_unused]] const char* name, [[maybe_unused]] const char* typeName)
{
return true;
}
const uint8_t* HashSerializer::GetBuffer() const
{
return nullptr;
}
uint32_t HashSerializer::GetCapacity() const
{
return 0;
}
uint32_t HashSerializer::GetSize() const
{
return 0;
}
}
@@ -0,0 +1,61 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzNetworking/Serialization/ISerializer.h>
#include <AzCore/Utils/TypeHash.h>
namespace AzNetworking
{
//! @class HashSerializer
//! @brief Generate a 32bit integer hash for a serializable object.
//! NOTE: This hash is not designed to be cryptographically secure
class HashSerializer
: public ISerializer
{
public:
HashSerializer() = default;
AZ::HashValue64 GetHash() const;
// ISerializer interfaces
SerializerMode GetSerializerMode() const override;
bool Serialize( bool& value, const char* name) override;
bool Serialize( char& value, const char* name, char minValue, char maxValue) override;
bool Serialize( int8_t& value, const char* name, int8_t minValue, int8_t maxValue) override;
bool Serialize( int16_t& value, const char* name, int16_t minValue, int16_t maxValue) override;
bool Serialize( int32_t& value, const char* name, int32_t minValue, int32_t maxValue) override;
bool Serialize( int64_t& value, const char* name, int64_t minValue, int64_t maxValue) override;
bool Serialize( uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue) override;
bool Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue) override;
bool Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue) override;
bool Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue) override;
bool Serialize( float& value, const char* name, float minValue, float maxValue) override;
bool Serialize( double& value, const char* name, double minValue, double maxValue) override;
bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) override;
bool BeginObject(const char *name, const char* typeName) override;
bool EndObject(const char *name, const char* typeName) override;
const uint8_t* GetBuffer() const override;
uint32_t GetCapacity() const override;
uint32_t GetSize() const override;
void ClearTrackedChangesFlag() override {}
bool GetTrackedChangesFlag() const override { return false; }
// ISerializer interfaces
private:
AZ::HashValue64 m_hash;
};
}
@@ -0,0 +1,202 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <stdint.h>
#include <AzCore/std/limits.h>
namespace AzNetworking
{
class IBitset;
enum class SerializerMode
{
ReadFromObject,
WriteToObject
};
//! @class ISerializer
//! @brief Interface class for all serializers to derive from.
class ISerializer
{
public:
ISerializer() = default;
virtual ~ISerializer() = default;
//! Returns true if the serializer is valid and in a consistent state.
//! @return boolean true if the serializer is valid and in a consistent state
virtual bool IsValid() const;
//! Mark the serializer as invalid.
void Invalidate();
//! Returns an enum the represents the serializer mode.
//! returns WriteToObject if the serializer is writing values to the objects it visits, otherwise returns ReadFromObject
//! @return boolean true if the serializer is writing to objects that it visits
virtual SerializerMode GetSerializerMode() const = 0;
//! Serialize a boolean.
//! @param value boolean input value to serialize
//! @param name string name of the value being serialized
//! @return boolean true for success, false for serialization failure
virtual bool Serialize(bool& value, const char* name) = 0;
//! Serialize a character.
//! @param value character input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(char& value, const char* name, char minValue = AZStd::numeric_limits<char>::min(), char maxValue = AZStd::numeric_limits<char>::max()) = 0;
//! Serialize a signed byte.
//! @param value signed byte input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(int8_t& value, const char* name, int8_t minValue = AZStd::numeric_limits<int8_t>::min(), int8_t maxValue = AZStd::numeric_limits<int8_t>::max()) = 0;
//! Serialize a signed short.
//! @param value signed short input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(int16_t& value, const char* name, int16_t minValue = AZStd::numeric_limits<int16_t>::min(), int16_t maxValue = AZStd::numeric_limits<int16_t>::max()) = 0;
//! Serialize a signed integer.
//! @param value signed integer input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(int32_t& value, const char* name, int32_t minValue = AZStd::numeric_limits<int32_t>::min(), int32_t maxValue = AZStd::numeric_limits<int32_t>::max()) = 0;
//! Serialize a signed 64-bit integer.
//! @param value signed 64-bit integer input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(int64_t& value, const char* name, int64_t minValue = AZStd::numeric_limits<int64_t>::min(), int64_t maxValue = AZStd::numeric_limits<int64_t>::max()) = 0;
//! Serialize an unsigned byte.
//! @param value unsigned byte input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(uint8_t& value, const char* name, uint8_t minValue = AZStd::numeric_limits<uint8_t>::min(), uint8_t maxValue = AZStd::numeric_limits<uint8_t>::max()) = 0;
//! Serialize an unsigned short.
//! @param value signed integer short value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(uint16_t& value, const char* name, uint16_t minValue = AZStd::numeric_limits<uint16_t>::min(), uint16_t maxValue = AZStd::numeric_limits<uint16_t>::max()) = 0;
//! Serialize an unsigned integer.
//! @param value signed integer input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(uint32_t& value, const char* name, uint32_t minValue = AZStd::numeric_limits<uint32_t>::min(), uint32_t maxValue = AZStd::numeric_limits<uint32_t>::max()) = 0;
//! Serialize an unsigned 64-bit integer.
//! @param value signed 64-bit integer input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(uint64_t& value, const char* name, uint64_t minValue = AZStd::numeric_limits<uint64_t>::min(), uint64_t maxValue = AZStd::numeric_limits<uint64_t>::max()) = 0;
//! Serialize a 32-bit floating point number.
//! @param value 32-bit floating point input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(float& value, const char* name, float minValue = AZStd::numeric_limits<float>::min(), float maxValue = AZStd::numeric_limits<float>::max()) = 0;
//! Serialize a 64-bit floating point number.
//! @param value 64-bit floating point input value to serialize
//! @param name string name of the value being serialized
//! @param minValue the minimum value expected during serialization
//! @param maxValue the maximum value expected during serialization
//! @return boolean true for success, false for failure
virtual bool Serialize(double& value, const char* name, double minValue = AZStd::numeric_limits<double>::min(), double maxValue = AZStd::numeric_limits<double>::max()) = 0;
//! Serialize a raw set of bytes.
//! @param buffer buffer to serialize
//! @param bufferCapacity size of the buffer
//! @param isString true if the data being serialized is a string
//! @param outSize bytes serialized
//! @param name string name of the object
//! @return boolean true for success, false for serialization failure
virtual bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) = 0;
//! Serialize interface for deducing whether or not TYPE is an enum or an object.
//! @param value object instance to serialize
//! @param name string name of the object
//! @param typeInfo basic type information for the value being serialized
//! @return boolean true for success, false for serialization failure
template <typename TYPE>
bool Serialize(TYPE& value, const char* name);
//! Begins serializing an object.
//! @param name string name of the object
//! @param typeInfo basic type information for the value being serialized
//! @return Result. In the case of Skip, Serialize is not called.
virtual bool BeginObject(const char* name, const char* typeName) = 0;
//! Ends serializing an object.
//! @param name string name of the object
//! @param typeInfo basic type information for the value being serialized
//! @return boolean true for success, false for serialization failure
virtual bool EndObject(const char* name, const char* typeName) = 0;
//! Returns a pointer to the internal serialization buffer.
//! @return pointer to the internal serialization buffer
virtual const uint8_t* GetBuffer() const = 0;
//! Returns the total capacity serialization buffer in bytes.
//! @return total capacity serialization buffer in bytes
virtual uint32_t GetCapacity() const = 0;
//! Returns the size of the data contained in the serialization buffer in bytes.
//! @return size of the data contained in the serialization buffer in bytes
virtual uint32_t GetSize() const = 0;
//! This is a helper for network serialization.
//! It clears the track changes flag internal to some serializers
virtual void ClearTrackedChangesFlag() = 0;
//! This is a helper for network serialization.
//! It allows the owner of the serializer to query whether or not the serializer modified the state of an object during serialization
//! @return boolean true if the track changes flag is raised
virtual bool GetTrackedChangesFlag() const = 0;
protected:
template <bool IsEnum, bool IsTypeSafeIntegral>
struct SerializeHelper;
bool m_serializerValid = true; //< Here for performance reasons
};
}
#include <AzNetworking/Serialization/ISerializer.inl>
@@ -0,0 +1,178 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#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>
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;
}
};
}
#include <AzNetworking/Serialization/AzContainerSerializers.h>
@@ -0,0 +1,194 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzNetworking/Serialization/NetworkInputSerializer.h>
#include <AzNetworking/AzNetworking_Traits_Platform.h>
#include <AzNetworking/Utilities/Endian.h>
#include <AzNetworking/Utilities/NetworkIncludes.h>
#include <memory>
namespace AzNetworking
{
NetworkInputSerializer::NetworkInputSerializer(uint8_t* buffer, uint32_t bufferCapacity)
: m_bufferSize(0)
, m_bufferCapacity(bufferCapacity)
, m_buffer(buffer)
{
;
}
SerializerMode NetworkInputSerializer::GetSerializerMode() const
{
return SerializerMode::ReadFromObject;
}
bool NetworkInputSerializer::Serialize(bool& value, [[maybe_unused]] const char* name)
{
uint8_t serializeValue = (value) ? 1 : 0;
return SerializeBytes((const uint8_t*)&serializeValue, sizeof(uint8_t));
}
bool NetworkInputSerializer::Serialize(char& value, [[maybe_unused]] const char* name, char minValue, char maxValue)
{
return SerializeBoundedValue<char>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(int8_t& value, [[maybe_unused]] const char* name, int8_t minValue, int8_t maxValue)
{
return SerializeBoundedValue<int8_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(int16_t& value, [[maybe_unused]] const char* name, int16_t minValue, int16_t maxValue)
{
return SerializeBoundedValue<int16_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(int32_t& value, [[maybe_unused]] const char* name, int32_t minValue, int32_t maxValue)
{
return SerializeBoundedValue<int32_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(int64_t& value, [[maybe_unused]] const char* name, int64_t minValue, int64_t maxValue)
{
return SerializeBoundedValue<int64_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(uint8_t& value, [[maybe_unused]] const char* name, uint8_t minValue, uint8_t maxValue)
{
return SerializeBoundedValue<uint8_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(uint16_t& value, [[maybe_unused]] const char* name, uint16_t minValue, uint16_t maxValue)
{
return SerializeBoundedValue<uint16_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(uint32_t& value, [[maybe_unused]] const char* name, uint32_t minValue, uint32_t maxValue)
{
return SerializeBoundedValue<uint32_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(uint64_t& value, [[maybe_unused]] const char* name, uint64_t minValue, uint64_t maxValue)
{
return SerializeBoundedValue<uint64_t>(minValue, maxValue, value);
}
bool NetworkInputSerializer::Serialize(float& value, [[maybe_unused]] const char* name, [[maybe_unused]] float minValue, [[maybe_unused]] float maxValue)
{
uint32_t hostOrder = *reinterpret_cast<uint32_t*>(&value);
uint32_t networkOrder = ntohl(hostOrder);
return SerializeBytes((const uint8_t*)&networkOrder, sizeof(float));
}
bool NetworkInputSerializer::Serialize(double& value, [[maybe_unused]] const char* name, [[maybe_unused]] double minValue, [[maybe_unused]] double maxValue)
{
uint64_t hostOrder = *reinterpret_cast<uint64_t*>(&value);
uint64_t networkOrder = ntohll(hostOrder);
return SerializeBytes((const uint8_t*)&networkOrder, sizeof(double));
}
bool NetworkInputSerializer::SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, [[maybe_unused]] bool isString, uint32_t& outSize, [[maybe_unused]] const char* name)
{
return SerializeBoundedValue<uint32_t>(0, bufferCapacity, outSize) && SerializeBytes(reinterpret_cast<uint8_t*>(buffer), outSize);
}
bool NetworkInputSerializer::BeginObject([[maybe_unused]] const char* name, [[maybe_unused]] const char* typeName)
{
return true;
}
bool NetworkInputSerializer::EndObject([[maybe_unused]] const char* name, [[maybe_unused]] const char* typeName)
{
return true;
}
const uint8_t* NetworkInputSerializer::GetBuffer() const
{
return m_buffer;
}
uint32_t NetworkInputSerializer::GetCapacity() const
{
return m_bufferCapacity;
}
uint32_t NetworkInputSerializer::GetSize() const
{
return m_bufferSize;
}
template <typename ORIGINAL_TYPE>
bool NetworkInputSerializer::SerializeBoundedValue(ORIGINAL_TYPE minValue, ORIGINAL_TYPE maxValue, ORIGINAL_TYPE inputValue)
{
m_serializerValid &= (inputValue >= minValue);
m_serializerValid &= (inputValue <= maxValue);
const uint64_t valueRange = static_cast<uint64_t>(maxValue - minValue);
if (valueRange <= AZStd::numeric_limits<uint8_t>::max())
{
return SerializeBoundedValueHelper<uint8_t>(static_cast<uint8_t>(inputValue - minValue));
}
else if (valueRange <= AZStd::numeric_limits<uint16_t>::max())
{
return SerializeBoundedValueHelper<uint16_t>(static_cast<uint16_t>(inputValue - minValue));
}
else if (valueRange <= AZStd::numeric_limits<uint32_t>::max())
{
return SerializeBoundedValueHelper<uint32_t>(static_cast<uint32_t>(inputValue - minValue));
}
return SerializeBoundedValueHelper<uint64_t>(static_cast<uint64_t>(inputValue - minValue));
}
inline uint8_t HostToNetwork(uint8_t value)
{
return value;
}
inline uint16_t HostToNetwork(uint16_t value)
{
return htons(value);
}
inline uint32_t HostToNetwork(uint32_t value)
{
return htonl(value);
}
inline uint64_t HostToNetwork(uint64_t value)
{
return htonll(value);
}
template <typename SERIALIZE_TYPE>
bool NetworkInputSerializer::SerializeBoundedValueHelper(SERIALIZE_TYPE serializeValue)
{
const SERIALIZE_TYPE networkOrder = HostToNetwork(serializeValue);
return m_serializerValid && SerializeBytes((const uint8_t*)&networkOrder, sizeof(SERIALIZE_TYPE));
}
bool NetworkInputSerializer::SerializeBytes(const uint8_t* data, uint32_t count)
{
const uint32_t currSize = m_bufferSize;
const uint32_t nextSize = m_bufferSize + count;
if (!m_serializerValid || (nextSize > m_bufferCapacity))
{
// Keep the failed boolean so we can verify serialization success
m_serializerValid = false;
return false;
}
uint8_t* writeBuffer = (uint8_t*)(m_buffer + currSize);
memcpy(writeBuffer, data, count);
m_bufferSize += count;
return true;
}
}
@@ -0,0 +1,81 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzNetworking/Serialization/ISerializer.h>
namespace AzNetworking
{
//! @class NetworkInputSerializer
//! @brief Input serializer for writing an object model into a bytestream.
class NetworkInputSerializer final
: public ISerializer
{
public:
//! Constructor.
//! @param buffer input buffer to write to
//! @param bufferCapacity capacity of the buffer in bytes
NetworkInputSerializer(uint8_t* buffer, uint32_t bufferCapacity);
//! Copies the provided bytes into the serialization output buffer.
//! @param data pointer to the data buffer to copy
//! @param dataSize size of the data in bytes
//! @return boolean true on success, false if there was insufficient space to store all the data
bool CopyToBuffer(const uint8_t* data, uint32_t dataSize);
// ISerializer interfaces
SerializerMode GetSerializerMode() const override;
bool Serialize( bool& value, const char* name) override;
bool Serialize( char& value, const char* name, char minValue, char maxValue) override;
bool Serialize( int8_t& value, const char* name, int8_t minValue, int8_t maxValue) override;
bool Serialize( int16_t& value, const char* name, int16_t minValue, int16_t maxValue) override;
bool Serialize( int32_t& value, const char* name, int32_t minValue, int32_t maxValue) override;
bool Serialize( int64_t& value, const char* name, int64_t minValue, int64_t maxValue) override;
bool Serialize( uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue) override;
bool Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue) override;
bool Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue) override;
bool Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue) override;
bool Serialize( float& value, const char* name, float minValue, float maxValue) override;
bool Serialize( double& value, const char* name, double minValue, double maxValue) override;
bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) override;
bool BeginObject(const char *name, const char* typeName) override;
bool EndObject(const char *name, const char* typeName) override;
const uint8_t* GetBuffer() const override;
uint32_t GetCapacity() const override;
uint32_t GetSize() const override;
void ClearTrackedChangesFlag() override {}
bool GetTrackedChangesFlag() const override { return false; }
// ISerializer interfaces
private:
//! Private copy operator, do not allow copying instances
NetworkInputSerializer& operator=(const NetworkInputSerializer&) = delete;
template <typename ORIGINAL_TYPE>
bool SerializeBoundedValue(ORIGINAL_TYPE minValue, ORIGINAL_TYPE maxValue, ORIGINAL_TYPE inputValue);
template <typename SERIALIZE_TYPE>
bool SerializeBoundedValueHelper(SERIALIZE_TYPE serializeValue);
bool SerializeBytes(const uint8_t* data, uint32_t count);
uint32_t m_bufferSize = 0;
const uint32_t m_bufferCapacity;
const uint8_t* m_buffer;
};
}
#include <AzNetworking/Serialization/NetworkInputSerializer.inl>
@@ -0,0 +1,21 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace AzNetworking
{
inline bool NetworkInputSerializer::CopyToBuffer(const uint8_t* data, uint32_t dataSize)
{
return SerializeBytes(data, dataSize);
}
}
@@ -0,0 +1,204 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzNetworking/Serialization/NetworkOutputSerializer.h>
#include <AzNetworking/AzNetworking_Traits_Platform.h>
#include <AzNetworking/Utilities/Endian.h>
#include <AzNetworking/Utilities/NetworkIncludes.h>
namespace AzNetworking
{
NetworkOutputSerializer::NetworkOutputSerializer(const uint8_t* buffer, uint32_t bufferCapacity)
: m_bufferPosition(0)
, m_bufferCapacity(bufferCapacity)
, m_buffer(buffer)
{
;
}
SerializerMode NetworkOutputSerializer::GetSerializerMode() const
{
return SerializerMode::WriteToObject;
}
bool NetworkOutputSerializer::Serialize(bool& value, [[maybe_unused]] const char* name)
{
uint8_t byteValue = 0;
SerializeBytes((uint8_t*)&byteValue, sizeof(byteValue));
value = (byteValue > 0);
return m_serializerValid;
}
bool NetworkOutputSerializer::Serialize(char& value, [[maybe_unused]] const char* name, char minValue, char maxValue)
{
return SerializeBoundedValue<char>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(int8_t& value, [[maybe_unused]] const char* name, int8_t minValue, int8_t maxValue)
{
return SerializeBoundedValue<int8_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(int16_t& value, [[maybe_unused]] const char* name, int16_t minValue, int16_t maxValue)
{
return SerializeBoundedValue<int16_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(int32_t& value, [[maybe_unused]] const char* name, int32_t minValue, int32_t maxValue)
{
return SerializeBoundedValue<int32_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(int64_t& value, [[maybe_unused]] const char* name, int64_t minValue, int64_t maxValue)
{
return SerializeBoundedValue<int64_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(uint8_t& value, [[maybe_unused]] const char* name, uint8_t minValue, uint8_t maxValue)
{
return SerializeBoundedValue<uint8_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(uint16_t& value, [[maybe_unused]] const char* name, uint16_t minValue, uint16_t maxValue)
{
return SerializeBoundedValue<uint16_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(uint32_t& value, [[maybe_unused]] const char* name, uint32_t minValue, uint32_t maxValue)
{
return SerializeBoundedValue<uint32_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(uint64_t& value, [[maybe_unused]] const char* name, uint64_t minValue, uint64_t maxValue)
{
return SerializeBoundedValue<uint64_t>(minValue, maxValue, value);
}
bool NetworkOutputSerializer::Serialize(float& value, [[maybe_unused]] const char* name, [[maybe_unused]] float minValue, [[maybe_unused]] float maxValue)
{
uint32_t networkOrder = 0;
m_serializerValid &= SerializeBytes((uint8_t*)&networkOrder, sizeof(float));
networkOrder = ntohl(networkOrder);
value = m_serializerValid ? *reinterpret_cast<float*>(&networkOrder) : value;
return m_serializerValid;
}
bool NetworkOutputSerializer::Serialize(double& value, [[maybe_unused]] const char* name, [[maybe_unused]] double minValue, [[maybe_unused]] double maxValue)
{
uint64_t networkOrder = 0;
m_serializerValid &= SerializeBytes((uint8_t *)&networkOrder, sizeof(double));
networkOrder = ntohll(networkOrder);
value = m_serializerValid ? *reinterpret_cast<double*>(&networkOrder) : value;
return m_serializerValid;
}
bool NetworkOutputSerializer::SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, [[maybe_unused]] bool isString, uint32_t& outSize, [[maybe_unused]] const char* name)
{
return SerializeBoundedValue<uint32_t>(0, bufferCapacity, outSize) && SerializeBytes(reinterpret_cast<uint8_t*>(buffer), outSize);
}
bool NetworkOutputSerializer::BeginObject([[maybe_unused]] const char* name, [[maybe_unused]] const char* typeName)
{
return true;
}
bool NetworkOutputSerializer::EndObject([[maybe_unused]] const char* name, [[maybe_unused]] const char* typeName)
{
return true;
}
const uint8_t* NetworkOutputSerializer::GetBuffer() const
{
return m_buffer;
}
uint32_t NetworkOutputSerializer::GetCapacity() const
{
return m_bufferCapacity;
}
uint32_t NetworkOutputSerializer::GetSize() const
{
return m_bufferPosition;
}
template <typename ORIGINAL_TYPE>
bool NetworkOutputSerializer::SerializeBoundedValue(ORIGINAL_TYPE minValue, ORIGINAL_TYPE maxValue, ORIGINAL_TYPE& outValue)
{
const uint64_t valueRange = static_cast<uint64_t>(maxValue - minValue);
if (valueRange <= AZStd::numeric_limits<uint8_t>::max())
{
outValue = static_cast<ORIGINAL_TYPE>(SerializeBoundedValueHelper<uint8_t>(static_cast<uint8_t>(maxValue - minValue))) + minValue;
}
else if (valueRange <= AZStd::numeric_limits<uint16_t>::max())
{
outValue = static_cast<ORIGINAL_TYPE>(SerializeBoundedValueHelper<uint16_t>(static_cast<uint16_t>(maxValue - minValue))) + minValue;
}
else if (valueRange <= AZStd::numeric_limits<uint32_t>::max())
{
outValue = static_cast<ORIGINAL_TYPE>(SerializeBoundedValueHelper<uint32_t>(static_cast<uint32_t>(maxValue - minValue))) + minValue;
}
else
{
outValue = static_cast<ORIGINAL_TYPE>(SerializeBoundedValueHelper<uint64_t>(static_cast<uint64_t>(maxValue - minValue))) + minValue;
}
return m_serializerValid;
}
inline uint8_t NetworkToHost(uint8_t value)
{
return value;
}
inline uint16_t NetworkToHost(uint16_t value)
{
return ntohs(value);
}
inline uint32_t NetworkToHost(uint32_t value)
{
return ntohl(value);
}
inline uint64_t NetworkToHost(uint64_t value)
{
return ntohll(value);
}
template <typename SERIALIZE_TYPE>
SERIALIZE_TYPE NetworkOutputSerializer::SerializeBoundedValueHelper(SERIALIZE_TYPE maxValue)
{
SERIALIZE_TYPE result = 0;
m_serializerValid &= SerializeBytes((uint8_t*)&result, sizeof(SERIALIZE_TYPE));
result = m_serializerValid ? NetworkToHost(result) : result;
m_serializerValid &= (result <= maxValue);
return result;
}
bool NetworkOutputSerializer::SerializeBytes(uint8_t* data, uint32_t count)
{
const uint32_t currSize = m_bufferPosition;
const uint32_t nextSize = m_bufferPosition + count;
if (!m_serializerValid || (nextSize > m_bufferCapacity))
{
// Keep the failed boolean so we can verify serialization success
m_serializerValid = false;
return false;
}
const uint8_t* readBuffer = (const uint8_t*)(m_buffer + currSize);
memcpy(data, readBuffer, count);
m_bufferPosition += count;
return true;
}
}
@@ -0,0 +1,87 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzNetworking/Serialization/ISerializer.h>
namespace AzNetworking
{
//! @class NetworkOutputSerializer
//! @brief Output serializer for inflating and writing out a bytestream into an object model.
class NetworkOutputSerializer
: public ISerializer
{
public:
//! Constructor.
//! @param buffer output buffer to read from
//! @param bufferCapacity capacity of the buffer in bytes
NetworkOutputSerializer(const uint8_t* buffer, uint32_t bufferCapacity);
//! Returns the unread portion of the data stream.
//! @return the unread portion of the data stream
const uint8_t* GetUnreadData() const;
//! Returns the number of bytes not yet consumed from the serialization buffer.
//! @return number of bytes not yet consumed from the serialization buffer
uint32_t GetUnreadSize() const;
//! Returns the number of bytes consumed by serialization.
//! @return number of bytes consumed by serialization
uint32_t GetReadSize() const;
// ISerializer interfaces
SerializerMode GetSerializerMode() const override;
bool Serialize( bool& value, const char* name) override;
bool Serialize( char& value, const char* name, char minValue, char maxValue) override;
bool Serialize( int8_t& value, const char* name, int8_t minValue, int8_t maxValue) override;
bool Serialize( int16_t& value, const char* name, int16_t minValue, int16_t maxValue) override;
bool Serialize( int32_t& value, const char* name, int32_t minValue, int32_t maxValue) override;
bool Serialize( int64_t& value, const char* name, int64_t minValue, int64_t maxValue) override;
bool Serialize( uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue) override;
bool Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue) override;
bool Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue) override;
bool Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue) override;
bool Serialize( float& value, const char* name, float minValue, float maxValue) override;
bool Serialize( double& value, const char* name, double minValue, double maxValue) override;
bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) override;
bool BeginObject(const char *name, const char* typeName) override;
bool EndObject(const char *name, const char* typeName) override;
const uint8_t* GetBuffer() const override;
uint32_t GetCapacity() const override;
uint32_t GetSize() const override;
void ClearTrackedChangesFlag() override {}
bool GetTrackedChangesFlag() const override { return false; }
// ISerializer interfaces
private:
//! Private copy operator, do not allow copying instances.
NetworkOutputSerializer& operator=(const NetworkOutputSerializer&) = delete;
template <typename ORIGINAL_TYPE>
bool SerializeBoundedValue(ORIGINAL_TYPE minValue, ORIGINAL_TYPE maxValue, ORIGINAL_TYPE& outValue);
template <typename SERIALIZE_TYPE>
SERIALIZE_TYPE SerializeBoundedValueHelper(SERIALIZE_TYPE maxValue);
bool SerializeBytes(uint8_t* data, uint32_t count);
uint32_t m_bufferPosition = 0;
const uint32_t m_bufferCapacity;
const uint8_t* m_buffer;
};
}
#include <AzNetworking/Serialization/NetworkOutputSerializer.inl>
@@ -0,0 +1,31 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace AzNetworking
{
inline const uint8_t* NetworkOutputSerializer::GetUnreadData() const
{
return (const uint8_t*)(m_buffer + m_bufferPosition);
}
inline uint32_t NetworkOutputSerializer::GetUnreadSize() const
{
return (m_bufferCapacity - m_bufferPosition);
}
inline uint32_t NetworkOutputSerializer::GetReadSize() const
{
return m_bufferPosition;
}
}
@@ -0,0 +1,67 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzNetworking/DataStructures/ByteBuffer.h>
#include <AzNetworking/Serialization/ISerializer.h>
namespace AzNetworking
{
//! @class TrackChangedSerializer
//! @brief Output serializer that tracks if it actually writes changes to memory or not.
template <typename BASE_TYPE>
class TrackChangedSerializer final
: public BASE_TYPE
{
public:
//! Constructor.
//! @param buffer output buffer to read from
//! @param bufferCapacity capacity of the buffer in bytes
TrackChangedSerializer(const uint8_t* buffer, uint32_t bufferCapacity);
// ISerializer interfaces
SerializerMode GetSerializerMode() const override;
bool Serialize( bool& value, const char* name) override;
bool Serialize( char& value, const char* name, char minValue, char maxValue) override;
bool Serialize( int8_t& value, const char* name, int8_t minValue, int8_t maxValue) override;
bool Serialize( int16_t& value, const char* name, int16_t minValue, int16_t maxValue) override;
bool Serialize( int32_t& value, const char* name, int32_t minValue, int32_t maxValue) override;
bool Serialize( int64_t& value, const char* name, int64_t minValue, int64_t maxValue) override;
bool Serialize( uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue) override;
bool Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue) override;
bool Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue) override;
bool Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue) override;
bool Serialize( float& value, const char* name, float minValue, float maxValue) override;
bool Serialize( double& value, const char* name, double minValue, double maxValue) override;
bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) override;
bool BeginObject(const char *name, const char* typeName) override;
bool EndObject(const char *name, const char* typeName) override;
const uint8_t* GetBuffer() const override;
uint32_t GetCapacity() const override;
uint32_t GetSize() const override;
void ClearTrackedChangesFlag() override;
bool GetTrackedChangesFlag() const override;
// ISerializer interfaces
private:
//! Private copy operator, do not allow copying instances
TrackChangedSerializer& operator=(const TrackChangedSerializer&) = delete;
bool m_hasChanged;
};
}
#include <AzNetworking/Serialization/TrackChangedSerializer.inl>
@@ -0,0 +1,193 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace AzNetworking
{
template <typename BASE_TYPE>
TrackChangedSerializer<BASE_TYPE>::TrackChangedSerializer(const uint8_t* buffer, uint32_t bufferCapacity)
: BASE_TYPE(buffer, bufferCapacity)
, m_hasChanged(false)
{
;
}
template <typename BASE_TYPE>
SerializerMode TrackChangedSerializer<BASE_TYPE>::GetSerializerMode() const
{
return BASE_TYPE::GetSerializerMode();
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(bool& value, const char* name)
{
const bool cached = value;
const bool result = BASE_TYPE::Serialize(value, name);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(char& value, const char* name, char minValue, char maxValue)
{
const char cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(int8_t& value, const char* name, int8_t minValue, int8_t maxValue)
{
const int8_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(int16_t& value, const char* name, int16_t minValue, int16_t maxValue)
{
const int16_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(int32_t& value, const char* name, int32_t minValue, int32_t maxValue)
{
const int32_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(int64_t& value, const char* name, int64_t minValue, int64_t maxValue)
{
const int64_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue)
{
const uint8_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue)
{
const uint16_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue)
{
const uint32_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue)
{
const uint64_t cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(float& value, const char* name, float minValue, float maxValue)
{
const float cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::Serialize(double& value, const char* name, double minValue, double maxValue)
{
const double cached = value;
const bool result = BASE_TYPE::Serialize(value, name, minValue, maxValue);
m_hasChanged |= (cached != value);
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name)
{
ByteBuffer<16384> cached;
if (!cached.CopyValues(buffer, outSize))
{
return false;
}
const bool result = BASE_TYPE::SerializeBytes(buffer, bufferCapacity, isString, outSize, name);
m_hasChanged |= (cached.IsSame(buffer, outSize));
return result;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::BeginObject(const char* name, const char* typeName)
{
return BASE_TYPE::BeginObject(name, typeName);
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::EndObject(const char* name, const char* typeName)
{
return BASE_TYPE::EndObject(name, typeName);
}
template <typename BASE_TYPE>
const uint8_t* TrackChangedSerializer<BASE_TYPE>::GetBuffer() const
{
return BASE_TYPE::GetBuffer();
}
template <typename BASE_TYPE>
uint32_t TrackChangedSerializer<BASE_TYPE>::GetCapacity() const
{
return BASE_TYPE::GetCapacity();
}
template <typename BASE_TYPE>
uint32_t TrackChangedSerializer<BASE_TYPE>::GetSize() const
{
return BASE_TYPE::GetSize();
}
template <typename BASE_TYPE>
void TrackChangedSerializer<BASE_TYPE>::ClearTrackedChangesFlag()
{
m_hasChanged = false;
}
template <typename BASE_TYPE>
bool TrackChangedSerializer<BASE_TYPE>::GetTrackedChangesFlag() const
{
return m_hasChanged;
}
}