Fixed initialization of math types for Json Serialization

Several math types in AzCore deliberately don't initialize through a constructor. This set of changes make sure that they still get properly initialized in the Json Serialization instead having random values.
This commit is contained in:
AMZN-koppersr
2021-06-14 09:55:24 -07:00
parent bc5fc9a191
commit 08abc497f3
10 changed files with 150 additions and 83 deletions
@@ -36,6 +36,12 @@ namespace AZ
Color* color = reinterpret_cast<Color*>(outputValue);
AZ_Assert(color, "Output value for JsonColorSerializer can't be null.");
if (IsExplicitDefault(inputValue))
{
*color = Color::CreateZero();
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Color value set to default of zero.");
}
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
@@ -43,10 +49,14 @@ namespace AZ
case rapidjson::kObjectType:
return LoadObject(*color, inputValue, context);
case rapidjson::kStringType: // fall through
case rapidjson::kNumberType: // fall through
case rapidjson::kNullType: // fall through
case rapidjson::kFalseType: // fall through
case rapidjson::kStringType:
[[fallthrough]];
case rapidjson::kNumberType:
[[fallthrough]];
case rapidjson::kNullType:
[[fallthrough]];
case rapidjson::kFalseType:
[[fallthrough]];
case rapidjson::kTrueType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Colors can only be read from arrays or objects.");
@@ -91,6 +101,11 @@ namespace AZ
}
}
auto JsonColorSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
JsonSerializationResult::Result JsonColorSerializer::LoadObject(Color& output, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
@@ -28,6 +28,8 @@ namespace AZ
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
OperationFlags GetOperationsFlags() const override;
private:
enum class LoadAlpha
{
@@ -263,7 +263,7 @@ namespace AZ::JsonMathMatrixSerializerInternal
template<typename MatrixType, size_t RowCount, size_t ColumnCount>
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
const rapidjson::Value& inputValue, JsonDeserializerContext& context, bool isExplicitDefault)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
@@ -279,6 +279,12 @@ namespace AZ::JsonMathMatrixSerializerInternal
MatrixType* matrix = reinterpret_cast<MatrixType*>(outputValue);
AZ_Assert(matrix, "Output value for JsonMatrix%zux%zuSerializer can't be null.", RowCount, ColumnCount);
if (isExplicitDefault)
{
*matrix = MatrixType::CreateIdentity();
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Matrix value set to identity matrix.");
}
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
@@ -381,6 +387,16 @@ namespace AZ::JsonMathMatrixSerializerInternal
namespace AZ
{
// BaseJsonMatrixSerializer
AZ_CLASS_ALLOCATOR_IMPL(BaseJsonMatrixSerializer, SystemAllocator, 0);
auto BaseJsonMatrixSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
// Matrix3x3
AZ_CLASS_ALLOCATOR_IMPL(JsonMatrix3x3Serializer, SystemAllocator, 0);
@@ -389,10 +405,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathMatrixSerializerInternal::Load<Matrix3x3, 3, 3>(
outputValue,
outputValueTypeId,
inputValue,
context);
outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonMatrix3x3Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -401,11 +414,7 @@ namespace AZ
outputValue.SetObject();
return JsonMathMatrixSerializerInternal::StoreRotationAndScale<Matrix3x3>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
outputValue, inputValue, defaultValue, valueTypeId, context);
}
@@ -417,10 +426,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathMatrixSerializerInternal::Load<Matrix3x4, 3, 4>(
outputValue,
outputValueTypeId,
inputValue,
context);
outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonMatrix3x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -428,19 +434,11 @@ namespace AZ
{
outputValue.SetObject();
auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale<Matrix3x4>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
auto result =
JsonMathMatrixSerializerInternal::StoreRotationAndScale<Matrix3x4>(outputValue, inputValue, defaultValue, valueTypeId, context);
auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation<Matrix3x4>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
auto resultTranslation =
JsonMathMatrixSerializerInternal::StoreTranslation<Matrix3x4>(outputValue, inputValue, defaultValue, valueTypeId, context);
result.GetResultCode().Combine(resultTranslation);
return result;
@@ -454,10 +452,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathMatrixSerializerInternal::Load<Matrix4x4, 4, 4>(
outputValue,
outputValueTypeId,
inputValue,
context);
outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonMatrix4x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -465,19 +460,11 @@ namespace AZ
{
outputValue.SetObject();
auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale<Matrix4x4>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
auto result =
JsonMathMatrixSerializerInternal::StoreRotationAndScale<Matrix4x4>(outputValue, inputValue, defaultValue, valueTypeId, context);
auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation<Matrix4x4>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
auto resultTranslation =
JsonMathMatrixSerializerInternal::StoreTranslation<Matrix4x4>(outputValue, inputValue, defaultValue, valueTypeId, context);
result.GetResultCode().Combine(resultTranslation);
return result;
@@ -16,11 +16,18 @@
namespace AZ
{
class JsonMatrix3x3Serializer
: public BaseJsonSerializer
class BaseJsonMatrixSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonMatrix3x3Serializer, "{8C76CD6A-8576-4604-A746-CF7A7F20F366}", BaseJsonSerializer);
AZ_RTTI(BaseJsonMatrixSerializer, "{18CA4637-C9B7-454B-9126-107E18A8C096}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
OperationFlags GetOperationsFlags() const override;
};
class JsonMatrix3x3Serializer : public BaseJsonMatrixSerializer
{
public:
AZ_RTTI(JsonMatrix3x3Serializer, "{8C76CD6A-8576-4604-A746-CF7A7F20F366}", BaseJsonMatrixSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -28,11 +35,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonMatrix3x4Serializer
: public BaseJsonSerializer
class JsonMatrix3x4Serializer : public BaseJsonMatrixSerializer
{
public:
AZ_RTTI(JsonMatrix3x4Serializer, "{E801333B-4AF1-4F43-976C-579670B02DC5}", BaseJsonSerializer);
AZ_RTTI(JsonMatrix3x4Serializer, "{E801333B-4AF1-4F43-976C-579670B02DC5}", BaseJsonMatrixSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -40,11 +46,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonMatrix4x4Serializer
: public BaseJsonSerializer
class JsonMatrix4x4Serializer : public BaseJsonMatrixSerializer
{
public:
AZ_RTTI(JsonMatrix4x4Serializer, "{46E888FC-248A-4910-9221-4E101A10AEA1}", BaseJsonSerializer);
AZ_RTTI(JsonMatrix4x4Serializer, "{46E888FC-248A-4910-9221-4E101A10AEA1}", BaseJsonMatrixSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -124,7 +124,7 @@ namespace AZ
template<typename VectorType, size_t ElementCount>
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
JsonDeserializerContext& context, bool isExplicitDefault)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
@@ -138,6 +138,12 @@ namespace AZ
VectorType* vector = reinterpret_cast<VectorType*>(outputValue);
AZ_Assert(vector, "Output value for JsonVector%iSerializer can't be null.", ElementCount);
if (isExplicitDefault)
{
*vector = VectorType::CreateZero();
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Math vector value set to default of zero.");
}
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
@@ -145,10 +151,14 @@ namespace AZ
case rapidjson::kObjectType:
return LoadObject<VectorType, ElementCount>(*vector, inputValue, context);
case rapidjson::kStringType: // fall through
case rapidjson::kNumberType: // fall through
case rapidjson::kNullType: // fall through
case rapidjson::kFalseType: // fall through
case rapidjson::kStringType:
[[fallthrough]];
case rapidjson::kNumberType:
[[fallthrough]];
case rapidjson::kNullType:
[[fallthrough]];
case rapidjson::kFalseType:
[[fallthrough]];
case rapidjson::kTrueType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Math vectors can only be read from arrays or objects.");
@@ -189,6 +199,16 @@ namespace AZ
}
}
// BaseJsonVectorSerializer
AZ_CLASS_ALLOCATOR_IMPL(BaseJsonVectorSerializer, SystemAllocator, 0);
auto BaseJsonVectorSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
// Vector2
@@ -197,7 +217,8 @@ namespace AZ
JsonSerializationResult::Result JsonVector2Serializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathVectorSerializerInternal::Load<Vector2, 2>(outputValue, outputValueTypeId, inputValue, context);
return JsonMathVectorSerializerInternal::Load<Vector2, 2>(
outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonVector2Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -214,7 +235,8 @@ namespace AZ
JsonSerializationResult::Result JsonVector3Serializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathVectorSerializerInternal::Load<Vector3, 3>(outputValue, outputValueTypeId, inputValue, context);
return JsonMathVectorSerializerInternal::Load<Vector3, 3>(
outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonVector3Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -231,7 +253,8 @@ namespace AZ
JsonSerializationResult::Result JsonVector4Serializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathVectorSerializerInternal::Load<Vector4, 4>(outputValue, outputValueTypeId, inputValue, context);
return JsonMathVectorSerializerInternal::Load<Vector4, 4>(
outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonVector4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -252,7 +275,7 @@ namespace AZ
// check for "yaw, pitch, roll" object
if (inputValue.IsObject())
{
if (inputValue.GetObject().ObjectEmpty())
if (IsExplicitDefault(inputValue))
{
Quaternion* outQuaternion = reinterpret_cast<Quaternion*>(outputValue);
*outQuaternion = Quaternion::CreateIdentity();
@@ -283,7 +306,7 @@ namespace AZ
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read quaternion.");
}
return JsonMathVectorSerializerInternal::Load<Quaternion, 4>(outputValue, outputValueTypeId, inputValue, context);
return JsonMathVectorSerializerInternal::Load<Quaternion, 4>(outputValue, outputValueTypeId, inputValue, context, false);
}
JsonSerializationResult::Result JsonQuaternionSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -16,11 +16,18 @@
namespace AZ
{
class JsonVector2Serializer
: public BaseJsonSerializer
class BaseJsonVectorSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonVector2Serializer, "{E1EAA209-9682-4120-B26B-3EDD9AD56D6F}", BaseJsonSerializer);
AZ_RTTI(BaseJsonVectorSerializer, "{C188D355-E6DF-4590-8B31-F40591F48A8E}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
OperationFlags GetOperationsFlags() const override;
};
class JsonVector2Serializer : public BaseJsonVectorSerializer
{
public:
AZ_RTTI(JsonVector2Serializer, "{E1EAA209-9682-4120-B26B-3EDD9AD56D6F}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -28,11 +35,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonVector3Serializer
: public BaseJsonSerializer
class JsonVector3Serializer : public BaseJsonVectorSerializer
{
public:
AZ_RTTI(JsonVector3Serializer, "{BF82BBF3-3CD9-48DA-97CC-E4DF2EF01552}", BaseJsonSerializer);
AZ_RTTI(JsonVector3Serializer, "{BF82BBF3-3CD9-48DA-97CC-E4DF2EF01552}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -40,11 +46,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonVector4Serializer
: public BaseJsonSerializer
class JsonVector4Serializer : public BaseJsonVectorSerializer
{
public:
AZ_RTTI(JsonVector4Serializer, "{05B45EA7-7102-4281-8AA0-2AC72D74AAFD}", BaseJsonSerializer);
AZ_RTTI(JsonVector4Serializer, "{05B45EA7-7102-4281-8AA0-2AC72D74AAFD}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -52,11 +57,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonQuaternionSerializer
: public BaseJsonSerializer
class JsonQuaternionSerializer : public BaseJsonVectorSerializer
{
public:
AZ_RTTI(JsonQuaternionSerializer, "{18604375-3606-49AC-B366-0F6DF9149FF3}", BaseJsonSerializer);
AZ_RTTI(JsonQuaternionSerializer, "{18604375-3606-49AC-B366-0F6DF9149FF3}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -33,6 +33,12 @@ namespace AZ
AZ::Transform* transformInstance = reinterpret_cast<AZ::Transform*>(outputValue);
AZ_Assert(transformInstance, "Output value for JsonTransformSerializer can't be null.");
if (IsExplicitDefault(inputValue))
{
*transformInstance = AZ::Transform::CreateIdentity();
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Transform value set to identity.");
}
JSR::ResultCode result(JSR::Tasks::ReadField);
{
@@ -72,7 +78,7 @@ namespace AZ
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded Transform information."
result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded Transform information."
: "Failed to load Transform information.");
}
@@ -140,4 +146,9 @@ namespace AZ
: "Failed to store Transform information.");
}
auto JsonTransformSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
} // namespace AZ
@@ -30,6 +30,8 @@ namespace AZ
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
JsonSerializerContext& context) override;
OperationFlags GetOperationsFlags() const override;
private:
// Note: These need to be defined as "const char[]" instead of "const char*" so that they can be implicitly converted
// to a rapidjson::GenericStringRef<>. (This also lets rapidjson get the string length at compile time)
@@ -33,6 +33,11 @@ namespace AZ
AZStd::regex_constants::icase | AZStd::regex_constants::optimize);
}
auto JsonUuidSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
JsonSerializationResult::Result JsonUuidSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
@@ -53,13 +58,24 @@ namespace AZ
Uuid* valAsUuid = reinterpret_cast<Uuid*>(outputValue);
if (IsExplicitDefault(inputValue))
{
*valAsUuid = AZ::Uuid::CreateNull();
return MessageResult("Uuid value set to default of null.", JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed));
}
switch (inputValue.GetType())
{
case rapidjson::kArrayType: // fallthrough
case rapidjson::kObjectType:// fallthrough
case rapidjson::kFalseType: // fallthrough
case rapidjson::kTrueType: // fallthrough
case rapidjson::kNumberType:// fallthrough
case rapidjson::kArrayType:
[[fallthrough]];
case rapidjson::kObjectType:
[[fallthrough]];
case rapidjson::kFalseType:
[[fallthrough]];
case rapidjson::kTrueType:
[[fallthrough]];
case rapidjson::kNumberType:
[[fallthrough]];
case rapidjson::kNullType:
return MessageResult("Unsupported type. Uuids can only be read from strings.",
JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported));
@@ -41,6 +41,8 @@ namespace AZ
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
OperationFlags GetOperationsFlags() const override;
//! Does the same as load, but doesn't report through the provided callback in the settings. Instead the final
//! ResultCode and message are returned and it's up to the caller to report if need needed.
MessageResult UnreportedLoad(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue);