From 68368ce1e47feb8cbc32f4069ba16a004cd5fd3c Mon Sep 17 00:00:00 2001 From: Snigdha Date: Thu, 13 Aug 2026 12:33:45 -0400 Subject: [PATCH 1/4] spling Schema into a base class with a builder and factories --- .../include/smithy/client/schema/Schema.h | 85 +++- .../smithy/client/schema/SchemaBuilder.h | 40 ++ .../source/smithy/client/schema/Schema.cpp | 297 ++++++++++++ .../schema/CborShapeDeserializerTest.cpp | 153 +++--- .../client/schema/CborShapeSerializerTest.cpp | 455 +++++++++--------- .../client/schema/JsonShapeSerializerTest.cpp | 389 +++++++-------- .../client/schema/XmlShapeSerializerTest.cpp | 416 ++++++++-------- 7 files changed, 1104 insertions(+), 731 deletions(-) create mode 100644 src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h create mode 100644 src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h index 83c392dfa6d2..3df44acda3ea 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h @@ -1,14 +1,18 @@ #pragma once #include +#include #include #include +#include #include namespace smithy { namespace schema { +class SchemaBuilder; + enum class ShapeType : uint8_t { Boolean, Byte, @@ -34,21 +38,34 @@ enum class ShapeType : uint8_t { Service }; -class Schema { +// A single trait supplied at construction time. Schemas are immutable once +// built, so traits are attached through the factories and SchemaBuilder rather +// than mutated afterwards. +struct TraitEntry { + const TraitKeyBase& key; + std::shared_ptr value; +}; +using TraitList = std::initializer_list; + +// Abstract, immutable description of a shape. Concrete variants (scalar, member, +// structure/list/map/union root) live in the translation unit and are reached +// only through the factories below and SchemaBuilder. Serializers and +// deserializers hold a Schema only by const reference. +class SMITHY_API Schema { public: - Schema() = default; - Schema(const Aws::String& memberName, ShapeType type) : m_type(type), m_memberName(memberName) {} + virtual ~Schema() = default; - ShapeType GetType() const { return m_type; } - const char* GetId() const { return m_id; } - Aws::String GetMemberName() const { return m_memberName; } - int GetMemberIndex() const { return m_memberIndex; } - bool IsMember() const { return !m_memberName.empty(); } + virtual ShapeType GetType() const = 0; + virtual const char* GetId() const = 0; - const Schema* GetMember(const char* name) const; - const Schema* GetMember(int index) const; + virtual bool IsMember() const { return false; } + virtual Aws::String GetMemberName() const { return {}; } + virtual int GetMemberIndex() const { return 0; } + virtual const Schema* GetMemberTarget() const { return nullptr; } - uint16_t GetMemberCount() const { return m_memberCount; } + virtual const Schema* GetMember(const char* /*name*/) const { return nullptr; } + virtual const Schema* GetMember(int /*index*/) const { return nullptr; } + virtual uint16_t GetMemberCount() const { return 0; } template std::shared_ptr GetTrait(const TraitKey& key) const { @@ -57,19 +74,43 @@ class Schema { bool HasTrait(const TraitKeyBase& key) const { return m_traits.Has(key); } - Schema& SetTrait(const TraitKeyBase& key, std::shared_ptr trait) { - m_traits.Set(key, std::move(trait)); - return *this; - } + // Scalar factories. No members, so no builder is needed. + static std::shared_ptr CreateBoolean(const char* id, TraitList traits = {}); + static std::shared_ptr CreateByte(const char* id, TraitList traits = {}); + static std::shared_ptr CreateShort(const char* id, TraitList traits = {}); + static std::shared_ptr CreateInteger(const char* id, TraitList traits = {}); + static std::shared_ptr CreateLong(const char* id, TraitList traits = {}); + static std::shared_ptr CreateFloat(const char* id, TraitList traits = {}); + static std::shared_ptr CreateDouble(const char* id, TraitList traits = {}); + static std::shared_ptr CreateBigInteger(const char* id, TraitList traits = {}); + static std::shared_ptr CreateBigDecimal(const char* id, TraitList traits = {}); + static std::shared_ptr CreateString(const char* id, TraitList traits = {}); + static std::shared_ptr CreateEnum(const char* id, TraitList traits = {}); + static std::shared_ptr CreateIntEnum(const char* id, TraitList traits = {}); + static std::shared_ptr CreateBlob(const char* id, TraitList traits = {}); + static std::shared_ptr CreateTimestamp(const char* id, TraitList traits = {}); + static std::shared_ptr CreateDocument(const char* id, TraitList traits = {}); + + // Standalone member node targeting an (otherwise empty) shape of targetType. + // Convenience for the positional serializer/deserializer API, where a caller + // hands members one at a time rather than driving them off a parent shape. + static std::shared_ptr CreateMember(const char* name, ShapeType targetType, TraitList traits = {}); + + // Aggregate builders. Shapes that carry members are assembled incrementally. + static SchemaBuilder StructureBuilder(const char* id, TraitList traits = {}); + static SchemaBuilder UnionBuilder(const char* id, TraitList traits = {}); + static SchemaBuilder ListBuilder(const char* id, TraitList traits = {}); + static SchemaBuilder MapBuilder(const char* id, TraitList traits = {}); + + protected: + Schema() = default; + explicit Schema(TraitList traits); - private: - const char* m_id = nullptr; - ShapeType m_type = ShapeType::Structure; - Aws::String m_memberName; - int m_memberIndex = 0; - const Schema* m_members = nullptr; - uint16_t m_memberCount = 0; TraitMap m_traits; + + private: + Schema(const Schema&) = delete; + Schema& operator=(const Schema&) = delete; }; } // namespace schema diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h new file mode 100644 index 000000000000..f986359cacfa --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include + +#include + +namespace smithy { +namespace schema { + +// Assembles a shape that carries members (structure, union, list, map). Members +// may target shapes that are already built, or other builders that are not yet +// built to describe recursive shapes. Once Build() is called the builder is +// spent. Move-only; obtained from Schema::StructureBuilder and friends. +class SMITHY_API SchemaBuilder { + public: + ~SchemaBuilder(); + SchemaBuilder(SchemaBuilder&&) noexcept; + SchemaBuilder& operator=(SchemaBuilder&&) noexcept; + + SchemaBuilder& PutMember(const char* name, std::shared_ptr target, TraitList traits = {}); + SchemaBuilder& PutMember(const char* name, SchemaBuilder& target, TraitList traits = {}); + + std::shared_ptr Build(); + + private: + friend class Schema; + class SchemaBuilderImpl; + + explicit SchemaBuilder(Aws::UniquePtr impl); + + Aws::UniquePtr m_impl; + + SchemaBuilder(const SchemaBuilder&) = delete; + SchemaBuilder& operator=(const SchemaBuilder&) = delete; +}; + +} // namespace schema +} // namespace smithy diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp new file mode 100644 index 000000000000..98b3a3bcf615 --- /dev/null +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp @@ -0,0 +1,297 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include +#include +#include +#include + +#include + +namespace smithy { +namespace schema { + +namespace { + +const char SCHEMA_ALLOC_TAG[] = "SmithySchema"; + +TraitMap ToTraitMap(TraitList traits) { + TraitMap map; + for (const auto& entry : traits) { + map.Set(entry.key, entry.value); + } + return map; +} + +// Compose a member id from its containing shape id and member name, e.g. +// "com.example#Foo$bar". Purely informational; used for GetId(). +Aws::String MakeMemberId(const Aws::String& shapeId, const Aws::String& memberName) { + Aws::String id = shapeId; + id += "$"; + id += memberName; + return id; +} + +// A leaf shape with no members. +class ScalarSchema final : public Schema { + public: + ScalarSchema(ShapeType type, const char* id, TraitList traits) + : Schema(traits), m_type(type), m_id(id) {} + + ShapeType GetType() const override { return m_type; } + const char* GetId() const override { return m_id.c_str(); } + + private: + ShapeType m_type; + Aws::String m_id; +}; + +// A named member of an aggregate shape. Delegates its type to the shape it +// targets. A member normally owns its target; the non-owning overload is used +// only for recursive members, where the target is kept alive by the definition +// site so the graph does not form a reference cycle. +class MemberSchema final : public Schema { + public: + MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::shared_ptr target, + TraitMap traits) + : m_memberName(name), m_id(id), m_memberIndex(index), m_ownedTarget(std::move(target)), + m_target(m_ownedTarget.get()) { + m_traits = std::move(traits); + } + + MemberSchema(const Aws::String& name, const Aws::String& id, int index, const Schema* target, TraitMap traits) + : m_memberName(name), m_id(id), m_memberIndex(index), m_target(target) { + m_traits = std::move(traits); + } + + ShapeType GetType() const override { return m_target ? m_target->GetType() : ShapeType::Structure; } + const char* GetId() const override { return m_id.c_str(); } + bool IsMember() const override { return true; } + Aws::String GetMemberName() const override { return m_memberName; } + int GetMemberIndex() const override { return m_memberIndex; } + const Schema* GetMemberTarget() const override { return m_target; } + + private: + Aws::String m_memberName; + Aws::String m_id; + int m_memberIndex; + std::shared_ptr m_ownedTarget; + const Schema* m_target; +}; + +// A shape that carries members (structure, union, list, map). Owns its member +// nodes and any eagerly-built target shapes; recursively referenced targets are +// kept alive by the definition site, not by this shape. +class RootSchema final : public Schema { + public: + RootSchema(ShapeType type, const Aws::String& id, TraitMap traits) : m_type(type), m_id(id) { + m_traits = std::move(traits); + } + + ShapeType GetType() const override { return m_type; } + const char* GetId() const override { return m_id.c_str(); } + + const Schema* GetMember(const char* name) const override { + auto it = m_nameToIndex.find(name); + if (it == m_nameToIndex.end()) { + return nullptr; + } + return m_members[it->second].get(); + } + + const Schema* GetMember(int index) const override { + if (index < 0 || static_cast(index) >= m_members.size()) { + return nullptr; + } + return m_members[index].get(); + } + + uint16_t GetMemberCount() const override { return static_cast(m_members.size()); } + + // Used only by SchemaBuilder while assembling the shape. + void AddMember(const std::shared_ptr& member) { + m_nameToIndex[member->GetMemberName()] = static_cast(m_members.size()); + m_members.push_back(member); + } + + private: + ShapeType m_type; + Aws::String m_id; + Aws::Vector> m_members; + Aws::Map m_nameToIndex; +}; + +std::shared_ptr MakeScalar(ShapeType type, const char* id, TraitList traits) { + return Aws::MakeShared(SCHEMA_ALLOC_TAG, type, id, traits); +} + +// An empty shape of the given type, used as the target of a standalone member. +std::shared_ptr MakeEmptyShape(ShapeType type, const char* id) { + switch (type) { + case ShapeType::Structure: + case ShapeType::Union: + case ShapeType::List: + case ShapeType::Map: + return Aws::MakeShared(SCHEMA_ALLOC_TAG, type, Aws::String(id), TraitMap()); + default: + return Aws::MakeShared(SCHEMA_ALLOC_TAG, type, id, TraitList{}); + } +} + +} // namespace + +Schema::Schema(TraitList traits) : m_traits(ToTraitMap(traits)) {} + +std::shared_ptr Schema::CreateBoolean(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Boolean, id, traits); +} +std::shared_ptr Schema::CreateByte(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Byte, id, traits); +} +std::shared_ptr Schema::CreateShort(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Short, id, traits); +} +std::shared_ptr Schema::CreateInteger(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Integer, id, traits); +} +std::shared_ptr Schema::CreateLong(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Long, id, traits); +} +std::shared_ptr Schema::CreateFloat(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Float, id, traits); +} +std::shared_ptr Schema::CreateDouble(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Double, id, traits); +} +std::shared_ptr Schema::CreateBigInteger(const char* id, TraitList traits) { + return MakeScalar(ShapeType::BigInteger, id, traits); +} +std::shared_ptr Schema::CreateBigDecimal(const char* id, TraitList traits) { + return MakeScalar(ShapeType::BigDecimal, id, traits); +} +std::shared_ptr Schema::CreateString(const char* id, TraitList traits) { + return MakeScalar(ShapeType::String, id, traits); +} +std::shared_ptr Schema::CreateEnum(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Enum, id, traits); +} +std::shared_ptr Schema::CreateIntEnum(const char* id, TraitList traits) { + return MakeScalar(ShapeType::IntEnum, id, traits); +} +std::shared_ptr Schema::CreateBlob(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Blob, id, traits); +} +std::shared_ptr Schema::CreateTimestamp(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Timestamp, id, traits); +} +std::shared_ptr Schema::CreateDocument(const char* id, TraitList traits) { + return MakeScalar(ShapeType::Document, id, traits); +} + +std::shared_ptr Schema::CreateMember(const char* name, ShapeType targetType, TraitList traits) { + return Aws::MakeShared(SCHEMA_ALLOC_TAG, Aws::String(name), Aws::String(name), 0, + MakeEmptyShape(targetType, name), ToTraitMap(traits)); +} + +// A pending member captured before Build(). Exactly one of eagerTarget / +// deferredTarget is set. +class SchemaBuilder::SchemaBuilderImpl { + public: + SchemaBuilderImpl(ShapeType type, const char* id, TraitList traits) + : m_type(type), m_id(id), m_traits(ToTraitMap(traits)) {} + + struct PendingMember { + Aws::String name; + TraitMap traits; + std::shared_ptr eagerTarget; + SchemaBuilderImpl* deferredTarget = nullptr; + }; + + void AddMember(const char* name, std::shared_ptr target, TraitList traits) { + PendingMember member; + member.name = name; + member.traits = ToTraitMap(traits); + member.eagerTarget = std::move(target); + m_members.push_back(std::move(member)); + } + + void AddMember(const char* name, SchemaBuilderImpl* target, TraitList traits) { + PendingMember member; + member.name = name; + member.traits = ToTraitMap(traits); + member.deferredTarget = target; + m_members.push_back(std::move(member)); + } + + std::shared_ptr Build() { + if (m_builtShape) { + return m_builtShape; + } + + // Publish the shell before resolving members so a member that targets this + // same shape (directly or transitively) sees the in-progress shape rather + // than recursing forever. + auto shell = Aws::MakeShared(SCHEMA_ALLOC_TAG, m_type, m_id, m_traits); + m_builtShape = shell; + + int index = 0; + for (auto& pending : m_members) { + std::shared_ptr member; + if (pending.eagerTarget) { + // Non-recursive member owns its target directly. + member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, + pending.eagerTarget, pending.traits); + } else if (pending.deferredTarget != nullptr) { + // Recursive member references a target kept alive by the definition site. + auto target = pending.deferredTarget->Build(); + member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, + target.get(), pending.traits); + } + shell->AddMember(member); + ++index; + } + + return m_builtShape; + } + + private: + ShapeType m_type; + Aws::String m_id; + TraitMap m_traits; + Aws::Vector m_members; + std::shared_ptr m_builtShape; +}; + +SchemaBuilder Schema::StructureBuilder(const char* id, TraitList traits) { + return SchemaBuilder(Aws::MakeUnique(SCHEMA_ALLOC_TAG, ShapeType::Structure, id, traits)); +} +SchemaBuilder Schema::UnionBuilder(const char* id, TraitList traits) { + return SchemaBuilder(Aws::MakeUnique(SCHEMA_ALLOC_TAG, ShapeType::Union, id, traits)); +} +SchemaBuilder Schema::ListBuilder(const char* id, TraitList traits) { + return SchemaBuilder(Aws::MakeUnique(SCHEMA_ALLOC_TAG, ShapeType::List, id, traits)); +} +SchemaBuilder Schema::MapBuilder(const char* id, TraitList traits) { + return SchemaBuilder(Aws::MakeUnique(SCHEMA_ALLOC_TAG, ShapeType::Map, id, traits)); +} + +SchemaBuilder::SchemaBuilder(Aws::UniquePtr impl) : m_impl(std::move(impl)) {} +SchemaBuilder::~SchemaBuilder() = default; +SchemaBuilder::SchemaBuilder(SchemaBuilder&&) noexcept = default; +SchemaBuilder& SchemaBuilder::operator=(SchemaBuilder&&) noexcept = default; + +SchemaBuilder& SchemaBuilder::PutMember(const char* name, std::shared_ptr target, TraitList traits) { + m_impl->AddMember(name, std::move(target), traits); + return *this; +} + +SchemaBuilder& SchemaBuilder::PutMember(const char* name, SchemaBuilder& target, TraitList traits) { + m_impl->AddMember(name, target.m_impl.get(), traits); + return *this; +} + +std::shared_ptr SchemaBuilder::Build() { return m_impl->Build(); } + +} // namespace schema +} // namespace smithy diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp index a08539687eaa..cdd1a391eb4e 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace smithy::schema; @@ -16,10 +17,10 @@ class CborShapeDeserializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; TEST_F(CborShapeDeserializerTest, BooleanTrue) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("enabled"); - s.WriteBoolean(root, true); + s.WriteBoolean(*root, true); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -38,10 +39,10 @@ TEST_F(CborShapeDeserializerTest, BooleanTrue) { TEST_F(CborShapeDeserializerTest, BooleanFalse) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("ok"); - s.WriteBoolean(root, false); + s.WriteBoolean(*root, false); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -59,10 +60,10 @@ TEST_F(CborShapeDeserializerTest, BooleanFalse) { TEST_F(CborShapeDeserializerTest, IntegerSmall) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(root, 7); + s.WriteInteger(*root, 7); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -80,10 +81,10 @@ TEST_F(CborShapeDeserializerTest, IntegerSmall) { TEST_F(CborShapeDeserializerTest, IntegerNegative) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(root, -42); + s.WriteInteger(*root, -42); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -101,10 +102,10 @@ TEST_F(CborShapeDeserializerTest, IntegerNegative) { TEST_F(CborShapeDeserializerTest, LongValue) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("big"); - s.WriteLong(root, 5000000000LL); + s.WriteLong(*root, 5000000000LL); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -122,10 +123,10 @@ TEST_F(CborShapeDeserializerTest, LongValue) { TEST_F(CborShapeDeserializerTest, DoubleValue) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("d"); - s.WriteDouble(root, 3.14); + s.WriteDouble(*root, 3.14); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -144,10 +145,10 @@ TEST_F(CborShapeDeserializerTest, DoubleValue) { TEST_F(CborShapeDeserializerTest, DoubleWholeNumber) { // CRT encodes 5.0 as integer 5 — deserializer must handle this CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("d"); - s.WriteDouble(root, 5.0); + s.WriteDouble(*root, 5.0); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -165,10 +166,10 @@ TEST_F(CborShapeDeserializerTest, DoubleWholeNumber) { TEST_F(CborShapeDeserializerTest, FloatValue) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("f"); - s.WriteFloat(root, 1.5f); + s.WriteFloat(*root, 1.5f); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -186,10 +187,10 @@ TEST_F(CborShapeDeserializerTest, FloatValue) { TEST_F(CborShapeDeserializerTest, StringValue) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("name"); - s.WriteString(root, "hello"); + s.WriteString(*root, "hello"); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -207,15 +208,15 @@ TEST_F(CborShapeDeserializerTest, StringValue) { TEST_F(CborShapeDeserializerTest, BlobValue) { CborShapeSerializer s; - Schema root; + auto root = Schema::StructureBuilder("Root").Build(); Aws::Utils::ByteBuffer blob(4); blob[0] = 0xDE; blob[1] = 0xAD; blob[2] = 0xBE; blob[3] = 0xEF; - s.BeginStructure(root); + s.BeginStructure(*root); s.WriteMapKey("data"); - s.WriteBlob(root, blob); + s.WriteBlob(*root, blob); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -237,11 +238,11 @@ TEST_F(CborShapeDeserializerTest, BlobValue) { TEST_F(CborShapeDeserializerTest, TimestampValue) { CborShapeSerializer s; - Schema root; + auto root = Schema::StructureBuilder("Root").Build(); Aws::Utils::DateTime dt(1234567890.0); // seconds since epoch - s.BeginStructure(root); + s.BeginStructure(*root); s.WriteMapKey("ts"); - s.WriteTimestamp(root, dt); + s.WriteTimestamp(*root, dt); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -259,10 +260,10 @@ TEST_F(CborShapeDeserializerTest, TimestampValue) { TEST_F(CborShapeDeserializerTest, NullValue) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("item"); - s.WriteNull(root); + s.WriteNull(*root); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -281,13 +282,13 @@ TEST_F(CborShapeDeserializerTest, NullValue) { TEST_F(CborShapeDeserializerTest, ListOfIntegers) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("nums"); - s.BeginList(root, 3); - s.WriteInteger(root, 10); - s.WriteInteger(root, 20); - s.WriteInteger(root, 30); + s.BeginList(*root, 3); + s.WriteInteger(*root, 10); + s.WriteInteger(*root, 20); + s.WriteInteger(*root, 30); s.EndList(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -315,14 +316,14 @@ TEST_F(CborShapeDeserializerTest, ListOfIntegers) { TEST_F(CborShapeDeserializerTest, MapOfStrings) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("headers"); - s.BeginMap(root, 2); + s.BeginMap(*root, 2); s.WriteMapKey("foo"); - s.WriteString(root, "bar"); + s.WriteString(*root, "bar"); s.WriteMapKey("baz"); - s.WriteString(root, "qux"); + s.WriteString(*root, "qux"); s.EndMap(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -353,12 +354,12 @@ TEST_F(CborShapeDeserializerTest, MapOfStrings) { TEST_F(CborShapeDeserializerTest, NestedStructure) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("meta"); - s.BeginNestedStructure(root); + s.BeginNestedStructure(*root); s.WriteMapKey("key"); - s.WriteString(root, "val"); + s.WriteString(*root, "val"); s.EndNestedStructure(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -385,14 +386,14 @@ TEST_F(CborShapeDeserializerTest, NestedStructure) { TEST_F(CborShapeDeserializerTest, SkipUnknownField) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("known"); - s.WriteInteger(root, 1); + s.WriteInteger(*root, 1); s.WriteMapKey("unknown"); - s.WriteString(root, "skip me"); + s.WriteString(*root, "skip me"); s.WriteMapKey("also_known"); - s.WriteInteger(root, 2); + s.WriteInteger(*root, 2); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -420,17 +421,17 @@ TEST_F(CborShapeDeserializerTest, SkipUnknownField) { TEST_F(CborShapeDeserializerTest, SkipNestedUnknown) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("unknown_struct"); - s.BeginNestedStructure(root); + s.BeginNestedStructure(*root); s.WriteMapKey("a"); - s.WriteInteger(root, 1); + s.WriteInteger(*root, 1); s.WriteMapKey("b"); - s.WriteString(root, "nested"); + s.WriteString(*root, "nested"); s.EndNestedStructure(); s.WriteMapKey("known"); - s.WriteInteger(root, 42); + s.WriteInteger(*root, 42); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -454,14 +455,14 @@ TEST_F(CborShapeDeserializerTest, SkipNestedUnknown) { TEST_F(CborShapeDeserializerTest, MultipleScalars) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("a"); - s.WriteBoolean(root, true); + s.WriteBoolean(*root, true); s.WriteMapKey("b"); - s.WriteInteger(root, 7); + s.WriteInteger(*root, 7); s.WriteMapKey("c"); - s.WriteString(root, "x"); + s.WriteString(*root, "x"); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -500,10 +501,10 @@ TEST_F(CborShapeDeserializerTest, EmptyOptionalOnEmptyPayload) { TEST_F(CborShapeDeserializerTest, EmptyOptionalOnTypeMismatch) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("val"); - s.WriteString(root, "hello"); + s.WriteString(*root, "hello"); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -518,10 +519,10 @@ TEST_F(CborShapeDeserializerTest, EmptyOptionalOnTypeMismatch) { TEST_F(CborShapeDeserializerTest, ValidOptionalOnSuccess) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(root, 42); + s.WriteInteger(*root, 42); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -565,10 +566,10 @@ TEST_F(CborShapeDeserializerTest, BeginStructDefiniteLengthMap) { TEST_F(CborShapeDeserializerTest, BeginStructIndefiniteLengthMap) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.WriteMapKey("x"); - s.WriteInteger(root, 99); + s.WriteInteger(*root, 99); s.EndStructure(); auto payload = s.GetPayload().GetResult(); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp index a1f936d70887..bbf6d0fd2591 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -21,8 +22,8 @@ Aws::String Bytes(const char* data, size_t len) { return Aws::String(data, len); TEST_F(CborShapeSerializerTest, EmptyStructure) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -32,11 +33,11 @@ TEST_F(CborShapeSerializerTest, EmptyStructure) { TEST_F(CborShapeSerializerTest, BooleanTrue) { CborShapeSerializer s; - Schema root; - Schema member("enabled", ShapeType::Boolean); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("enabled", ShapeType::Boolean); + s.BeginStructure(*root); s.WriteMapKey("enabled"); - s.WriteBoolean(member, true); + s.WriteBoolean(*member, true); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -54,11 +55,11 @@ TEST_F(CborShapeSerializerTest, BooleanTrue) { TEST_F(CborShapeSerializerTest, BooleanFalse) { CborShapeSerializer s; - Schema root; - Schema member("ok", ShapeType::Boolean); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("ok", ShapeType::Boolean); + s.BeginStructure(*root); s.WriteMapKey("ok"); - s.WriteBoolean(member, false); + s.WriteBoolean(*member, false); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -74,11 +75,11 @@ TEST_F(CborShapeSerializerTest, BooleanFalse) { TEST_F(CborShapeSerializerTest, IntegerSmall) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(member, 1); + s.WriteInteger(*member, 1); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -94,11 +95,11 @@ TEST_F(CborShapeSerializerTest, IntegerSmall) { TEST_F(CborShapeSerializerTest, IntegerOneByte) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(member, 42); + s.WriteInteger(*member, 42); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -115,11 +116,11 @@ TEST_F(CborShapeSerializerTest, IntegerOneByte) { TEST_F(CborShapeSerializerTest, IntegerNegative) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(member, -1); + s.WriteInteger(*member, -1); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -135,11 +136,11 @@ TEST_F(CborShapeSerializerTest, IntegerNegative) { TEST_F(CborShapeSerializerTest, IntegerNegativeLarge) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(member, -100); + s.WriteInteger(*member, -100); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -156,11 +157,11 @@ TEST_F(CborShapeSerializerTest, IntegerNegativeLarge) { TEST_F(CborShapeSerializerTest, LongValue) { CborShapeSerializer s; - Schema root; - Schema member("big", ShapeType::Long); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("big", ShapeType::Long); + s.BeginStructure(*root); s.WriteMapKey("big"); - s.WriteLong(member, 1000000LL); + s.WriteLong(*member, 1000000LL); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -181,11 +182,11 @@ TEST_F(CborShapeSerializerTest, LongValue) { TEST_F(CborShapeSerializerTest, DoubleValue) { CborShapeSerializer s; - Schema root; - Schema member("d", ShapeType::Double); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("d", ShapeType::Double); + s.BeginStructure(*root); s.WriteMapKey("d"); - s.WriteDouble(member, 3.14); + s.WriteDouble(*member, 3.14); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -211,11 +212,11 @@ TEST_F(CborShapeSerializerTest, DoubleValue) { TEST_F(CborShapeSerializerTest, StringValue) { CborShapeSerializer s; - Schema root; - Schema member("name", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("name", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("name"); - s.WriteString(member, "hello"); + s.WriteString(*member, "hello"); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -232,11 +233,11 @@ TEST_F(CborShapeSerializerTest, StringValue) { TEST_F(CborShapeSerializerTest, EmptyString) { CborShapeSerializer s; - Schema root; - Schema member("s", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("s", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("s"); - s.WriteString(member, ""); + s.WriteString(*member, ""); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -252,13 +253,13 @@ TEST_F(CborShapeSerializerTest, EmptyString) { TEST_F(CborShapeSerializerTest, BlobValue) { CborShapeSerializer s; - Schema root; - Schema member("data", ShapeType::Blob); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("data", ShapeType::Blob); + s.BeginStructure(*root); s.WriteMapKey("data"); unsigned char raw[] = {0xDE, 0xAD, 0xBE, 0xEF}; Aws::Utils::ByteBuffer buf(raw, 4); - s.WriteBlob(member, buf); + s.WriteBlob(*member, buf); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -278,11 +279,11 @@ TEST_F(CborShapeSerializerTest, BlobValue) { TEST_F(CborShapeSerializerTest, NullValue) { CborShapeSerializer s; - Schema root; - Schema member("item", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("item", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("item"); - s.WriteNull(member); + s.WriteNull(*member); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -298,13 +299,13 @@ TEST_F(CborShapeSerializerTest, NullValue) { TEST_F(CborShapeSerializerTest, TimestampIntegerSeconds) { CborShapeSerializer s; - Schema root; - Schema member("ts", ShapeType::Timestamp); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("ts", ShapeType::Timestamp); + s.BeginStructure(*root); s.WriteMapKey("ts"); // DateTime(int64_t) takes milliseconds; 1234567000ms = 1234567 seconds (no fractional part) Aws::Utils::DateTime dt(static_cast(1234567000)); - s.WriteTimestamp(member, dt); + s.WriteTimestamp(*member, dt); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -327,12 +328,12 @@ TEST_F(CborShapeSerializerTest, TimestampIntegerSeconds) { TEST_F(CborShapeSerializerTest, TimestampFractionalSeconds) { // Fractional seconds are truncated to integer per rpcv2Cbor protocol CborShapeSerializer s; - Schema root; - Schema member("ts", ShapeType::Timestamp); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("ts", ShapeType::Timestamp); + s.BeginStructure(*root); s.WriteMapKey("ts"); Aws::Utils::DateTime dt(1234567890.5); - s.WriteTimestamp(member, dt); + s.WriteTimestamp(*member, dt); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -352,17 +353,17 @@ TEST_F(CborShapeSerializerTest, TimestampFractionalSeconds) { TEST_F(CborShapeSerializerTest, MultipleScalars) { CborShapeSerializer s; - Schema root; - Schema m1("a", ShapeType::Boolean); - Schema m2("b", ShapeType::Integer); - Schema m3("c", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto m1 = Schema::CreateMember("a", ShapeType::Boolean); + auto m2 = Schema::CreateMember("b", ShapeType::Integer); + auto m3 = Schema::CreateMember("c", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("a"); - s.WriteBoolean(m1, true); + s.WriteBoolean(*m1, true); s.WriteMapKey("b"); - s.WriteInteger(m2, 7); + s.WriteInteger(*m2, 7); s.WriteMapKey("c"); - s.WriteString(m3, "x"); + s.WriteString(*m3, "x"); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -387,14 +388,14 @@ TEST_F(CborShapeSerializerTest, MultipleScalars) { TEST_F(CborShapeSerializerTest, NestedStructure) { CborShapeSerializer s; - Schema root; - Schema nested("meta", ShapeType::Structure); - Schema inner("key", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto nested = Schema::CreateMember("meta", ShapeType::Structure); + auto inner = Schema::CreateMember("key", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("meta"); - s.BeginNestedStructure(nested); + s.BeginNestedStructure(*nested); s.WriteMapKey("key"); - s.WriteString(inner, "val"); + s.WriteString(*inner, "val"); s.EndNestedStructure(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -416,17 +417,17 @@ TEST_F(CborShapeSerializerTest, NestedStructure) { TEST_F(CborShapeSerializerTest, DeeplyNestedStructure) { CborShapeSerializer s; - Schema root; - Schema l1("l1", ShapeType::Structure); - Schema l2("l2", ShapeType::Structure); - Schema leaf("v", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto l1 = Schema::CreateMember("l1", ShapeType::Structure); + auto l2 = Schema::CreateMember("l2", ShapeType::Structure); + auto leaf = Schema::CreateMember("v", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("l1"); - s.BeginNestedStructure(l1); + s.BeginNestedStructure(*l1); s.WriteMapKey("l2"); - s.BeginNestedStructure(l2); + s.BeginNestedStructure(*l2); s.WriteMapKey("v"); - s.WriteInteger(leaf, 99); + s.WriteInteger(*leaf, 99); s.EndNestedStructure(); s.EndNestedStructure(); s.EndStructure(); @@ -455,15 +456,15 @@ TEST_F(CborShapeSerializerTest, DeeplyNestedStructure) { TEST_F(CborShapeSerializerTest, ListOfIntegers) { CborShapeSerializer s; - Schema root; - Schema listMember("nums", ShapeType::List); - Schema elem("member", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("nums", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("nums"); - s.BeginList(listMember, 3); - s.WriteInteger(elem, 1); - s.WriteInteger(elem, 2); - s.WriteInteger(elem, 3); + s.BeginList(*listMember, 3); + s.WriteInteger(*elem, 1); + s.WriteInteger(*elem, 2); + s.WriteInteger(*elem, 3); s.EndList(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -483,11 +484,11 @@ TEST_F(CborShapeSerializerTest, ListOfIntegers) { TEST_F(CborShapeSerializerTest, EmptyList) { CborShapeSerializer s; - Schema root; - Schema listMember("items", ShapeType::List); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + s.BeginStructure(*root); s.WriteMapKey("items"); - s.BeginList(listMember, 0); + s.BeginList(*listMember, 0); s.EndList(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -504,14 +505,14 @@ TEST_F(CborShapeSerializerTest, EmptyList) { TEST_F(CborShapeSerializerTest, ListOfStrings) { CborShapeSerializer s; - Schema root; - Schema listMember("tags", ShapeType::List); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("tags", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("tags"); - s.BeginList(listMember, 2); - s.WriteString(elem, "ab"); - s.WriteString(elem, "cd"); + s.BeginList(*listMember, 2); + s.WriteString(*elem, "ab"); + s.WriteString(*elem, "cd"); s.EndList(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -532,20 +533,20 @@ TEST_F(CborShapeSerializerTest, ListOfStrings) { TEST_F(CborShapeSerializerTest, ListOfStructures) { CborShapeSerializer s; - Schema root; - Schema listMember("items", ShapeType::List); - Schema structElem("member", ShapeType::Structure); - Schema field("id", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + auto structElem = Schema::CreateMember("member", ShapeType::Structure); + auto field = Schema::CreateMember("id", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("items"); - s.BeginList(listMember, 2); - s.BeginNestedStructure(structElem); + s.BeginList(*listMember, 2); + s.BeginNestedStructure(*structElem); s.WriteMapKey("id"); - s.WriteInteger(field, 1); + s.WriteInteger(*field, 1); s.EndNestedStructure(); - s.BeginNestedStructure(structElem); + s.BeginNestedStructure(*structElem); s.WriteMapKey("id"); - s.WriteInteger(field, 2); + s.WriteInteger(*field, 2); s.EndNestedStructure(); s.EndList(); s.EndStructure(); @@ -575,16 +576,16 @@ TEST_F(CborShapeSerializerTest, ListOfStructures) { TEST_F(CborShapeSerializerTest, MapOfStrings) { CborShapeSerializer s; - Schema root; - Schema mapMember("headers", ShapeType::Map); - Schema valSchema("value", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("headers", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("headers"); - s.BeginMap(mapMember, 2); + s.BeginMap(*mapMember, 2); s.WriteMapKey("foo"); - s.WriteString(valSchema, "bar"); + s.WriteString(*valSchema, "bar"); s.WriteMapKey("baz"); - s.WriteString(valSchema, "qux"); + s.WriteString(*valSchema, "qux"); s.EndMap(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -609,11 +610,11 @@ TEST_F(CborShapeSerializerTest, MapOfStrings) { TEST_F(CborShapeSerializerTest, EmptyMap) { CborShapeSerializer s; - Schema root; - Schema mapMember("tags", ShapeType::Map); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("tags", ShapeType::Map); + s.BeginStructure(*root); s.WriteMapKey("tags"); - s.BeginMap(mapMember, 0); + s.BeginMap(*mapMember, 0); s.EndMap(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -630,17 +631,17 @@ TEST_F(CborShapeSerializerTest, EmptyMap) { TEST_F(CborShapeSerializerTest, MapOfStructures) { CborShapeSerializer s; - Schema root; - Schema mapMember("nodes", ShapeType::Map); - Schema valSchema("value", ShapeType::Structure); - Schema field("val", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("nodes", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::Structure); + auto field = Schema::CreateMember("val", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("nodes"); - s.BeginMap(mapMember, 1); + s.BeginMap(*mapMember, 1); s.WriteMapKey("a"); - s.BeginNestedStructure(valSchema); + s.BeginNestedStructure(*valSchema); s.WriteMapKey("val"); - s.WriteInteger(field, 1); + s.WriteInteger(*field, 1); s.EndNestedStructure(); s.EndMap(); s.EndStructure(); @@ -669,8 +670,8 @@ TEST_F(CborShapeSerializerTest, MapOfStructures) { TEST_F(CborShapeSerializerTest, GetPayloadCalledTwice) { CborShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.EndStructure(); auto outcome1 = s.GetPayload(); ASSERT_TRUE(outcome1.IsSuccess()); @@ -683,11 +684,11 @@ TEST_F(CborShapeSerializerTest, GetPayloadCalledTwice) { TEST_F(CborShapeSerializerTest, EnumValue) { CborShapeSerializer s; - Schema root; - Schema member("status", ShapeType::Enum); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("status", ShapeType::Enum); + s.BeginStructure(*root); s.WriteMapKey("status"); - s.WriteEnum(member, 3); + s.WriteEnum(*member, 3); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -705,24 +706,24 @@ TEST_F(CborShapeSerializerTest, EnumValue) { TEST_F(CborShapeSerializerTest, StructureWithListAndMap) { CborShapeSerializer s; - Schema root; - Schema strMember("name", ShapeType::String); - Schema listMember("tags", ShapeType::List); - Schema listElem("member", ShapeType::String); - Schema mapMember("meta", ShapeType::Map); - Schema mapVal("value", ShapeType::Integer); + auto root = Schema::StructureBuilder("Root").Build(); + auto strMember = Schema::CreateMember("name", ShapeType::String); + auto listMember = Schema::CreateMember("tags", ShapeType::List); + auto listElem = Schema::CreateMember("member", ShapeType::String); + auto mapMember = Schema::CreateMember("meta", ShapeType::Map); + auto mapVal = Schema::CreateMember("value", ShapeType::Integer); - s.BeginStructure(root); + s.BeginStructure(*root); s.WriteMapKey("name"); - s.WriteString(strMember, "hi"); + s.WriteString(*strMember, "hi"); s.WriteMapKey("tags"); - s.BeginList(listMember, 1); - s.WriteString(listElem, "t1"); + s.BeginList(*listMember, 1); + s.WriteString(*listElem, "t1"); s.EndList(); s.WriteMapKey("meta"); - s.BeginMap(mapMember, 1); + s.BeginMap(*mapMember, 1); s.WriteMapKey("k"); - s.WriteInteger(mapVal, 5); + s.WriteInteger(*mapVal, 5); s.EndMap(); s.EndStructure(); @@ -752,11 +753,11 @@ TEST_F(CborShapeSerializerTest, StructureWithListAndMap) { TEST_F(CborShapeSerializerTest, IntegerZero) { CborShapeSerializer s; - Schema root; - Schema member("z", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("z", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("z"); - s.WriteInteger(member, 0); + s.WriteInteger(*member, 0); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -772,11 +773,11 @@ TEST_F(CborShapeSerializerTest, IntegerZero) { TEST_F(CborShapeSerializerTest, IntegerTwoByte) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(member, 1000); + s.WriteInteger(*member, 1000); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -795,15 +796,15 @@ TEST_F(CborShapeSerializerTest, IntegerTwoByte) { TEST_F(CborShapeSerializerTest, SparseList) { CborShapeSerializer s; - Schema root; - Schema listMember("items", ShapeType::List); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("items"); - s.BeginList(listMember, 3); - s.WriteString(elem, "a"); - s.WriteNull(elem); - s.WriteString(elem, "b"); + s.BeginList(*listMember, 3); + s.WriteString(*elem, "a"); + s.WriteNull(*elem); + s.WriteString(*elem, "b"); s.EndList(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -827,11 +828,11 @@ TEST_F(CborShapeSerializerTest, SparseList) { TEST_F(CborShapeSerializerTest, IntegerFourByte) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteInteger(member, 70000); + s.WriteInteger(*member, 70000); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -851,11 +852,11 @@ TEST_F(CborShapeSerializerTest, IntegerFourByte) { TEST_F(CborShapeSerializerTest, LongEightByte) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Long); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Long); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteLong(member, 5000000000LL); + s.WriteLong(*member, 5000000000LL); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -879,11 +880,11 @@ TEST_F(CborShapeSerializerTest, LongEightByte) { TEST_F(CborShapeSerializerTest, LargeNegativeInteger) { CborShapeSerializer s; - Schema root; - Schema member("n", ShapeType::Long); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("n", ShapeType::Long); + s.BeginStructure(*root); s.WriteMapKey("n"); - s.WriteLong(member, -1000000LL); + s.WriteLong(*member, -1000000LL); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -904,11 +905,11 @@ TEST_F(CborShapeSerializerTest, LargeNegativeInteger) { TEST_F(CborShapeSerializerTest, DoubleWholeNumberEncodedAsInt) { // CRT encoder uses "smallest possible" — a double like 5.0 encodes as integer 5 CborShapeSerializer s; - Schema root; - Schema member("d", ShapeType::Double); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("d", ShapeType::Double); + s.BeginStructure(*root); s.WriteMapKey("d"); - s.WriteDouble(member, 5.0); + s.WriteDouble(*member, 5.0); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -926,11 +927,11 @@ TEST_F(CborShapeSerializerTest, DoubleWholeNumberEncodedAsInt) { TEST_F(CborShapeSerializerTest, DoubleNegativeWholeNumberEncodedAsNegInt) { // CRT encoder: -3.0 encodes as negint 2 (meaning -(2+1) = -3) CborShapeSerializer s; - Schema root; - Schema member("d", ShapeType::Double); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("d", ShapeType::Double); + s.BeginStructure(*root); s.WriteMapKey("d"); - s.WriteDouble(member, -3.0); + s.WriteDouble(*member, -3.0); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -946,11 +947,11 @@ TEST_F(CborShapeSerializerTest, DoubleNegativeWholeNumberEncodedAsNegInt) { TEST_F(CborShapeSerializerTest, UnicodeString) { CborShapeSerializer s; - Schema root; - Schema member("s", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("s", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("s"); - s.WriteString(member, "\xC3\xA9\xC3\xA8"); // "éè" in UTF-8 (4 bytes) + s.WriteString(*member, "\xC3\xA9\xC3\xA8"); // "éè" in UTF-8 (4 bytes) s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -967,19 +968,19 @@ TEST_F(CborShapeSerializerTest, UnicodeString) { TEST_F(CborShapeSerializerTest, NestedListInList) { CborShapeSerializer s; - Schema root; - Schema outerList("data", ShapeType::List); - Schema innerList("member", ShapeType::List); - Schema elem("member", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto outerList = Schema::CreateMember("data", ShapeType::List); + auto innerList = Schema::CreateMember("member", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("data"); - s.BeginList(outerList, 2); - s.BeginList(innerList, 2); - s.WriteInteger(elem, 1); - s.WriteInteger(elem, 2); + s.BeginList(*outerList, 2); + s.BeginList(*innerList, 2); + s.WriteInteger(*elem, 1); + s.WriteInteger(*elem, 2); s.EndList(); - s.BeginList(innerList, 1); - s.WriteInteger(elem, 3); + s.BeginList(*innerList, 1); + s.WriteInteger(*elem, 3); s.EndList(); s.EndList(); s.EndStructure(); @@ -1002,18 +1003,18 @@ TEST_F(CborShapeSerializerTest, NestedListInList) { TEST_F(CborShapeSerializerTest, MapWithMultipleEntries) { CborShapeSerializer s; - Schema root; - Schema mapMember("m", ShapeType::Map); - Schema valSchema("value", ShapeType::Integer); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("m", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::Integer); + s.BeginStructure(*root); s.WriteMapKey("m"); - s.BeginMap(mapMember, 3); + s.BeginMap(*mapMember, 3); s.WriteMapKey("x"); - s.WriteInteger(valSchema, 1); + s.WriteInteger(*valSchema, 1); s.WriteMapKey("y"); - s.WriteInteger(valSchema, 2); + s.WriteInteger(*valSchema, 2); s.WriteMapKey("z"); - s.WriteInteger(valSchema, 3); + s.WriteInteger(*valSchema, 3); s.EndMap(); s.EndStructure(); auto outcome = s.GetPayload(); @@ -1039,11 +1040,11 @@ TEST_F(CborShapeSerializerTest, MapWithMultipleEntries) { TEST_F(CborShapeSerializerTest, FloatValue) { CborShapeSerializer s; - Schema root; - Schema member("f", ShapeType::Float); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("f", ShapeType::Float); + s.BeginStructure(*root); s.WriteMapKey("f"); - s.WriteFloat(member, 1.5f); + s.WriteFloat(*member, 1.5f); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -1065,11 +1066,11 @@ TEST_F(CborShapeSerializerTest, FloatValue) { TEST_F(CborShapeSerializerTest, FloatWholeNumberEncodedAsInt) { // CRT "smallest possible": 7.0f encodes as integer 7 CborShapeSerializer s; - Schema root; - Schema member("f", ShapeType::Float); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("f", ShapeType::Float); + s.BeginStructure(*root); s.WriteMapKey("f"); - s.WriteFloat(member, 7.0f); + s.WriteFloat(*member, 7.0f); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -1085,12 +1086,12 @@ TEST_F(CborShapeSerializerTest, FloatWholeNumberEncodedAsInt) { TEST_F(CborShapeSerializerTest, TimestampEpochZero) { CborShapeSerializer s; - Schema root; - Schema member("ts", ShapeType::Timestamp); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("ts", ShapeType::Timestamp); + s.BeginStructure(*root); s.WriteMapKey("ts"); Aws::Utils::DateTime dt(0.0); - s.WriteTimestamp(member, dt); + s.WriteTimestamp(*member, dt); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -1108,15 +1109,15 @@ TEST_F(CborShapeSerializerTest, TimestampEpochZero) { TEST_F(CborShapeSerializerTest, LargeBlob) { CborShapeSerializer s; - Schema root; - Schema member("b", ShapeType::Blob); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("b", ShapeType::Blob); + s.BeginStructure(*root); s.WriteMapKey("b"); Aws::Utils::ByteBuffer blob(300); for (size_t i = 0; i < 300; i++) { blob[i] = static_cast(i % 256); } - s.WriteBlob(member, blob); + s.WriteBlob(*member, blob); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -1136,14 +1137,14 @@ TEST_F(CborShapeSerializerTest, LargeBlob) { TEST_F(CborShapeSerializerTest, UnionAsStructure) { // Unions serialize like a structure with exactly one field CborShapeSerializer s; - Schema root; - Schema unionMember("result", ShapeType::Union); - Schema field("message", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto unionMember = Schema::CreateMember("result", ShapeType::Union); + auto field = Schema::CreateMember("message", ShapeType::String); + s.BeginStructure(*root); s.WriteMapKey("result"); - s.BeginNestedStructure(unionMember); + s.BeginNestedStructure(*unionMember); s.WriteMapKey("message"); - s.WriteString(field, "ok"); + s.WriteString(*field, "ok"); s.EndNestedStructure(); s.EndStructure(); auto outcome = s.GetPayload(); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp index 7ca1e8ffd894..22876355adff 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include using namespace smithy::schema; @@ -15,8 +17,8 @@ class JsonShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; TEST_F(JsonShapeSerializerTest, EmptyStructure) { JsonShapeSerializer s; - Schema root; - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + s.BeginStructure(*root); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -25,117 +27,117 @@ TEST_F(JsonShapeSerializerTest, EmptyStructure) { TEST_F(JsonShapeSerializerTest, BooleanTrue) { JsonShapeSerializer s; - Schema root; - Schema member("enabled", ShapeType::Boolean); - s.BeginStructure(root); - s.WriteBoolean(member, true); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("enabled", ShapeType::Boolean); + s.BeginStructure(*root); + s.WriteBoolean(*member, true); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"enabled\":true"), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, BooleanFalse) { JsonShapeSerializer s; - Schema root; - Schema member("enabled", ShapeType::Boolean); - s.BeginStructure(root); - s.WriteBoolean(member, false); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("enabled", ShapeType::Boolean); + s.BeginStructure(*root); + s.WriteBoolean(*member, false); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"enabled\":false"), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, Integer) { JsonShapeSerializer s; - Schema root; - Schema member("count", ShapeType::Integer); - s.BeginStructure(root); - s.WriteInteger(member, 42); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("count", ShapeType::Integer); + s.BeginStructure(*root); + s.WriteInteger(*member, 42); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"count\":42"), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, Long) { JsonShapeSerializer s; - Schema root; - Schema member("bigNum", ShapeType::Long); - s.BeginStructure(root); - s.WriteLong(member, 9876543210LL); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("bigNum", ShapeType::Long); + s.BeginStructure(*root); + s.WriteLong(*member, 9876543210LL); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"bigNum\":9876543210"), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, Double) { JsonShapeSerializer s; - Schema root; - Schema member("ratio", ShapeType::Double); - s.BeginStructure(root); - s.WriteDouble(member, 3.14); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("ratio", ShapeType::Double); + s.BeginStructure(*root); + s.WriteDouble(*member, 3.14); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"ratio\":3.14"), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, String) { JsonShapeSerializer s; - Schema root; - Schema member("name", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "hello"); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("name", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "hello"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"name\":\"hello\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, EmptyString) { JsonShapeSerializer s; - Schema root; - Schema member("name", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, ""); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("name", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, ""); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"name\":\"\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, Timestamp) { JsonShapeSerializer s; - Schema root; - Schema member("created", ShapeType::Timestamp); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("created", ShapeType::Timestamp); + s.BeginStructure(*root); Aws::Utils::DateTime dt(1234567890.0); - s.WriteTimestamp(member, dt); + s.WriteTimestamp(*member, dt); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"created\":"), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, Blob) { JsonShapeSerializer s; - Schema root; - Schema member("data", ShapeType::Blob); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("data", ShapeType::Blob); + s.BeginStructure(*root); unsigned char raw[] = {0x66, 0x6f, 0x6f}; Aws::Utils::ByteBuffer buf(raw, 3); - s.WriteBlob(member, buf); + s.WriteBlob(*member, buf); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"data\":\"Zm9v\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, NullValue) { JsonShapeSerializer s; - Schema root; - Schema member("item", ShapeType::String); - s.BeginStructure(root); - s.WriteNull(member); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("item", ShapeType::String); + s.BeginStructure(*root); + s.WriteNull(*member); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"item\":null"), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, MultipleScalars) { JsonShapeSerializer s; - Schema root; - Schema m1("a", ShapeType::Boolean); - Schema m2("b", ShapeType::Integer); - Schema m3("c", ShapeType::String); - s.BeginStructure(root); - s.WriteBoolean(m1, true); - s.WriteInteger(m2, 7); - s.WriteString(m3, "x"); + auto root = Schema::StructureBuilder("Root").Build(); + auto m1 = Schema::CreateMember("a", ShapeType::Boolean); + auto m2 = Schema::CreateMember("b", ShapeType::Integer); + auto m3 = Schema::CreateMember("c", ShapeType::String); + s.BeginStructure(*root); + s.WriteBoolean(*m1, true); + s.WriteInteger(*m2, 7); + s.WriteString(*m3, "x"); s.EndStructure(); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("\"a\":true"), Aws::String::npos); @@ -147,12 +149,12 @@ TEST_F(JsonShapeSerializerTest, MultipleScalars) { TEST_F(JsonShapeSerializerTest, NestedStructure) { JsonShapeSerializer s; - Schema root; - Schema nested("metadata", ShapeType::Structure); - Schema inner("key", ShapeType::String); - s.BeginStructure(root); - s.BeginNestedStructure(nested); - s.WriteString(inner, "val"); + auto root = Schema::StructureBuilder("Root").Build(); + auto nested = Schema::CreateMember("metadata", ShapeType::Structure); + auto inner = Schema::CreateMember("key", ShapeType::String); + s.BeginStructure(*root); + s.BeginNestedStructure(*nested); + s.WriteString(*inner, "val"); s.EndNestedStructure(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"metadata\":{\"key\":\"val\"}"), Aws::String::npos); @@ -160,14 +162,14 @@ TEST_F(JsonShapeSerializerTest, NestedStructure) { TEST_F(JsonShapeSerializerTest, DeeplyNestedStructure) { JsonShapeSerializer s; - Schema root; - Schema level1("l1", ShapeType::Structure); - Schema level2("l2", ShapeType::Structure); - Schema leaf("val", ShapeType::Integer); - s.BeginStructure(root); - s.BeginNestedStructure(level1); - s.BeginNestedStructure(level2); - s.WriteInteger(leaf, 99); + auto root = Schema::StructureBuilder("Root").Build(); + auto level1 = Schema::CreateMember("l1", ShapeType::Structure); + auto level2 = Schema::CreateMember("l2", ShapeType::Structure); + auto leaf = Schema::CreateMember("val", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginNestedStructure(*level1); + s.BeginNestedStructure(*level2); + s.WriteInteger(*leaf, 99); s.EndNestedStructure(); s.EndNestedStructure(); s.EndStructure(); @@ -178,14 +180,14 @@ TEST_F(JsonShapeSerializerTest, DeeplyNestedStructure) { TEST_F(JsonShapeSerializerTest, ListOfStrings) { JsonShapeSerializer s; - Schema root; - Schema listMember("tags", ShapeType::List); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); - s.BeginList(listMember, 3); - s.WriteString(elem, "a"); - s.WriteString(elem, "b"); - s.WriteString(elem, "c"); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("tags", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); + s.BeginList(*listMember, 3); + s.WriteString(*elem, "a"); + s.WriteString(*elem, "b"); + s.WriteString(*elem, "c"); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"tags\":[\"a\",\"b\",\"c\"]"), Aws::String::npos); @@ -193,14 +195,14 @@ TEST_F(JsonShapeSerializerTest, ListOfStrings) { TEST_F(JsonShapeSerializerTest, ListOfIntegers) { JsonShapeSerializer s; - Schema root; - Schema listMember("nums", ShapeType::List); - Schema elem("member", ShapeType::Integer); - s.BeginStructure(root); - s.BeginList(listMember, 3); - s.WriteInteger(elem, 1); - s.WriteInteger(elem, 2); - s.WriteInteger(elem, 3); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("nums", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginList(*listMember, 3); + s.WriteInteger(*elem, 1); + s.WriteInteger(*elem, 2); + s.WriteInteger(*elem, 3); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"nums\":[1,2,3]"), Aws::String::npos); @@ -208,10 +210,10 @@ TEST_F(JsonShapeSerializerTest, ListOfIntegers) { TEST_F(JsonShapeSerializerTest, EmptyList) { JsonShapeSerializer s; - Schema root; - Schema listMember("items", ShapeType::List); - s.BeginStructure(root); - s.BeginList(listMember, 0); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + s.BeginStructure(*root); + s.BeginList(*listMember, 0); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"items\":[]"), Aws::String::npos); @@ -219,17 +221,17 @@ TEST_F(JsonShapeSerializerTest, EmptyList) { TEST_F(JsonShapeSerializerTest, ListOfStructures) { JsonShapeSerializer s; - Schema root; - Schema listMember("items", ShapeType::List); - Schema structElem("member", ShapeType::Structure); - Schema field("id", ShapeType::Integer); - s.BeginStructure(root); - s.BeginList(listMember, 2); - s.BeginNestedStructure(structElem); - s.WriteInteger(field, 1); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + auto structElem = Schema::CreateMember("member", ShapeType::Structure); + auto field = Schema::CreateMember("id", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginList(*listMember, 2); + s.BeginNestedStructure(*structElem); + s.WriteInteger(*field, 1); s.EndNestedStructure(); - s.BeginNestedStructure(structElem); - s.WriteInteger(field, 2); + s.BeginNestedStructure(*structElem); + s.WriteInteger(*field, 2); s.EndNestedStructure(); s.EndList(); s.EndStructure(); @@ -238,14 +240,14 @@ TEST_F(JsonShapeSerializerTest, ListOfStructures) { TEST_F(JsonShapeSerializerTest, SparseList) { JsonShapeSerializer s; - Schema root; - Schema listMember("items", ShapeType::List); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); - s.BeginList(listMember, 3); - s.WriteString(elem, "a"); - s.WriteNull(elem); - s.WriteString(elem, "b"); + auto root = Schema::StructureBuilder("Root").Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); + s.BeginList(*listMember, 3); + s.WriteString(*elem, "a"); + s.WriteNull(*elem); + s.WriteString(*elem, "b"); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"items\":[\"a\",null,\"b\"]"), Aws::String::npos); @@ -255,15 +257,15 @@ TEST_F(JsonShapeSerializerTest, SparseList) { TEST_F(JsonShapeSerializerTest, MapOfStrings) { JsonShapeSerializer s; - Schema root; - Schema mapMember("headers", ShapeType::Map); - Schema valSchema("value", ShapeType::String); - s.BeginStructure(root); - s.BeginMap(mapMember, 2); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("headers", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 2); s.WriteMapKey("x-foo"); - s.WriteString(valSchema, "bar"); + s.WriteString(*valSchema, "bar"); s.WriteMapKey("x-baz"); - s.WriteString(valSchema, "qux"); + s.WriteString(*valSchema, "qux"); s.EndMap(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -273,10 +275,10 @@ TEST_F(JsonShapeSerializerTest, MapOfStrings) { TEST_F(JsonShapeSerializerTest, EmptyMap) { JsonShapeSerializer s; - Schema root; - Schema mapMember("tags", ShapeType::Map); - s.BeginStructure(root); - s.BeginMap(mapMember, 0); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("tags", ShapeType::Map); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 0); s.EndMap(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"tags\":{}"), Aws::String::npos); @@ -284,15 +286,15 @@ TEST_F(JsonShapeSerializerTest, EmptyMap) { TEST_F(JsonShapeSerializerTest, MapOfStructures) { JsonShapeSerializer s; - Schema root; - Schema mapMember("nodes", ShapeType::Map); - Schema valSchema("value", ShapeType::Structure); - Schema field("val", ShapeType::Integer); - s.BeginStructure(root); - s.BeginMap(mapMember, 1); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("nodes", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::Structure); + auto field = Schema::CreateMember("val", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 1); s.WriteMapKey("a"); - s.BeginNestedStructure(valSchema); - s.WriteInteger(field, 1); + s.BeginNestedStructure(*valSchema); + s.WriteInteger(*field, 1); s.EndNestedStructure(); s.EndMap(); s.EndStructure(); @@ -301,15 +303,15 @@ TEST_F(JsonShapeSerializerTest, MapOfStructures) { TEST_F(JsonShapeSerializerTest, SparseMap) { JsonShapeSerializer s; - Schema root; - Schema mapMember("data", ShapeType::Map); - Schema valSchema("value", ShapeType::String); - s.BeginStructure(root); - s.BeginMap(mapMember, 2); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("data", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 2); s.WriteMapKey("present"); - s.WriteString(valSchema, "yes"); + s.WriteString(*valSchema, "yes"); s.WriteMapKey("absent"); - s.WriteNull(valSchema); + s.WriteNull(*valSchema); s.EndMap(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -321,22 +323,22 @@ TEST_F(JsonShapeSerializerTest, SparseMap) { TEST_F(JsonShapeSerializerTest, StructureWithListAndMap) { JsonShapeSerializer s; - Schema root; - Schema strMember("name", ShapeType::String); - Schema listMember("tags", ShapeType::List); - Schema listElem("member", ShapeType::String); - Schema mapMember("meta", ShapeType::Map); - Schema mapVal("value", ShapeType::String); - - s.BeginStructure(root); - s.WriteString(strMember, "test"); - s.BeginList(listMember, 2); - s.WriteString(listElem, "t1"); - s.WriteString(listElem, "t2"); + auto root = Schema::StructureBuilder("Root").Build(); + auto strMember = Schema::CreateMember("name", ShapeType::String); + auto listMember = Schema::CreateMember("tags", ShapeType::List); + auto listElem = Schema::CreateMember("member", ShapeType::String); + auto mapMember = Schema::CreateMember("meta", ShapeType::Map); + auto mapVal = Schema::CreateMember("value", ShapeType::String); + + s.BeginStructure(*root); + s.WriteString(*strMember, "test"); + s.BeginList(*listMember, 2); + s.WriteString(*listElem, "t1"); + s.WriteString(*listElem, "t2"); s.EndList(); - s.BeginMap(mapMember, 1); + s.BeginMap(*mapMember, 1); s.WriteMapKey("k"); - s.WriteString(mapVal, "v"); + s.WriteString(*mapVal, "v"); s.EndMap(); s.EndStructure(); @@ -348,17 +350,17 @@ TEST_F(JsonShapeSerializerTest, StructureWithListAndMap) { TEST_F(JsonShapeSerializerTest, MapContainingList) { JsonShapeSerializer s; - Schema root; - Schema mapMember("data", ShapeType::Map); - Schema listSchema("value", ShapeType::List); - Schema elem("member", ShapeType::Integer); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("data", ShapeType::Map); + auto listSchema = Schema::CreateMember("value", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::Integer); - s.BeginStructure(root); - s.BeginMap(mapMember, 1); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 1); s.WriteMapKey("nums"); - s.BeginList(listSchema, 2); - s.WriteInteger(elem, 1); - s.WriteInteger(elem, 2); + s.BeginList(*listSchema, 2); + s.WriteInteger(*elem, 1); + s.WriteInteger(*elem, 2); s.EndList(); s.EndMap(); s.EndStructure(); @@ -370,56 +372,56 @@ TEST_F(JsonShapeSerializerTest, MapContainingList) { TEST_F(JsonShapeSerializerTest, EscapesQuotesInString) { JsonShapeSerializer s; - Schema root; - Schema member("msg", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "say \"hello\""); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("msg", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "say \"hello\""); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"msg\":\"say \\\"hello\\\"\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, EscapesBackslash) { JsonShapeSerializer s; - Schema root; - Schema member("path", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "C:\\Users\\test"); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("path", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "C:\\Users\\test"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"path\":\"C:\\\\Users\\\\test\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, EscapesControlCharacters) { JsonShapeSerializer s; - Schema root; - Schema member("text", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "line1\nline2\ttab"); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("text", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "line1\nline2\ttab"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"text\":\"line1\\nline2\\ttab\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, EscapesNullByte) { JsonShapeSerializer s; - Schema root; - Schema member("data", ShapeType::String); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("data", ShapeType::String); + s.BeginStructure(*root); Aws::String val("ab"); val += '\0'; val += "cd"; - s.WriteString(member, val); + s.WriteString(*member, val); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"data\":\"ab\\u0000cd\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, EscapesInMapKey) { JsonShapeSerializer s; - Schema root; - Schema mapMember("m", ShapeType::Map); - Schema valSchema("value", ShapeType::String); - s.BeginStructure(root); - s.BeginMap(mapMember, 1); + auto root = Schema::StructureBuilder("Root").Build(); + auto mapMember = Schema::CreateMember("m", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 1); s.WriteMapKey("key\"with\"quotes"); - s.WriteString(valSchema, "v"); + s.WriteString(*valSchema, "v"); s.EndMap(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"key\\\"with\\\"quotes\":\"v\""), Aws::String::npos); @@ -429,12 +431,12 @@ TEST_F(JsonShapeSerializerTest, EscapesInMapKey) { TEST_F(JsonShapeSerializerTest, MaxDepthEnforcement) { JsonShapeSerializer s; - Schema root; - Schema nested("n", ShapeType::Structure); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root").Build(); + auto nested = Schema::CreateMember("n", ShapeType::Structure); + s.BeginStructure(*root); // Nest 1000+ times to exceed MAX_DEPTH for (int i = 0; i < 1000; i++) { - s.BeginNestedStructure(nested); + s.BeginNestedStructure(*nested); } auto outcome = s.GetPayload(); ASSERT_FALSE(outcome.IsSuccess()); @@ -445,11 +447,10 @@ TEST_F(JsonShapeSerializerTest, MaxDepthEnforcement) { TEST_F(JsonShapeSerializerTest, JsonNameOverridesMemberName) { JsonShapeSerializer s; - Schema root; - Schema member("internalName", ShapeType::String); - member.SetTrait(JsonNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")); - s.BeginStructure(root); - s.WriteString(member, "hello"); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("internalName", ShapeType::String, {{JsonNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")}}); + s.BeginStructure(*root); + s.WriteString(*member, "hello"); s.EndStructure(); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("\"ExternalName\":\"hello\""), Aws::String::npos); @@ -458,20 +459,20 @@ TEST_F(JsonShapeSerializerTest, JsonNameOverridesMemberName) { TEST_F(JsonShapeSerializerTest, NoJsonNameUsesGetMemberName) { JsonShapeSerializer s; - Schema root; - Schema member("fieldName", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "value"); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("fieldName", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "value"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("\"fieldName\":\"value\""), Aws::String::npos); } TEST_F(JsonShapeSerializerTest, FloatValue) { JsonShapeSerializer s; - Schema root; - Schema member("f", ShapeType::Float); - s.BeginStructure(root); - s.WriteFloat(member, 1.5f); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("f", ShapeType::Float); + s.BeginStructure(*root); + s.WriteFloat(*member, 1.5f); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -480,10 +481,10 @@ TEST_F(JsonShapeSerializerTest, FloatValue) { TEST_F(JsonShapeSerializerTest, FloatNegativeValue) { JsonShapeSerializer s; - Schema root; - Schema member("f", ShapeType::Float); - s.BeginStructure(root); - s.WriteFloat(member, -2.25f); + auto root = Schema::StructureBuilder("Root").Build(); + auto member = Schema::CreateMember("f", ShapeType::Float); + s.BeginStructure(*root); + s.WriteFloat(*member, -2.25f); s.EndStructure(); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp index 0918cc9f5037..75cdf7c90679 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp @@ -4,6 +4,8 @@ */ #include #include +#include +#include #include #include @@ -15,111 +17,111 @@ class XmlShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; TEST_F(XmlShapeSerializerTest, EmptyStructure) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + s.BeginStructure(*root); s.EndStructure(); EXPECT_EQ(s.GetPayload().GetResult(), ""); } TEST_F(XmlShapeSerializerTest, BooleanTrue) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("enabled", ShapeType::Boolean); - s.BeginStructure(root); - s.WriteBoolean(member, true); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("enabled", ShapeType::Boolean); + s.BeginStructure(*root); + s.WriteBoolean(*member, true); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("true"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, BooleanFalse) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("enabled", ShapeType::Boolean); - s.BeginStructure(root); - s.WriteBoolean(member, false); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("enabled", ShapeType::Boolean); + s.BeginStructure(*root); + s.WriteBoolean(*member, false); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("false"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, Integer) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("count", ShapeType::Integer); - s.BeginStructure(root); - s.WriteInteger(member, 42); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("count", ShapeType::Integer); + s.BeginStructure(*root); + s.WriteInteger(*member, 42); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("42"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, Long) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("bigNum", ShapeType::Long); - s.BeginStructure(root); - s.WriteLong(member, 9876543210LL); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("bigNum", ShapeType::Long); + s.BeginStructure(*root); + s.WriteLong(*member, 9876543210LL); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("9876543210"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, Double) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("ratio", ShapeType::Double); - s.BeginStructure(root); - s.WriteDouble(member, 3.14); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("ratio", ShapeType::Double); + s.BeginStructure(*root); + s.WriteDouble(*member, 3.14); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("3.14"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, String) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("name", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "hello"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("name", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "hello"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("hello"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, EmptyString) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("name", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, ""); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("name", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, ""); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find(""), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, Timestamp) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("created", ShapeType::Timestamp); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("created", ShapeType::Timestamp); + s.BeginStructure(*root); Aws::Utils::DateTime dt(1234567890.0); - s.WriteTimestamp(member, dt); + s.WriteTimestamp(*member, dt); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("2009-02-13T23:31:30Z"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, Blob) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("data", ShapeType::Blob); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("data", ShapeType::Blob); + s.BeginStructure(*root); unsigned char raw[] = {0x66, 0x6f, 0x6f}; Aws::Utils::ByteBuffer buf(raw, 3); - s.WriteBlob(member, buf); + s.WriteBlob(*member, buf); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("Zm9v"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, NullValueOmitted) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("item", ShapeType::String); - s.BeginStructure(root); - s.WriteNull(member); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("item", ShapeType::String); + s.BeginStructure(*root); + s.WriteNull(*member); s.EndStructure(); // Null values are omitted in XML EXPECT_EQ(s.GetPayload().GetResult(), ""); @@ -127,14 +129,14 @@ TEST_F(XmlShapeSerializerTest, NullValueOmitted) { TEST_F(XmlShapeSerializerTest, MultipleScalars) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema m1("a", ShapeType::Boolean); - Schema m2("b", ShapeType::Integer); - Schema m3("c", ShapeType::String); - s.BeginStructure(root); - s.WriteBoolean(m1, true); - s.WriteInteger(m2, 7); - s.WriteString(m3, "x"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto m1 = Schema::CreateMember("a", ShapeType::Boolean); + auto m2 = Schema::CreateMember("b", ShapeType::Integer); + auto m3 = Schema::CreateMember("c", ShapeType::String); + s.BeginStructure(*root); + s.WriteBoolean(*m1, true); + s.WriteInteger(*m2, 7); + s.WriteString(*m3, "x"); s.EndStructure(); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("true"), Aws::String::npos); @@ -146,12 +148,12 @@ TEST_F(XmlShapeSerializerTest, MultipleScalars) { TEST_F(XmlShapeSerializerTest, NestedStructure) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema nested("metadata", ShapeType::Structure); - Schema inner("key", ShapeType::String); - s.BeginStructure(root); - s.BeginNestedStructure(nested); - s.WriteString(inner, "val"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto nested = Schema::CreateMember("metadata", ShapeType::Structure); + auto inner = Schema::CreateMember("key", ShapeType::String); + s.BeginStructure(*root); + s.BeginNestedStructure(*nested); + s.WriteString(*inner, "val"); s.EndNestedStructure(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("val"), Aws::String::npos); @@ -159,14 +161,14 @@ TEST_F(XmlShapeSerializerTest, NestedStructure) { TEST_F(XmlShapeSerializerTest, DeeplyNestedStructure) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema level1("l1", ShapeType::Structure); - Schema level2("l2", ShapeType::Structure); - Schema leaf("val", ShapeType::Integer); - s.BeginStructure(root); - s.BeginNestedStructure(level1); - s.BeginNestedStructure(level2); - s.WriteInteger(leaf, 99); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto level1 = Schema::CreateMember("l1", ShapeType::Structure); + auto level2 = Schema::CreateMember("l2", ShapeType::Structure); + auto leaf = Schema::CreateMember("val", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginNestedStructure(*level1); + s.BeginNestedStructure(*level2); + s.WriteInteger(*leaf, 99); s.EndNestedStructure(); s.EndNestedStructure(); s.EndStructure(); @@ -177,14 +179,14 @@ TEST_F(XmlShapeSerializerTest, DeeplyNestedStructure) { TEST_F(XmlShapeSerializerTest, ListOfStrings) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema listMember("tags", ShapeType::List); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); - s.BeginList(listMember, 3); - s.WriteString(elem, "a"); - s.WriteString(elem, "b"); - s.WriteString(elem, "c"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto listMember = Schema::CreateMember("tags", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); + s.BeginList(*listMember, 3); + s.WriteString(*elem, "a"); + s.WriteString(*elem, "b"); + s.WriteString(*elem, "c"); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("abc"), Aws::String::npos); @@ -192,14 +194,14 @@ TEST_F(XmlShapeSerializerTest, ListOfStrings) { TEST_F(XmlShapeSerializerTest, ListOfIntegers) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema listMember("nums", ShapeType::List); - Schema elem("member", ShapeType::Integer); - s.BeginStructure(root); - s.BeginList(listMember, 3); - s.WriteInteger(elem, 1); - s.WriteInteger(elem, 2); - s.WriteInteger(elem, 3); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto listMember = Schema::CreateMember("nums", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginList(*listMember, 3); + s.WriteInteger(*elem, 1); + s.WriteInteger(*elem, 2); + s.WriteInteger(*elem, 3); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("123"), Aws::String::npos); @@ -207,10 +209,10 @@ TEST_F(XmlShapeSerializerTest, ListOfIntegers) { TEST_F(XmlShapeSerializerTest, EmptyList) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema listMember("items", ShapeType::List); - s.BeginStructure(root); - s.BeginList(listMember, 0); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + s.BeginStructure(*root); + s.BeginList(*listMember, 0); s.EndList(); s.EndStructure(); // Empty list still produces the wrapper element @@ -219,17 +221,17 @@ TEST_F(XmlShapeSerializerTest, EmptyList) { TEST_F(XmlShapeSerializerTest, ListOfStructures) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema listMember("items", ShapeType::List); - Schema structElem("member", ShapeType::Structure); - Schema field("id", ShapeType::Integer); - s.BeginStructure(root); - s.BeginList(listMember, 2); - s.BeginNestedStructure(structElem); - s.WriteInteger(field, 1); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List); + auto structElem = Schema::CreateMember("member", ShapeType::Structure); + auto field = Schema::CreateMember("id", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginList(*listMember, 2); + s.BeginNestedStructure(*structElem); + s.WriteInteger(*field, 1); s.EndNestedStructure(); - s.BeginNestedStructure(structElem); - s.WriteInteger(field, 2); + s.BeginNestedStructure(*structElem); + s.WriteInteger(*field, 2); s.EndNestedStructure(); s.EndList(); s.EndStructure(); @@ -240,15 +242,15 @@ TEST_F(XmlShapeSerializerTest, ListOfStructures) { TEST_F(XmlShapeSerializerTest, MapOfStrings) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema mapMember("headers", ShapeType::Map); - Schema valSchema("value", ShapeType::String); - s.BeginStructure(root); - s.BeginMap(mapMember, 2); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto mapMember = Schema::CreateMember("headers", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 2); s.WriteMapKey("foo"); - s.WriteString(valSchema, "bar"); + s.WriteString(*valSchema, "bar"); s.WriteMapKey("baz"); - s.WriteString(valSchema, "qux"); + s.WriteString(*valSchema, "qux"); s.EndMap(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -260,10 +262,10 @@ TEST_F(XmlShapeSerializerTest, MapOfStrings) { TEST_F(XmlShapeSerializerTest, EmptyMap) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema mapMember("tags", ShapeType::Map); - s.BeginStructure(root); - s.BeginMap(mapMember, 0); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto mapMember = Schema::CreateMember("tags", ShapeType::Map); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 0); s.EndMap(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find(""), Aws::String::npos); @@ -271,15 +273,15 @@ TEST_F(XmlShapeSerializerTest, EmptyMap) { TEST_F(XmlShapeSerializerTest, MapOfStructures) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema mapMember("nodes", ShapeType::Map); - Schema valSchema("value", ShapeType::Structure); - Schema field("val", ShapeType::Integer); - s.BeginStructure(root); - s.BeginMap(mapMember, 1); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto mapMember = Schema::CreateMember("nodes", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::Structure); + auto field = Schema::CreateMember("val", ShapeType::Integer); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 1); s.WriteMapKey("a"); - s.BeginNestedStructure(valSchema); - s.WriteInteger(field, 1); + s.BeginNestedStructure(*valSchema); + s.WriteInteger(*field, 1); s.EndNestedStructure(); s.EndMap(); s.EndStructure(); @@ -290,22 +292,22 @@ TEST_F(XmlShapeSerializerTest, MapOfStructures) { TEST_F(XmlShapeSerializerTest, StructureWithListAndMap) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema strMember("name", ShapeType::String); - Schema listMember("tags", ShapeType::List); - Schema listElem("member", ShapeType::String); - Schema mapMember("meta", ShapeType::Map); - Schema mapVal("value", ShapeType::String); - - s.BeginStructure(root); - s.WriteString(strMember, "test"); - s.BeginList(listMember, 2); - s.WriteString(listElem, "t1"); - s.WriteString(listElem, "t2"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto strMember = Schema::CreateMember("name", ShapeType::String); + auto listMember = Schema::CreateMember("tags", ShapeType::List); + auto listElem = Schema::CreateMember("member", ShapeType::String); + auto mapMember = Schema::CreateMember("meta", ShapeType::Map); + auto mapVal = Schema::CreateMember("value", ShapeType::String); + + s.BeginStructure(*root); + s.WriteString(*strMember, "test"); + s.BeginList(*listMember, 2); + s.WriteString(*listElem, "t1"); + s.WriteString(*listElem, "t2"); s.EndList(); - s.BeginMap(mapMember, 1); + s.BeginMap(*mapMember, 1); s.WriteMapKey("k"); - s.WriteString(mapVal, "v"); + s.WriteString(*mapVal, "v"); s.EndMap(); s.EndStructure(); @@ -319,50 +321,50 @@ TEST_F(XmlShapeSerializerTest, StructureWithListAndMap) { TEST_F(XmlShapeSerializerTest, EscapesAmpersand) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("msg", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "a&b"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("msg", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "a&b"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("a&b"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, EscapesLessThan) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("msg", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "a("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("msg", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "aa<b"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, EscapesGreaterThan) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("msg", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "a>b"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("msg", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "a>b"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("a>b"), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, EscapesQuotes) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("msg", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "say \"hello\""); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("msg", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "say \"hello\""); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("say "hello""), Aws::String::npos); } TEST_F(XmlShapeSerializerTest, EscapesMultipleSpecialChars) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("expr", ShapeType::String); - s.BeginStructure(root); - s.WriteString(member, "x < 5 & y > 3"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("expr", ShapeType::String); + s.BeginStructure(*root); + s.WriteString(*member, "x < 5 & y > 3"); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("x < 5 & y > 3"), Aws::String::npos); } @@ -371,12 +373,12 @@ TEST_F(XmlShapeSerializerTest, EscapesMultipleSpecialChars) { TEST_F(XmlShapeSerializerTest, MaxDepthEnforcement) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema nested("n", ShapeType::Structure); - s.BeginStructure(root); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto nested = Schema::CreateMember("n", ShapeType::Structure); + s.BeginStructure(*root); bool hitLimit = false; for (int i = 0; i < 1000; i++) { - if (!s.BeginNestedStructure(nested)) { + if (!s.BeginNestedStructure(*nested)) { hitLimit = true; break; } @@ -388,11 +390,10 @@ TEST_F(XmlShapeSerializerTest, MaxDepthEnforcement) { TEST_F(XmlShapeSerializerTest, XmlNameOverridesMemberName) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("internalName", ShapeType::String); - member.SetTrait(XmlNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")); - s.BeginStructure(root); - s.WriteString(member, "hello"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("internalName", ShapeType::String, {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")}}); + s.BeginStructure(*root); + s.WriteString(*member, "hello"); s.EndStructure(); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("hello"), Aws::String::npos); @@ -401,11 +402,10 @@ TEST_F(XmlShapeSerializerTest, XmlNameOverridesMemberName) { TEST_F(XmlShapeSerializerTest, XmlNameOnStructure) { XmlShapeSerializer s; - Schema root("MyStruct", ShapeType::Structure); - root.SetTrait(XmlNameTrait::KEY(), Aws::MakeShared("Schema", "CustomRoot")); - Schema field("val", ShapeType::Integer); - s.BeginStructure(root); - s.WriteInteger(field, 42); + auto root = Schema::StructureBuilder("MyStruct", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "CustomRoot")}}).Build(); + auto field = Schema::CreateMember("val", ShapeType::Integer); + s.BeginStructure(*root); + s.WriteInteger(*field, 42); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("42"), Aws::String::npos); } @@ -414,15 +414,14 @@ TEST_F(XmlShapeSerializerTest, XmlNameOnStructure) { TEST_F(XmlShapeSerializerTest, FlattenedListOfStrings) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema listMember("item", ShapeType::List); - listMember.SetTrait(XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); - s.BeginList(listMember, 3); - s.WriteString(elem, "a"); - s.WriteString(elem, "b"); - s.WriteString(elem, "c"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto listMember = Schema::CreateMember("item", ShapeType::List, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}}); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); + s.BeginList(*listMember, 3); + s.WriteString(*elem, "a"); + s.WriteString(*elem, "b"); + s.WriteString(*elem, "c"); s.EndList(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -434,15 +433,13 @@ TEST_F(XmlShapeSerializerTest, FlattenedListOfStrings) { TEST_F(XmlShapeSerializerTest, FlattenedListWithXmlName) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema listMember("items", ShapeType::List); - listMember.SetTrait(XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")); - listMember.SetTrait(XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Tag")); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); - s.BeginList(listMember, 2); - s.WriteString(elem, "x"); - s.WriteString(elem, "y"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto listMember = Schema::CreateMember("items", ShapeType::List, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}, {XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Tag")}}); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); + s.BeginList(*listMember, 2); + s.WriteString(*elem, "x"); + s.WriteString(*elem, "y"); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("xy"), Aws::String::npos); @@ -452,14 +449,13 @@ TEST_F(XmlShapeSerializerTest, FlattenedListWithXmlName) { TEST_F(XmlShapeSerializerTest, CustomListItemName) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema listMember("things", ShapeType::List); - listMember.SetTrait(XmlListItemNameTrait::KEY(), Aws::MakeShared("Schema", "item")); - Schema elem("member", ShapeType::String); - s.BeginStructure(root); - s.BeginList(listMember, 2); - s.WriteString(elem, "a"); - s.WriteString(elem, "b"); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto listMember = Schema::CreateMember("things", ShapeType::List, {{XmlListItemNameTrait::KEY(), Aws::MakeShared("Schema", "item")}}); + auto elem = Schema::CreateMember("member", ShapeType::String); + s.BeginStructure(*root); + s.BeginList(*listMember, 2); + s.WriteString(*elem, "a"); + s.WriteString(*elem, "b"); s.EndList(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("ab"), Aws::String::npos); @@ -469,16 +465,13 @@ TEST_F(XmlShapeSerializerTest, CustomListItemName) { TEST_F(XmlShapeSerializerTest, CustomMapNames) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema mapMember("tags", ShapeType::Map); - mapMember.SetTrait(XmlMapEntryNameTrait::KEY(), Aws::MakeShared("Schema", "item")); - mapMember.SetTrait(XmlMapKeyNameTrait::KEY(), Aws::MakeShared("Schema", "tagKey")); - mapMember.SetTrait(XmlMapValueNameTrait::KEY(), Aws::MakeShared("Schema", "tagValue")); - Schema valSchema("value", ShapeType::String); - s.BeginStructure(root); - s.BeginMap(mapMember, 1); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto mapMember = Schema::CreateMember("tags", ShapeType::Map, {{XmlMapEntryNameTrait::KEY(), Aws::MakeShared("Schema", "item")}, {XmlMapKeyNameTrait::KEY(), Aws::MakeShared("Schema", "tagKey")}, {XmlMapValueNameTrait::KEY(), Aws::MakeShared("Schema", "tagValue")}}); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 1); s.WriteMapKey("color"); - s.WriteString(valSchema, "red"); + s.WriteString(*valSchema, "red"); s.EndMap(); s.EndStructure(); EXPECT_NE(s.GetPayload().GetResult().find("colorred"), Aws::String::npos); @@ -486,16 +479,15 @@ TEST_F(XmlShapeSerializerTest, CustomMapNames) { TEST_F(XmlShapeSerializerTest, FlattenedMap) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema mapMember("tag", ShapeType::Map); - mapMember.SetTrait(XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")); - Schema valSchema("value", ShapeType::String); - s.BeginStructure(root); - s.BeginMap(mapMember, 2); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto mapMember = Schema::CreateMember("tag", ShapeType::Map, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}}); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + s.BeginStructure(*root); + s.BeginMap(*mapMember, 2); s.WriteMapKey("k1"); - s.WriteString(valSchema, "v1"); + s.WriteString(*valSchema, "v1"); s.WriteMapKey("k2"); - s.WriteString(valSchema, "v2"); + s.WriteString(*valSchema, "v2"); s.EndMap(); s.EndStructure(); auto payload = s.GetPayload().GetResult(); @@ -506,10 +498,10 @@ TEST_F(XmlShapeSerializerTest, FlattenedMap) { TEST_F(XmlShapeSerializerTest, FloatValue) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("temp", ShapeType::Float); - s.BeginStructure(root); - s.WriteFloat(member, 1.5f); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("temp", ShapeType::Float); + s.BeginStructure(*root); + s.WriteFloat(*member, 1.5f); s.EndStructure(); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("1.5"), Aws::String::npos); @@ -517,10 +509,10 @@ TEST_F(XmlShapeSerializerTest, FloatValue) { TEST_F(XmlShapeSerializerTest, FloatNegativeValue) { XmlShapeSerializer s; - Schema root("Root", ShapeType::Structure); - Schema member("val", ShapeType::Float); - s.BeginStructure(root); - s.WriteFloat(member, -2.25f); + auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); + auto member = Schema::CreateMember("val", ShapeType::Float); + s.BeginStructure(*root); + s.WriteFloat(*member, -2.25f); s.EndStructure(); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("-2.25"), Aws::String::npos); From 46db32d6c538aadccd91638b8793ca3005938f8e Mon Sep 17 00:00:00 2001 From: Snigdha Date: Tue, 18 Aug 2026 11:10:23 -0400 Subject: [PATCH 2/4] Restructuring shape serializers --- .../client/schema/CborShapeSerializer.h | 17 +- .../client/schema/InterceptingSerializer.h | 76 ++ .../client/schema/JsonShapeSerializer.h | 17 +- .../smithy/client/schema/MapSerializer.h | 24 + .../include/smithy/client/schema/Schema.h | 7 +- .../smithy/client/schema/SchemaBuilder.h | 2 +- .../smithy/client/schema/SerializableStruct.h | 24 + .../smithy/client/schema/ShapeSerializer.h | 29 +- .../client/schema/SpecificShapeSerializer.h | 33 + .../smithy/client/schema/XmlShapeSerializer.h | 19 +- .../client/schema/CborShapeSerializer.cpp | 164 ++-- .../client/schema/JsonShapeSerializer.cpp | 297 ++++--- .../source/smithy/client/schema/Schema.cpp | 66 +- .../client/schema/XmlShapeSerializer.cpp | 734 ++++++++++-------- .../schema/CborShapeDeserializerTest.cpp | 216 +++--- .../client/schema/CborShapeSerializerTest.cpp | 402 ++++------ .../client/schema/JsonShapeSerializerTest.cpp | 325 ++++---- .../schema/SchemaSerializerTestHelpers.h | 39 + .../client/schema/XmlShapeSerializerTest.cpp | 342 ++++---- 19 files changed, 1514 insertions(+), 1319 deletions(-) create mode 100644 src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h create mode 100644 src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h create mode 100644 src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h create mode 100644 src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h create mode 100644 tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/CborShapeSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/CborShapeSerializer.h index e6350c9cb9b0..714874418d96 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/CborShapeSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/CborShapeSerializer.h @@ -5,6 +5,8 @@ #include #include +#include + namespace smithy { namespace schema { @@ -14,8 +16,9 @@ class SMITHY_API CborShapeSerializer final : public ShapeSerializer { CborShapeSerializer(); ~CborShapeSerializer(); - bool BeginStructure(const Schema& schema) override; - void EndStructure() override; + void WriteStruct(const Schema& schema, const SerializableStruct& value) override; + void WriteList(const Schema& schema, size_t size, const std::function& consumer) override; + void WriteMap(const Schema& schema, size_t size, const std::function& consumer) override; void WriteBoolean(const Schema& schema, bool value) override; void WriteInteger(const Schema& schema, int value) override; @@ -28,16 +31,6 @@ class SMITHY_API CborShapeSerializer final : public ShapeSerializer { void WriteEnum(const Schema& schema, int value) override; void WriteNull(const Schema& schema) override; - bool BeginList(const Schema& schema, size_t count) override; - void EndList() override; - - bool BeginMap(const Schema& schema, size_t count) override; - void WriteMapKey(const Aws::String& key) override; - void EndMap() override; - - bool BeginNestedStructure(const Schema& schema) override; - void EndNestedStructure() override; - SerializerOutcome GetPayload(); private: diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h new file mode 100644 index 000000000000..80bb7d86a310 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +#include + +namespace smithy { +namespace schema { + +// A ShapeSerializer that routes each write through Before()/After(). Before() +// returns the serializer that actually performs the write, so a subclass can +// act as a per-shape router (e.g. wrap a value in an XML element, then delegate +// the content to a value serializer). After() runs once the delegate returns. +class SMITHY_API InterceptingSerializer : public ShapeSerializer { + public: + void WriteStruct(const Schema& schema, const SerializableStruct& value) override { + Before(schema).WriteStruct(schema, value); + After(schema); + } + void WriteList(const Schema& schema, size_t size, const std::function& consumer) override { + Before(schema).WriteList(schema, size, consumer); + After(schema); + } + void WriteMap(const Schema& schema, size_t size, const std::function& consumer) override { + Before(schema).WriteMap(schema, size, consumer); + After(schema); + } + void WriteBoolean(const Schema& schema, bool value) override { + Before(schema).WriteBoolean(schema, value); + After(schema); + } + void WriteInteger(const Schema& schema, int value) override { + Before(schema).WriteInteger(schema, value); + After(schema); + } + void WriteLong(const Schema& schema, int64_t value) override { + Before(schema).WriteLong(schema, value); + After(schema); + } + void WriteFloat(const Schema& schema, float value) override { + Before(schema).WriteFloat(schema, value); + After(schema); + } + void WriteDouble(const Schema& schema, double value) override { + Before(schema).WriteDouble(schema, value); + After(schema); + } + void WriteString(const Schema& schema, const Aws::String& value) override { + Before(schema).WriteString(schema, value); + After(schema); + } + void WriteTimestamp(const Schema& schema, const Aws::Utils::DateTime& value) override { + Before(schema).WriteTimestamp(schema, value); + After(schema); + } + void WriteBlob(const Schema& schema, const Aws::Utils::ByteBuffer& value) override { + Before(schema).WriteBlob(schema, value); + After(schema); + } + void WriteEnum(const Schema& schema, int value) override { + Before(schema).WriteEnum(schema, value); + After(schema); + } + void WriteNull(const Schema& schema) override { + Before(schema).WriteNull(schema); + After(schema); + } + + protected: + virtual ShapeSerializer& Before(const Schema& schema) = 0; + virtual void After(const Schema& /*schema*/) {} +}; + +} // namespace schema +} // namespace smithy diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/JsonShapeSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/JsonShapeSerializer.h index 2ef94ef1e37c..941bf8d5d386 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/JsonShapeSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/JsonShapeSerializer.h @@ -5,6 +5,8 @@ #include #include +#include + namespace smithy { namespace schema { @@ -14,8 +16,9 @@ class SMITHY_API JsonShapeSerializer final : public ShapeSerializer { JsonShapeSerializer(); ~JsonShapeSerializer(); - bool BeginStructure(const Schema& schema) override; - void EndStructure() override; + void WriteStruct(const Schema& schema, const SerializableStruct& value) override; + void WriteList(const Schema& schema, size_t size, const std::function& consumer) override; + void WriteMap(const Schema& schema, size_t size, const std::function& consumer) override; void WriteBoolean(const Schema& schema, bool value) override; void WriteInteger(const Schema& schema, int value) override; @@ -28,16 +31,6 @@ class SMITHY_API JsonShapeSerializer final : public ShapeSerializer { void WriteEnum(const Schema& schema, int value) override; void WriteNull(const Schema& schema) override; - bool BeginList(const Schema& schema, size_t count) override; - void EndList() override; - - bool BeginMap(const Schema& schema, size_t count) override; - void WriteMapKey(const Aws::String& key) override; - void EndMap() override; - - bool BeginNestedStructure(const Schema& schema) override; - void EndNestedStructure() override; - SerializerOutcome GetPayload(); private: diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h new file mode 100644 index 000000000000..08c469b35eed --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include + +namespace smithy { +namespace schema { + +class ShapeSerializer; + +// Handed to the WriteMap consumer. Each entry writes its key, then the value +// through a nested consumer that receives the same underlying serializer, so map +// values can themselves be scalars, structs, lists, or maps. +class SMITHY_API MapSerializer { + public: + virtual ~MapSerializer() = default; + + virtual void WriteEntry(const Aws::String& key, const std::function& value) = 0; +}; + +} // namespace schema +} // namespace smithy diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h index 3df44acda3ea..fabcc97a85c3 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -61,10 +62,10 @@ class SMITHY_API Schema { virtual bool IsMember() const { return false; } virtual Aws::String GetMemberName() const { return {}; } virtual int GetMemberIndex() const { return 0; } - virtual const Schema* GetMemberTarget() const { return nullptr; } + virtual Aws::Crt::Optional> GetMemberTarget() const { return {}; } - virtual const Schema* GetMember(const char* /*name*/) const { return nullptr; } - virtual const Schema* GetMember(int /*index*/) const { return nullptr; } + virtual Aws::Crt::Optional> GetMember(const char* /*name*/) const { return {}; } + virtual Aws::Crt::Optional> GetMember(int /*index*/) const { return {}; } virtual uint16_t GetMemberCount() const { return 0; } template diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h index f986359cacfa..f5fae323d225 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h @@ -13,7 +13,7 @@ namespace schema { // may target shapes that are already built, or other builders that are not yet // built to describe recursive shapes. Once Build() is called the builder is // spent. Move-only; obtained from Schema::StructureBuilder and friends. -class SMITHY_API SchemaBuilder { +class SMITHY_API SchemaBuilder final { public: ~SchemaBuilder(); SchemaBuilder(SchemaBuilder&&) noexcept; diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h new file mode 100644 index 000000000000..c9fef8f1fd60 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +namespace smithy { +namespace schema { + +class ShapeSerializer; + +// Implemented by generated shapes. A shape knows its own Schema and how to write +// its members to a serializer; the wire format is decided entirely by which +// ShapeSerializer is passed in. This is the protocol-agnostic hook that lets one +// SerializeMembers() implementation produce JSON, XML, or CBOR. +class SMITHY_API SerializableStruct { + public: + virtual ~SerializableStruct() = default; + + virtual const Schema& GetSchema() const = 0; + virtual void SerializeMembers(ShapeSerializer& serializer) const = 0; +}; + +} // namespace schema +} // namespace smithy diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h index a9e218f7916e..831cb81de4b9 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h @@ -7,16 +7,31 @@ #include #include +#include namespace smithy { namespace schema { +class SerializableStruct; +class MapSerializer; + +// Push-based serializer: the model drives serialization by calling these +// methods, and the serializer owns all wire-format structure (delimiters, +// element boundaries). Aggregates hand control back through a consumer callback +// so nesting is expressed by re-entrancy rather than begin/end bookkeeping. +// +// smithy-java parameterizes the list/map consumers on a caller-supplied state +// type to avoid capturing lambdas; C++ virtual methods cannot be templated, so +// the consumer is a std::function and any state is captured by the closure. class SMITHY_API ShapeSerializer { public: virtual ~ShapeSerializer() = default; - virtual bool BeginStructure(const Schema& schema) = 0; - virtual void EndStructure() = 0; + virtual void WriteStruct(const Schema& schema, const SerializableStruct& value) = 0; + virtual void WriteList(const Schema& schema, size_t size, + const std::function& consumer) = 0; + virtual void WriteMap(const Schema& schema, size_t size, + const std::function& consumer) = 0; virtual void WriteBoolean(const Schema& schema, bool value) = 0; virtual void WriteInteger(const Schema& schema, int value) = 0; @@ -28,16 +43,6 @@ class SMITHY_API ShapeSerializer { virtual void WriteBlob(const Schema& schema, const Aws::Utils::ByteBuffer& value) = 0; virtual void WriteEnum(const Schema& schema, int value) = 0; virtual void WriteNull(const Schema& schema) = 0; - - virtual bool BeginList(const Schema& schema, size_t count) = 0; - virtual void EndList() = 0; - - virtual bool BeginMap(const Schema& schema, size_t count) = 0; - virtual void WriteMapKey(const Aws::String& key) = 0; - virtual void EndMap() = 0; - - virtual bool BeginNestedStructure(const Schema& schema) = 0; - virtual void EndNestedStructure() = 0; }; } // namespace schema diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h new file mode 100644 index 000000000000..6d240b26c264 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include + +namespace smithy { +namespace schema { + +// A ShapeSerializer whose writes all default to no-ops. Subclasses override only +// the writes they support; unsupported writes are silently ignored (the SDK does +// not use exceptions). Also usable directly as a "null" serializer to discard a +// member that should not be written in the current pass. +class SMITHY_API SpecificShapeSerializer : public ShapeSerializer { + public: + void WriteStruct(const Schema&, const SerializableStruct&) override {} + void WriteList(const Schema&, size_t, const std::function&) override {} + void WriteMap(const Schema&, size_t, const std::function&) override {} + void WriteBoolean(const Schema&, bool) override {} + void WriteInteger(const Schema&, int) override {} + void WriteLong(const Schema&, int64_t) override {} + void WriteFloat(const Schema&, float) override {} + void WriteDouble(const Schema&, double) override {} + void WriteString(const Schema&, const Aws::String&) override {} + void WriteTimestamp(const Schema&, const Aws::Utils::DateTime&) override {} + void WriteBlob(const Schema&, const Aws::Utils::ByteBuffer&) override {} + void WriteEnum(const Schema&, int) override {} + void WriteNull(const Schema&) override {} +}; + +} // namespace schema +} // namespace smithy diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/XmlShapeSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/XmlShapeSerializer.h index 89672fa0e54e..1ff4f95a852e 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/XmlShapeSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/XmlShapeSerializer.h @@ -5,6 +5,8 @@ #include #include +#include + namespace smithy { namespace schema { @@ -14,8 +16,9 @@ class SMITHY_API XmlShapeSerializer final : public ShapeSerializer { XmlShapeSerializer(); ~XmlShapeSerializer(); - bool BeginStructure(const Schema& schema) override; - void EndStructure() override; + void WriteStruct(const Schema& schema, const SerializableStruct& value) override; + void WriteList(const Schema& schema, size_t size, const std::function& consumer) override; + void WriteMap(const Schema& schema, size_t size, const std::function& consumer) override; void WriteBoolean(const Schema& schema, bool value) override; void WriteInteger(const Schema& schema, int value) override; @@ -28,18 +31,6 @@ class SMITHY_API XmlShapeSerializer final : public ShapeSerializer { void WriteEnum(const Schema& schema, int value) override; void WriteNull(const Schema& schema) override; - void WriteAttribute(const Schema& schema, const Aws::String& value); - - bool BeginList(const Schema& schema, size_t count) override; - void EndList() override; - - bool BeginMap(const Schema& schema, size_t count) override; - void WriteMapKey(const Aws::String& key) override; - void EndMap() override; - - bool BeginNestedStructure(const Schema& schema) override; - void EndNestedStructure() override; - SerializerOutcome GetPayload(); private: diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp index 1dacae7c9594..6422739ee95a 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp @@ -6,68 +6,61 @@ #include #include #include +#include +#include using namespace smithy::schema; using namespace Aws::Utils; using SerializerOutcome = Aws::Utils::Outcome>; -class CborShapeSerializer::Impl { +// Outer serializer: writes bare CBOR values and container framing (indefinite +// map for structs, definite array/map for lists/maps). Struct members are map +// entries, so the struct context writes the member name as the map key before +// the value; list/map contexts add no key. CBOR is length- or break-delimited, +// so there is no separator bookkeeping. +class CborShapeSerializer::Impl final : public ShapeSerializer { public: - bool BeginStructure(const Schema&) { + void WriteStruct(const Schema& /*schema*/, const SerializableStruct& value) override { m_encoder.WriteIndefMapStart(); - return true; + StructContext ctx(this); + value.SerializeMembers(ctx); + m_encoder.WriteBreak(); } - void EndStructure() { m_encoder.WriteBreak(); } - - void WriteBoolean(const Schema&, bool value) { m_encoder.WriteBool(value); } - - void WriteInteger(const Schema&, int value) { WriteIntValue(value); } - - void WriteLong(const Schema&, int64_t value) { WriteIntValue(value); } - - void WriteFloat(const Schema&, float value) { m_encoder.WriteFloat(value); } - - void WriteDouble(const Schema&, double value) { m_encoder.WriteFloat(value); } + void WriteList(const Schema& /*schema*/, size_t size, const std::function& consumer) override { + m_encoder.WriteArrayStart(size); + ListContext ctx(this); + consumer(ctx); + } - void WriteString(const Schema&, const Aws::String& value) { WriteText(value); } + void WriteMap(const Schema& /*schema*/, size_t size, const std::function& consumer) override { + m_encoder.WriteMapStart(size); + MapContext ctx(this); + consumer(ctx); + } - void WriteTimestamp(const Schema&, const DateTime& value) { + void WriteBoolean(const Schema&, bool value) override { m_encoder.WriteBool(value); } + void WriteInteger(const Schema&, int value) override { WriteIntValue(value); } + void WriteLong(const Schema&, int64_t value) override { WriteIntValue(value); } + void WriteFloat(const Schema&, float value) override { m_encoder.WriteFloat(value); } + void WriteDouble(const Schema&, double value) override { m_encoder.WriteFloat(value); } + void WriteString(const Schema&, const Aws::String& value) override { WriteText(value); } + void WriteTimestamp(const Schema&, const DateTime& value) override { m_encoder.WriteTag(1); WriteIntValue(value.Seconds()); } - - void WriteBlob(const Schema&, const ByteBuffer& value) { + void WriteBlob(const Schema&, const ByteBuffer& value) override { m_encoder.WriteBytes(Aws::Crt::ByteCursorFromArray(value.GetUnderlyingData(), value.GetLength())); } + void WriteEnum(const Schema& schema, int value) override { WriteInteger(schema, value); } + void WriteNull(const Schema&) override { m_encoder.WriteNull(); } - void WriteEnum(const Schema& schema, int value) { WriteInteger(schema, value); } - - void WriteNull(const Schema&) { m_encoder.WriteNull(); } - - bool BeginList(const Schema&, size_t count) { - m_encoder.WriteArrayStart(count); - return true; - } - - void EndList() {} - - bool BeginMap(const Schema&, size_t count) { - m_encoder.WriteMapStart(count); - return true; - } - - void WriteMapKey(const Aws::String& key) { WriteText(key); } - - void EndMap() {} - - bool BeginNestedStructure(const Schema&) { - m_encoder.WriteIndefMapStart(); - return true; + // Used by the context objects: a struct member's map key, and a map entry key. + void WriteMemberKey(const Schema& schema) { WriteText(schema.GetMemberName()); } + void WriteText(const Aws::String& str) { + m_encoder.WriteText(Aws::Crt::ByteCursorFromArray(reinterpret_cast(str.data()), str.size())); } - void EndNestedStructure() { m_encoder.WriteBreak(); } - SerializerOutcome GetPayload() { if (m_finalized) { return Aws::Client::AWSError( @@ -80,12 +73,65 @@ class CborShapeSerializer::Impl { } private: - Aws::Crt::Cbor::CborEncoder m_encoder; - bool m_finalized = false; + // Struct members: member name as the map key, then the value. + class StructContext final : public ShapeSerializer { + public: + explicit StructContext(Impl* outer) : m_outer(outer) {} + + void WriteStruct(const Schema& s, const SerializableStruct& v) override { m_outer->WriteMemberKey(s); m_outer->WriteStruct(s, v); } + void WriteList(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteMemberKey(s); m_outer->WriteList(s, n, c); } + void WriteMap(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteMemberKey(s); m_outer->WriteMap(s, n, c); } + void WriteBoolean(const Schema& s, bool v) override { m_outer->WriteMemberKey(s); m_outer->WriteBoolean(s, v); } + void WriteInteger(const Schema& s, int v) override { m_outer->WriteMemberKey(s); m_outer->WriteInteger(s, v); } + void WriteLong(const Schema& s, int64_t v) override { m_outer->WriteMemberKey(s); m_outer->WriteLong(s, v); } + void WriteFloat(const Schema& s, float v) override { m_outer->WriteMemberKey(s); m_outer->WriteFloat(s, v); } + void WriteDouble(const Schema& s, double v) override { m_outer->WriteMemberKey(s); m_outer->WriteDouble(s, v); } + void WriteString(const Schema& s, const Aws::String& v) override { m_outer->WriteMemberKey(s); m_outer->WriteString(s, v); } + void WriteTimestamp(const Schema& s, const DateTime& v) override { m_outer->WriteMemberKey(s); m_outer->WriteTimestamp(s, v); } + void WriteBlob(const Schema& s, const ByteBuffer& v) override { m_outer->WriteMemberKey(s); m_outer->WriteBlob(s, v); } + void WriteEnum(const Schema& s, int v) override { m_outer->WriteMemberKey(s); m_outer->WriteEnum(s, v); } + void WriteNull(const Schema& s) override { m_outer->WriteMemberKey(s); m_outer->WriteNull(s); } + + private: + Impl* m_outer; + }; + + // List elements: value only (the array carries the count). + class ListContext final : public ShapeSerializer { + public: + explicit ListContext(Impl* outer) : m_outer(outer) {} + + void WriteStruct(const Schema& s, const SerializableStruct& v) override { m_outer->WriteStruct(s, v); } + void WriteList(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteList(s, n, c); } + void WriteMap(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteMap(s, n, c); } + void WriteBoolean(const Schema& s, bool v) override { m_outer->WriteBoolean(s, v); } + void WriteInteger(const Schema& s, int v) override { m_outer->WriteInteger(s, v); } + void WriteLong(const Schema& s, int64_t v) override { m_outer->WriteLong(s, v); } + void WriteFloat(const Schema& s, float v) override { m_outer->WriteFloat(s, v); } + void WriteDouble(const Schema& s, double v) override { m_outer->WriteDouble(s, v); } + void WriteString(const Schema& s, const Aws::String& v) override { m_outer->WriteString(s, v); } + void WriteTimestamp(const Schema& s, const DateTime& v) override { m_outer->WriteTimestamp(s, v); } + void WriteBlob(const Schema& s, const ByteBuffer& v) override { m_outer->WriteBlob(s, v); } + void WriteEnum(const Schema& s, int v) override { m_outer->WriteEnum(s, v); } + void WriteNull(const Schema& s) override { m_outer->WriteNull(s); } + + private: + Impl* m_outer; + }; + + // Map entries: text key, then the value. + class MapContext final : public MapSerializer { + public: + explicit MapContext(Impl* outer) : m_outer(outer) {} + + void WriteEntry(const Aws::String& key, const std::function& value) override { + m_outer->WriteText(key); + value(*m_outer); + } - void WriteText(const Aws::String& str) { - m_encoder.WriteText(Aws::Crt::ByteCursorFromArray(reinterpret_cast(str.data()), str.size())); - } + private: + Impl* m_outer; + }; void WriteIntValue(int64_t value) { if (value >= 0) { @@ -94,13 +140,23 @@ class CborShapeSerializer::Impl { m_encoder.WriteNegInt(static_cast(-(value + 1))); } } + + Aws::Crt::Cbor::CborEncoder m_encoder; + bool m_finalized = false; }; CborShapeSerializer::CborShapeSerializer() : m_impl(Aws::MakeUnique("CborShapeSerializer")) {} CborShapeSerializer::~CborShapeSerializer() = default; -bool CborShapeSerializer::BeginStructure(const Schema& schema) { return m_impl->BeginStructure(schema); } -void CborShapeSerializer::EndStructure() { m_impl->EndStructure(); } +void CborShapeSerializer::WriteStruct(const Schema& schema, const SerializableStruct& value) { + m_impl->WriteStruct(schema, value); +} +void CborShapeSerializer::WriteList(const Schema& schema, size_t size, const std::function& consumer) { + m_impl->WriteList(schema, size, consumer); +} +void CborShapeSerializer::WriteMap(const Schema& schema, size_t size, const std::function& consumer) { + m_impl->WriteMap(schema, size, consumer); +} void CborShapeSerializer::WriteBoolean(const Schema& schema, bool value) { m_impl->WriteBoolean(schema, value); } void CborShapeSerializer::WriteInteger(const Schema& schema, int value) { m_impl->WriteInteger(schema, value); } void CborShapeSerializer::WriteLong(const Schema& schema, int64_t value) { m_impl->WriteLong(schema, value); } @@ -111,11 +167,5 @@ void CborShapeSerializer::WriteTimestamp(const Schema& schema, const DateTime& v void CborShapeSerializer::WriteBlob(const Schema& schema, const ByteBuffer& value) { m_impl->WriteBlob(schema, value); } void CborShapeSerializer::WriteEnum(const Schema& schema, int value) { m_impl->WriteEnum(schema, value); } void CborShapeSerializer::WriteNull(const Schema& schema) { m_impl->WriteNull(schema); } -bool CborShapeSerializer::BeginList(const Schema& schema, size_t count) { return m_impl->BeginList(schema, count); } -void CborShapeSerializer::EndList() { m_impl->EndList(); } -bool CborShapeSerializer::BeginMap(const Schema& schema, size_t count) { return m_impl->BeginMap(schema, count); } -void CborShapeSerializer::WriteMapKey(const Aws::String& key) { m_impl->WriteMapKey(key); } -void CborShapeSerializer::EndMap() { m_impl->EndMap(); } -bool CborShapeSerializer::BeginNestedStructure(const Schema& schema) { return m_impl->BeginNestedStructure(schema); } -void CborShapeSerializer::EndNestedStructure() { m_impl->EndNestedStructure(); } + CborShapeSerializer::SerializerOutcome CborShapeSerializer::GetPayload() { return m_impl->GetPayload(); } diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp index a9eaacc7d238..332066d1561e 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp @@ -7,8 +7,8 @@ #include #include #include - -#include +#include +#include #include "aws/core/client/AWSClient.h" #include "aws/core/utils/Outcome.h" @@ -18,198 +18,193 @@ using namespace smithy::schema; using namespace Aws::Utils; using SerializerOutcome = Aws::Utils::Outcome>; -static constexpr int MAX_DEPTH = 1000; +static constexpr int MAX_DEPTH = 64; -class JsonShapeSerializer::Impl { +// The serializer that writes bare values and container delimiters, and hands +// each container's body to a context object. The context objects prepend the +// per-position prefix (a struct member's field name, or a list/map element's +// comma) and delegate the value itself back to this outer serializer. This is +// the SmithyJsonSerializer structure: contexts express "what precedes a value" +// through polymorphism rather than a runtime branch. +class JsonShapeSerializer::Impl final : public ShapeSerializer { public: Impl() { m_buf.reserve(8192); } - bool BeginStructure(const Schema&) { - if (m_depth + 1 >= MAX_DEPTH) { - m_errorMessage = "Maximum nesting depth exceeded"; - return false; + void WriteStruct(const Schema& /*schema*/, const SerializableStruct& value) override { + if (!OpenContainer('{')) { + return; } - - m_buf += '{'; - m_depth++; - m_needsComma[m_depth] = false; - m_isMap[m_depth] = false; - m_isList[m_depth] = false; - - return true; - } - - void EndStructure() { - m_depth--; - m_buf += '}'; - } - - void WriteBoolean(const Schema& schema, bool value) { - WriteFieldName(schema); - m_buf += value ? "true" : "false"; + StructContext ctx(this); + value.SerializeMembers(ctx); + CloseContainer('}'); } - void WriteInteger(const Schema& schema, int value) { - WriteFieldName(schema); - m_buf += StringUtils::to_string(value); - } - - void WriteLong(const Schema& schema, int64_t value) { - WriteFieldName(schema); - m_buf += StringUtils::to_string(value); - } - - void WriteFloat(const Schema& schema, float value) { - WriteFieldName(schema); - m_buf += StringUtils::to_string(value); - } - - void WriteDouble(const Schema& schema, double value) { - WriteFieldName(schema); - m_buf += StringUtils::to_string(value); - } - - void WriteString(const Schema& schema, const Aws::String& value) { - WriteFieldName(schema); - Aws::Schema::WriteQuotedJsonString(m_buf, value); + void WriteList(const Schema& /*schema*/, size_t, const std::function& consumer) override { + if (!OpenContainer('[')) { + return; + } + ListContext ctx(this); + consumer(ctx); + CloseContainer(']'); } - void WriteTimestamp(const Schema& schema, const DateTime& value) { - WriteFieldName(schema); + void WriteMap(const Schema& /*schema*/, size_t, const std::function& consumer) override { + if (!OpenContainer('{')) { + return; + } + MapContext ctx(this); + consumer(ctx); + CloseContainer('}'); + } + + // Bare scalar writers: value only, no prefix. + void WriteBoolean(const Schema&, bool value) override { m_buf += value ? "true" : "false"; } + void WriteInteger(const Schema&, int value) override { m_buf += StringUtils::to_string(value); } + void WriteLong(const Schema&, int64_t value) override { m_buf += StringUtils::to_string(value); } + void WriteFloat(const Schema&, float value) override { m_buf += StringUtils::to_string(value); } + void WriteDouble(const Schema&, double value) override { m_buf += StringUtils::to_string(value); } + void WriteString(const Schema&, const Aws::String& value) override { Aws::Schema::WriteQuotedJsonString(m_buf, value); } + void WriteTimestamp(const Schema&, const DateTime& value) override { m_buf += StringUtils::to_string(value.SecondsWithMSPrecision()); } - - void WriteBlob(const Schema& schema, const ByteBuffer& value) { - WriteFieldName(schema); + void WriteBlob(const Schema&, const ByteBuffer& value) override { m_buf += '"'; m_buf += HashingUtils::Base64Encode(value); m_buf += '"'; } + void WriteEnum(const Schema& schema, int value) override { WriteInteger(schema, value); } + void WriteNull(const Schema&) override { m_buf += "null"; } - void WriteEnum(const Schema& schema, int value) { WriteInteger(schema, value); } - - void WriteNull(const Schema& schema) { - WriteFieldName(schema); - m_buf += "null"; - } - - bool BeginList(const Schema& schema, size_t) { - if (m_depth + 1 >= MAX_DEPTH) { - m_errorMessage = "Maximum nesting depth exceeded"; - return false; + // Prefix primitives, used by the context objects. + void WriteCommaIfNeeded() { + if (m_needsComma[m_depth]) { + m_buf += ','; + } else { + m_needsComma[m_depth] = true; } + } - WriteFieldName(schema); - m_buf += '['; - m_depth++; - m_needsComma[m_depth] = false; - m_isMap[m_depth] = false; - m_isList[m_depth] = true; - - return true; + void WriteKey(const Aws::String& key) { + Aws::Schema::WriteQuotedJsonString(m_buf, key); + m_buf += ':'; } - void EndList() { - m_depth--; - m_buf += ']'; + void WriteFieldName(const Schema& schema) { + WriteCommaIfNeeded(); + const auto jsonName = schema.GetTrait(JsonNameTrait::KEY()); + WriteKey(jsonName ? jsonName->GetValue() : schema.GetMemberName()); } - bool BeginMap(const Schema& schema, size_t) { - if (m_depth + 1 >= MAX_DEPTH) { - m_errorMessage = "Maximum nesting depth exceeded"; - return false; + SerializerOutcome GetPayload() { + if (m_finalized || !m_errorMessage.empty()) { + return Aws::Client::AWSError( + Aws::Client::CoreErrors::INTERNAL_FAILURE, "SerializationException", + !m_errorMessage.empty() ? m_errorMessage : "Serializer has already been finalized", false); } - - WriteFieldName(schema); - m_buf += '{'; - m_depth++; - m_needsComma[m_depth] = false; - m_isMap[m_depth] = true; - m_isList[m_depth] = false; - - return true; + m_finalized = true; + return std::move(m_buf); } - void WriteMapKey(const Aws::String& key) { m_currentMapKey = key; } + private: + // Struct members: field name, then the value written bare by the outer. + class StructContext final : public ShapeSerializer { + public: + explicit StructContext(Impl* outer) : m_outer(outer) {} + + void WriteStruct(const Schema& s, const SerializableStruct& v) override { m_outer->WriteFieldName(s); m_outer->WriteStruct(s, v); } + void WriteList(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteFieldName(s); m_outer->WriteList(s, n, c); } + void WriteMap(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteFieldName(s); m_outer->WriteMap(s, n, c); } + void WriteBoolean(const Schema& s, bool v) override { m_outer->WriteFieldName(s); m_outer->WriteBoolean(s, v); } + void WriteInteger(const Schema& s, int v) override { m_outer->WriteFieldName(s); m_outer->WriteInteger(s, v); } + void WriteLong(const Schema& s, int64_t v) override { m_outer->WriteFieldName(s); m_outer->WriteLong(s, v); } + void WriteFloat(const Schema& s, float v) override { m_outer->WriteFieldName(s); m_outer->WriteFloat(s, v); } + void WriteDouble(const Schema& s, double v) override { m_outer->WriteFieldName(s); m_outer->WriteDouble(s, v); } + void WriteString(const Schema& s, const Aws::String& v) override { m_outer->WriteFieldName(s); m_outer->WriteString(s, v); } + void WriteTimestamp(const Schema& s, const DateTime& v) override { m_outer->WriteFieldName(s); m_outer->WriteTimestamp(s, v); } + void WriteBlob(const Schema& s, const ByteBuffer& v) override { m_outer->WriteFieldName(s); m_outer->WriteBlob(s, v); } + void WriteEnum(const Schema& s, int v) override { m_outer->WriteFieldName(s); m_outer->WriteEnum(s, v); } + void WriteNull(const Schema& s) override { m_outer->WriteFieldName(s); m_outer->WriteNull(s); } + + private: + Impl* m_outer; + }; + + // List elements: comma, then the value written bare by the outer. + class ListContext final : public ShapeSerializer { + public: + explicit ListContext(Impl* outer) : m_outer(outer) {} + + void WriteStruct(const Schema& s, const SerializableStruct& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteStruct(s, v); } + void WriteList(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteList(s, n, c); } + void WriteMap(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteMap(s, n, c); } + void WriteBoolean(const Schema& s, bool v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteBoolean(s, v); } + void WriteInteger(const Schema& s, int v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteInteger(s, v); } + void WriteLong(const Schema& s, int64_t v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteLong(s, v); } + void WriteFloat(const Schema& s, float v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteFloat(s, v); } + void WriteDouble(const Schema& s, double v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteDouble(s, v); } + void WriteString(const Schema& s, const Aws::String& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteString(s, v); } + void WriteTimestamp(const Schema& s, const DateTime& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteTimestamp(s, v); } + void WriteBlob(const Schema& s, const ByteBuffer& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteBlob(s, v); } + void WriteEnum(const Schema& s, int v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteEnum(s, v); } + void WriteNull(const Schema& s) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteNull(s); } + + private: + Impl* m_outer; + }; + + // Map entries: comma, key, then the value written bare by the outer. + class MapContext final : public MapSerializer { + public: + explicit MapContext(Impl* outer) : m_outer(outer) {} + + void WriteEntry(const Aws::String& key, const std::function& value) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteKey(key); + value(*m_outer); + } - void EndMap() { - m_depth--; - m_buf += '}'; - } + private: + Impl* m_outer; + }; - bool BeginNestedStructure(const Schema& schema) { + bool OpenContainer(char open) { + if (!m_errorMessage.empty()) { + return false; + } if (m_depth + 1 >= MAX_DEPTH) { m_errorMessage = "Maximum nesting depth exceeded"; return false; } - - WriteFieldName(schema); - m_buf += '{'; - m_depth++; + m_buf += open; + ++m_depth; m_needsComma[m_depth] = false; - m_isMap[m_depth] = false; - m_isList[m_depth] = false; - return true; } - void EndNestedStructure() { - m_depth--; - m_buf += '}'; - } - - SerializerOutcome GetPayload() { - if (m_finalized || !m_errorMessage.empty()) { - return Aws::Client::AWSError( - Aws::Client::CoreErrors::INTERNAL_FAILURE, "SerializationException", - !m_errorMessage.empty() ? m_errorMessage : "Serializer has already been finalized", false); - } - m_finalized = true; - return std::move(m_buf); + void CloseContainer(char close) { + --m_depth; + m_buf += close; } - private: Aws::String m_buf; int m_depth = 0; Aws::Array m_needsComma{}; - Aws::Array m_isMap{}; - Aws::Array m_isList{}; - Aws::String m_currentMapKey; bool m_finalized = false; Aws::String m_errorMessage; - - void WriteCommaIfNeeded() { - if (m_needsComma[m_depth]) { - m_buf += ','; - } else { - m_needsComma[m_depth] = true; - } - } - - void WriteKey(const Aws::String& key) { - Aws::Schema::WriteQuotedJsonString(m_buf, key); - m_buf += ':'; - } - - void WriteFieldName(const Schema& schema) { - WriteCommaIfNeeded(); - if (m_isList[m_depth]) { - return; - } - if (m_depth > 0 && m_isMap[m_depth]) { - WriteKey(m_currentMapKey); - } else { - const auto jsonName = schema.GetTrait(JsonNameTrait::KEY()); - WriteKey(jsonName ? jsonName->GetValue() : schema.GetMemberName()); - } - } }; JsonShapeSerializer::JsonShapeSerializer() : m_impl(Aws::MakeUnique("JsonShapeSerializer")) {} JsonShapeSerializer::~JsonShapeSerializer() = default; -bool JsonShapeSerializer::BeginStructure(const Schema& schema) { return m_impl->BeginStructure(schema); } -void JsonShapeSerializer::EndStructure() { m_impl->EndStructure(); } +void JsonShapeSerializer::WriteStruct(const Schema& schema, const SerializableStruct& value) { + m_impl->WriteStruct(schema, value); +} +void JsonShapeSerializer::WriteList(const Schema& schema, size_t size, const std::function& consumer) { + m_impl->WriteList(schema, size, consumer); +} +void JsonShapeSerializer::WriteMap(const Schema& schema, size_t size, const std::function& consumer) { + m_impl->WriteMap(schema, size, consumer); +} void JsonShapeSerializer::WriteBoolean(const Schema& schema, bool value) { m_impl->WriteBoolean(schema, value); } void JsonShapeSerializer::WriteInteger(const Schema& schema, int value) { m_impl->WriteInteger(schema, value); } void JsonShapeSerializer::WriteLong(const Schema& schema, int64_t value) { m_impl->WriteLong(schema, value); } @@ -220,11 +215,5 @@ void JsonShapeSerializer::WriteTimestamp(const Schema& schema, const DateTime& v void JsonShapeSerializer::WriteBlob(const Schema& schema, const ByteBuffer& value) { m_impl->WriteBlob(schema, value); } void JsonShapeSerializer::WriteEnum(const Schema& schema, int value) { m_impl->WriteEnum(schema, value); } void JsonShapeSerializer::WriteNull(const Schema& schema) { m_impl->WriteNull(schema); } -bool JsonShapeSerializer::BeginList(const Schema& schema, size_t count) { return m_impl->BeginList(schema, count); } -void JsonShapeSerializer::EndList() { m_impl->EndList(); } -bool JsonShapeSerializer::BeginMap(const Schema& schema, size_t count) { return m_impl->BeginMap(schema, count); } -void JsonShapeSerializer::WriteMapKey(const Aws::String& key) { m_impl->WriteMapKey(key); } -void JsonShapeSerializer::EndMap() { m_impl->EndMap(); } -bool JsonShapeSerializer::BeginNestedStructure(const Schema& schema) { return m_impl->BeginNestedStructure(schema); } -void JsonShapeSerializer::EndNestedStructure() { m_impl->EndNestedStructure(); } + JsonShapeSerializer::SerializerOutcome JsonShapeSerializer::GetPayload() { return m_impl->GetPayload(); } diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp index 98b3a3bcf615..794a2fe5c9a9 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace smithy { @@ -48,36 +49,51 @@ class ScalarSchema final : public Schema { }; // A named member of an aggregate shape. Delegates its type to the shape it -// targets. A member normally owns its target; the non-owning overload is used -// only for recursive members, where the target is kept alive by the definition -// site so the graph does not form a reference cycle. +// targets. A member normally owns its target; the weak overload is used only for +// recursive members, where the target is kept alive by the definition site so +// the graph does not form a reference cycle. Either way GetMemberTarget() hands +// back a shared_ptr that lifetime-extends the target while the caller holds it. class MemberSchema final : public Schema { public: MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::shared_ptr target, TraitMap traits) - : m_memberName(name), m_id(id), m_memberIndex(index), m_ownedTarget(std::move(target)), - m_target(m_ownedTarget.get()) { + : m_memberName(name), m_id(id), m_memberIndex(index), m_ownedTarget(std::move(target)) { m_traits = std::move(traits); } - MemberSchema(const Aws::String& name, const Aws::String& id, int index, const Schema* target, TraitMap traits) - : m_memberName(name), m_id(id), m_memberIndex(index), m_target(target) { + MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::weak_ptr target, + TraitMap traits) + : m_memberName(name), m_id(id), m_memberIndex(index), m_weakTarget(std::move(target)) { m_traits = std::move(traits); } - ShapeType GetType() const override { return m_target ? m_target->GetType() : ShapeType::Structure; } + ShapeType GetType() const override { + const auto target = ResolvedTarget(); + return target ? target->GetType() : ShapeType::Structure; + } const char* GetId() const override { return m_id.c_str(); } bool IsMember() const override { return true; } Aws::String GetMemberName() const override { return m_memberName; } int GetMemberIndex() const override { return m_memberIndex; } - const Schema* GetMemberTarget() const override { return m_target; } + + Aws::Crt::Optional> GetMemberTarget() const override { + const auto target = ResolvedTarget(); + if (target) { + return target; + } + return {}; + } private: + std::shared_ptr ResolvedTarget() const { + return m_ownedTarget ? m_ownedTarget : m_weakTarget.lock(); + } + Aws::String m_memberName; Aws::String m_id; int m_memberIndex; std::shared_ptr m_ownedTarget; - const Schema* m_target; + std::weak_ptr m_weakTarget; }; // A shape that carries members (structure, union, list, map). Owns its member @@ -92,26 +108,33 @@ class RootSchema final : public Schema { ShapeType GetType() const override { return m_type; } const char* GetId() const override { return m_id.c_str(); } - const Schema* GetMember(const char* name) const override { + Aws::Crt::Optional> GetMember(const char* name) const override { auto it = m_nameToIndex.find(name); if (it == m_nameToIndex.end()) { - return nullptr; + return {}; } - return m_members[it->second].get(); + return m_members[it->second]; } - const Schema* GetMember(int index) const override { + Aws::Crt::Optional> GetMember(int index) const override { if (index < 0 || static_cast(index) >= m_members.size()) { - return nullptr; + return {}; } - return m_members[index].get(); + return m_members[index]; } uint16_t GetMemberCount() const override { return static_cast(m_members.size()); } - // Used only by SchemaBuilder while assembling the shape. + // Used only by SchemaBuilder while assembling the shape. Member names must be + // unique within a shape; a duplicate is a codegen/programming error, so reject + // it rather than shadowing the earlier member (which would leave the first + // unreachable by name yet still counted in GetMemberCount()). void AddMember(const std::shared_ptr& member) { - m_nameToIndex[member->GetMemberName()] = static_cast(m_members.size()); + const auto inserted = m_nameToIndex.emplace(member->GetMemberName(), static_cast(m_members.size())); + assert(inserted.second && "duplicate member name in schema"); + if (!inserted.second) { + return; + } m_members.push_back(member); } @@ -243,10 +266,11 @@ class SchemaBuilder::SchemaBuilderImpl { member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, pending.eagerTarget, pending.traits); } else if (pending.deferredTarget != nullptr) { - // Recursive member references a target kept alive by the definition site. - auto target = pending.deferredTarget->Build(); + // Recursive member holds a weak reference to a target kept alive by the + // definition site, so the schema graph does not form a reference cycle. + std::weak_ptr target = pending.deferredTarget->Build(); member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, - target.get(), pending.traits); + target, pending.traits); } shell->AddMember(member); ++index; diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp index b39311c9deae..8d981781ac2a 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp @@ -2,220 +2,170 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ +#include #include +#include #include -#include +#include +#include +#include +#include #include #include using namespace smithy::schema; using namespace Aws::Utils; +using SerializerOutcome = Aws::Utils::Outcome>; static constexpr int MAX_DEPTH = 500; -class XmlShapeSerializer::Impl { - public: - Impl() { m_buf.reserve(8192); } +namespace { - bool BeginStructure(const Schema& schema) { - if (m_depth + 1 >= MAX_DEPTH) { - m_errorMessage = "Maximum serialization depth exceeded"; - return false; +void AppendXmlEscaped(Aws::String& buf, const Aws::String& value) { + const char* data = value.data(); + const size_t len = value.size(); + size_t i = 0; + while (i < len) { + size_t start = i; + while (i < len && data[i] != '&' && data[i] != '<' && data[i] != '>' && data[i] != '"' && data[i] != '\'') { + i++; } - FlushOpenTag(); - const auto name = GetXmlName(schema); - if (!name.empty()) { - m_buf += '<'; - m_buf += name; - const auto ns = schema.GetTrait(XmlNamespaceTrait::KEY()); - if (ns && !ns->GetUri().empty()) { - if (ns->GetPrefix().empty()) { - m_buf += " xmlns=\""; - } else { - m_buf += " xmlns:"; - m_buf += ns->GetPrefix(); - m_buf += "=\""; - } - m_buf += ns->GetUri(); - m_buf += '"'; - } - m_hasOpenTag = true; + if (i > start) { + buf.append(data + start, i - start); } - m_depth++; - m_tagStack[m_depth] = name; - return true; - } - - void EndStructure() { - FlushOpenTag(); - const auto& name = m_tagStack[m_depth]; - m_depth--; - if (!name.empty()) { - CloseTag(name); - } - } - - void WriteAttribute(const Schema& schema, const Aws::String& value) { - if (!m_hasOpenTag) return; - const auto name = GetXmlName(schema); - m_buf += ' '; - m_buf += name; - m_buf += "=\""; - WriteXmlEscaped(m_buf, value); - m_buf += '"'; - } - - void WriteBoolean(const Schema& schema, bool value) { WrapValue(GetXmlName(schema), value ? "true" : "false"); } - - void WriteInteger(const Schema& schema, int value) { WrapValue(GetXmlName(schema), StringUtils::to_string(value)); } - - void WriteLong(const Schema& schema, int64_t value) { WrapValue(GetXmlName(schema), StringUtils::to_string(value)); } - - void WriteFloat(const Schema& schema, float value) { WrapValue(GetXmlName(schema), StringUtils::to_string(value)); } - - void WriteDouble(const Schema& schema, double value) { WrapValue(GetXmlName(schema), StringUtils::to_string(value)); } - - void WriteString(const Schema& schema, const Aws::String& value) { WrapEscapedValue(GetXmlName(schema), value); } - - void WriteTimestamp(const Schema& schema, const DateTime& value) { - WrapValue(GetXmlName(schema), value.ToGmtString(Aws::Utils::DateFormat::ISO_8601)); - } - - void WriteBlob(const Schema& schema, const ByteBuffer& value) { WrapValue(GetXmlName(schema), HashingUtils::Base64Encode(value)); } - - void WriteEnum(const Schema& schema, int value) { WriteInteger(schema, value); } - - void WriteNull(const Schema&) { - // XML omits null values — no output - } - - bool BeginList(const Schema& schema, size_t) { - if (m_depth + 1 >= MAX_DEPTH) { - m_errorMessage = "Maximum serialization depth exceeded"; - return false; - } - FlushOpenTag(); - const auto name = GetXmlName(schema); - if (IsFlattened(schema)) { - // Flattened: no wrapper element, items repeat with the list's xmlName - m_depth++; - m_tagStack[m_depth] = name; - m_listItemName[m_depth] = name; - m_isList[m_depth] = true; - m_isFlattened[m_depth] = true; - m_isMap[m_depth] = false; - } else { - // Non-flattened: wrap in container element, items use configurable name - if (!name.empty()) { - OpenTag(name); + if (i < len) { + switch (data[i]) { + case '&': buf += "&"; break; + case '<': buf += "<"; break; + case '>': buf += ">"; break; + case '"': buf += """; break; + case '\'': buf += "'"; break; } - m_depth++; - m_tagStack[m_depth] = name; - m_listItemName[m_depth] = GetListItemName(schema); - m_isList[m_depth] = true; - m_isFlattened[m_depth] = false; - m_isMap[m_depth] = false; - } - return true; - } - - void EndList() { - const auto& name = m_tagStack[m_depth]; - bool flattened = m_isFlattened[m_depth]; - m_isList[m_depth] = false; - m_depth--; - if (!flattened && !name.empty()) { - CloseTag(name); + i++; } } - - bool BeginMap(const Schema& schema, size_t) { - if (m_depth + 1 >= MAX_DEPTH) { - m_errorMessage = "Maximum serialization depth exceeded"; - return false; - } - FlushOpenTag(); - const auto name = GetXmlName(schema); - bool flattened = IsFlattened(schema); - if (!flattened && !name.empty()) { - OpenTag(name); - } - m_depth++; - m_tagStack[m_depth] = name; - m_isMap[m_depth] = true; - m_isList[m_depth] = false; - m_isFlattened[m_depth] = flattened; - m_mapInEntry[m_depth] = false; - m_mapEntryName[m_depth] = flattened ? name : GetMapEntryName(schema); - m_mapKeyName[m_depth] = GetMapKeyName(schema); - m_mapValueName[m_depth] = GetMapValueName(schema); - return true; - } - - void WriteMapKey(const Aws::String& key) { - OpenTag(m_mapEntryName[m_depth]); - OpenTag(m_mapKeyName[m_depth]); - WriteXmlEscaped(m_buf, key); - CloseTag(m_mapKeyName[m_depth]); - m_mapInEntry[m_depth] = true; - } - - void EndMap() { - const auto& name = m_tagStack[m_depth]; - bool flattened = m_isFlattened[m_depth]; - m_isMap[m_depth] = false; - m_depth--; - if (!flattened && !name.empty()) { - CloseTag(name); - } - } - - bool BeginNestedStructure(const Schema& schema) { - if (m_depth + 1 >= MAX_DEPTH) { - m_errorMessage = "Maximum serialization depth exceeded"; - return false; - } - FlushOpenTag(); - if (m_depth > 0 && m_isMap[m_depth] && m_mapInEntry[m_depth]) { - // Inside a map entry: open as the struct wrapper - OpenTag(m_mapValueName[m_depth]); - m_mapInEntry[m_depth] = false; - m_depth++; - m_tagStack[m_depth] = ""; - m_isList[m_depth] = false; - m_isMap[m_depth] = false; - m_isFlattened[m_depth] = false; - m_mapInEntry[m_depth] = false; - m_isMapValueStruct[m_depth] = true; - return true; - } - const auto name = GetEffectiveTag(schema); - OpenTag(name); - m_depth++; - m_tagStack[m_depth] = name; - m_isList[m_depth] = false; - m_isMap[m_depth] = false; - m_isFlattened[m_depth] = false; - m_mapInEntry[m_depth] = false; - m_isMapValueStruct[m_depth] = false; - return true; - } - - void EndNestedStructure() { - const auto& name = m_tagStack[m_depth]; - bool closeMapEntry = m_isMapValueStruct[m_depth]; - m_depth--; - if (!name.empty()) { - CloseTag(name); - } - if (closeMapEntry) { - CloseTag(m_mapValueName[m_depth]); - CloseTag(m_mapEntryName[m_depth]); - } +} + +} // namespace + +// XML serializer following smithy-java's SmithyXmlSerializer: an outer +// InterceptingSerializer wraps each value in its element (Before writes the +// start tag, After the end tag), delegating the element content to a value +// serializer. Structs are two-pass — attributes are written into the still-open +// start tag first, the tag is then closed, then child-element members are +// written. Names, namespaces, flattening, and attribute-ness are resolved from +// schema traits rather than precomputed tables. +class XmlShapeSerializer::Impl final : public InterceptingSerializer { + public: + // Writes an element's content (the wrapping element is written by the caller). + class ValueSerializer final : public ShapeSerializer { + public: + explicit ValueSerializer(Impl* outer) : m_outer(outer) {} + void WriteStruct(const Schema& schema, const SerializableStruct& value) override; + void WriteList(const Schema& schema, size_t size, const std::function& consumer) override; + void WriteMap(const Schema& schema, size_t size, const std::function& consumer) override; + void WriteBoolean(const Schema& schema, bool value) override; + void WriteInteger(const Schema& schema, int value) override; + void WriteLong(const Schema& schema, int64_t value) override; + void WriteFloat(const Schema& schema, float value) override; + void WriteDouble(const Schema& schema, double value) override; + void WriteString(const Schema& schema, const Aws::String& value) override; + void WriteTimestamp(const Schema& schema, const Aws::Utils::DateTime& value) override; + void WriteBlob(const Schema& schema, const Aws::Utils::ByteBuffer& value) override; + void WriteEnum(const Schema& schema, int value) override; + void WriteNull(const Schema& schema) override; + + private: + Impl* m_outer; + }; + + // Routes each struct member: skips attributes (handled in the attribute pass), + // writes an element wrapper for ordinary members, and skips the wrapper for + // flattened list/map members. + class StructElementSerializer final : public InterceptingSerializer { + public: + explicit StructElementSerializer(Impl* outer) : m_outer(outer) {} + + protected: + ShapeSerializer& Before(const Schema& schema) override; + void After(const Schema& schema) override; + + private: + Impl* m_outer; + }; + + // Attribute pass: routes attribute members to the inline attribute writer and + // discards everything else. + class StructAttributeSerializer final : public InterceptingSerializer { + public: + explicit StructAttributeSerializer(Impl* outer) : m_outer(outer) {} + + protected: + ShapeSerializer& Before(const Schema& schema) override; + + private: + Impl* m_outer; + }; + + // Writes a scalar member as an attribute on the currently-open start tag. + class InlineAttributeSerializer final : public SpecificShapeSerializer { + public: + explicit InlineAttributeSerializer(Impl* outer) : m_outer(outer) {} + void WriteBoolean(const Schema& schema, bool value) override; + void WriteInteger(const Schema& schema, int value) override; + void WriteLong(const Schema& schema, int64_t value) override; + void WriteFloat(const Schema& schema, float value) override; + void WriteDouble(const Schema& schema, double value) override; + void WriteString(const Schema& schema, const Aws::String& value) override; + void WriteTimestamp(const Schema& schema, const Aws::Utils::DateTime& value) override; + void WriteEnum(const Schema& schema, int value) override; + + private: + void WriteAttr(const Schema& schema, const Aws::String& value); + Impl* m_outer; + }; + + // Wraps each list element in the resolved item element. + class ListItemSerializer final : public InterceptingSerializer { + public: + ListItemSerializer(Impl* outer, Aws::String itemName, Aws::String itemNamespace) + : m_outer(outer), m_itemName(std::move(itemName)), m_itemNamespace(std::move(itemNamespace)) {} + + protected: + ShapeSerializer& Before(const Schema& schema) override; + void After(const Schema& schema) override; + + private: + Impl* m_outer; + Aws::String m_itemName; + Aws::String m_itemNamespace; + }; + + // Writes each map entry as ..... + class XmlMapEntrySerializer final : public MapSerializer { + public: + XmlMapEntrySerializer(Impl* outer, Aws::String entryName, Aws::String keyName, Aws::String valueName) + : m_outer(outer), + m_entryName(std::move(entryName)), + m_keyName(std::move(keyName)), + m_valueName(std::move(valueName)) {} + void WriteEntry(const Aws::String& key, const std::function& value) override; + + private: + Impl* m_outer; + Aws::String m_entryName; + Aws::String m_keyName; + Aws::String m_valueName; + }; + + Impl() + : m_valueSerializer(this), + m_structElementSerializer(this), + m_structAttributeSerializer(this), + m_inlineAttributeSerializer(this) { + m_buf.reserve(8192); } - using SerializerOutcome = XmlShapeSerializer::SerializerOutcome; - SerializerOutcome GetPayload() { if (m_finalized || !m_errorMessage.empty()) { return Aws::Client::AWSError( @@ -226,171 +176,300 @@ class XmlShapeSerializer::Impl { return std::move(m_buf); } - private: - Aws::String m_buf; - int m_depth = 0; - bool m_finalized = false; - bool m_hasOpenTag = false; - Aws::String m_errorMessage; - Aws::Array m_tagStack{}; - Aws::Array m_listItemName{}; - Aws::Array m_isList{}; - Aws::Array m_isFlattened{}; - Aws::Array m_isMap{}; - Aws::Array m_mapInEntry{}; - Aws::Array m_isMapValueStruct{}; - Aws::Array m_mapEntryName{}; - Aws::Array m_mapKeyName{}; - Aws::Array m_mapValueName{}; - - void FlushOpenTag() { - if (m_hasOpenTag) { - m_buf += '>'; - m_hasOpenTag = false; + // Guards against unbounded nesting. Returns false (and records an error) once + // the depth limit is reached, so the container body is skipped. + bool EnterContainer() { + if (!m_errorMessage.empty()) { + return false; + } + if (m_depth + 1 > MAX_DEPTH) { + m_errorMessage = "Maximum serialization depth exceeded"; + return false; } + ++m_depth; + return true; } + void ExitContainer() { --m_depth; } - void OpenTag(const Aws::String& name) { - FlushOpenTag(); + // Tag primitives. + void ClosePendingTag() { + if (m_pendingClose) { + m_buf += '>'; + m_pendingClose = false; + } + } + void WriteStartOpen(const Aws::String& name, const Aws::String& ns) { + m_buf += '<'; + m_buf += name; + m_buf += ns; + m_pendingClose = true; + } + void WriteFullOpenTag(const Aws::String& name) { m_buf += '<'; m_buf += name; m_buf += '>'; } - - void CloseTag(const Aws::String& name) { + void WriteCloseTag(const Aws::String& name) { m_buf += "'; } + void AppendRaw(const Aws::String& text) { m_buf += text; } + void AppendEscaped(const Aws::String& text) { AppendXmlEscaped(m_buf, text); } - void WrapValue(const Aws::String& tag, const Aws::String& value) { - if (m_depth > 0 && m_isMap[m_depth] && m_mapInEntry[m_depth]) { - OpenTag(m_mapValueName[m_depth]); - m_buf += value; - CloseTag(m_mapValueName[m_depth]); - CloseTag(m_mapEntryName[m_depth]); - m_mapInEntry[m_depth] = false; - } else if (m_depth > 0 && m_isList[m_depth]) { - const auto& itemName = m_listItemName[m_depth]; - OpenTag(itemName); - m_buf += value; - CloseTag(itemName); - } else { - OpenTag(tag); - m_buf += value; - CloseTag(tag); + // Trait-resolved shape metadata. + static Aws::String GetXmlName(const Schema& schema) { + const auto trait = schema.GetTrait(XmlNameTrait::KEY()); + if (trait) { + return trait->GetValue(); } + return schema.GetMemberName(); } - - void WrapEscapedValue(const Aws::String& tag, const Aws::String& value) { - if (m_depth > 0 && m_isMap[m_depth] && m_mapInEntry[m_depth]) { - OpenTag(m_mapValueName[m_depth]); - WriteXmlEscaped(m_buf, value); - CloseTag(m_mapValueName[m_depth]); - CloseTag(m_mapEntryName[m_depth]); - m_mapInEntry[m_depth] = false; - } else if (m_depth > 0 && m_isList[m_depth]) { - const auto& itemName = m_listItemName[m_depth]; - OpenTag(itemName); - WriteXmlEscaped(m_buf, value); - CloseTag(itemName); - } else { - OpenTag(tag); - WriteXmlEscaped(m_buf, value); - CloseTag(tag); + static Aws::String ResolveTopLevelName(const Schema& schema) { + const auto trait = schema.GetTrait(XmlNameTrait::KEY()); + if (trait) { + return trait->GetValue(); } - } - - Aws::String GetEffectiveTag(const Schema& schema) const { - if (m_depth > 0 && m_isList[m_depth]) { - return m_listItemName[m_depth]; + const auto member = schema.GetMemberName(); + if (!member.empty()) { + return member; } - return GetXmlName(schema); + return schema.GetId() ? Aws::String(schema.GetId()) : Aws::String(); } - - static void WriteXmlEscaped(Aws::String& buf, const Aws::String& value) { - const char* data = value.data(); - const size_t len = value.size(); - size_t i = 0; - while (i < len) { - size_t start = i; - while (i < len && data[i] != '&' && data[i] != '<' && data[i] != '>' && data[i] != '"' && data[i] != '\'') { - i++; - } - if (i > start) { - buf.append(data + start, i - start); - } - if (i < len) { - switch (data[i]) { - case '&': - buf += "&"; - break; - case '<': - buf += "<"; - break; - case '>': - buf += ">"; - break; - case '"': - buf += """; - break; - case '\'': - buf += "'"; - break; - } - i++; - } + static Aws::String ResolveNamespace(const Schema& schema) { + const auto ns = schema.GetTrait(XmlNamespaceTrait::KEY()); + if (!ns || ns->GetUri().empty()) { + return {}; } - } - - static Aws::String GetXmlName(const Schema& schema) { - const auto trait = schema.GetTrait(XmlNameTrait::KEY()); - if (trait) { - return trait->GetValue(); + Aws::String escapedUri; + AppendXmlEscaped(escapedUri, ns->GetUri()); + Aws::String result; + if (ns->GetPrefix().empty()) { + result += " xmlns=\""; + } else { + result += " xmlns:"; + result += ns->GetPrefix(); + result += "=\""; } - return schema.GetMemberName(); + result += escapedUri; + result += '"'; + return result; } - static bool IsFlattened(const Schema& schema) { return schema.HasTrait(XmlFlattenedTrait::KEY()); } - + static bool IsAttribute(const Schema& schema) { return schema.HasTrait(XmlAttributeTrait::KEY()); } static Aws::String GetListItemName(const Schema& schema) { const auto trait = schema.GetTrait(XmlListItemNameTrait::KEY()); - if (trait) { - return trait->GetValue(); - } - return "member"; + return trait ? trait->GetValue() : Aws::String("member"); } - static Aws::String GetMapEntryName(const Schema& schema) { const auto trait = schema.GetTrait(XmlMapEntryNameTrait::KEY()); - if (trait) { - return trait->GetValue(); - } - return "entry"; + return trait ? trait->GetValue() : Aws::String("entry"); } - static Aws::String GetMapKeyName(const Schema& schema) { const auto trait = schema.GetTrait(XmlMapKeyNameTrait::KEY()); - if (trait) { - return trait->GetValue(); - } - return "key"; + return trait ? trait->GetValue() : Aws::String("key"); } - static Aws::String GetMapValueName(const Schema& schema) { const auto trait = schema.GetTrait(XmlMapValueNameTrait::KEY()); - if (trait) { - return trait->GetValue(); - } - return "value"; + return trait ? trait->GetValue() : Aws::String("value"); + } + ValueSerializer& Value() { return m_valueSerializer; } + StructElementSerializer& StructElement() { return m_structElementSerializer; } + StructAttributeSerializer& StructAttribute() { return m_structAttributeSerializer; } + InlineAttributeSerializer& InlineAttribute() { return m_inlineAttributeSerializer; } + SpecificShapeSerializer& Null() { return m_nullSerializer; } + + protected: + ShapeSerializer& Before(const Schema& schema) override { + WriteStartOpen(ResolveTopLevelName(schema), ResolveNamespace(schema)); + return m_valueSerializer; } + void After(const Schema& schema) override { WriteCloseTag(ResolveTopLevelName(schema)); } + + private: + Aws::String m_buf; + int m_depth = 0; + bool m_pendingClose = false; + bool m_finalized = false; + Aws::String m_errorMessage; + ValueSerializer m_valueSerializer; + StructElementSerializer m_structElementSerializer; + StructAttributeSerializer m_structAttributeSerializer; + InlineAttributeSerializer m_inlineAttributeSerializer; + SpecificShapeSerializer m_nullSerializer; }; +// --- ValueSerializer --- + +void XmlShapeSerializer::Impl::ValueSerializer::WriteStruct(const Schema&, const SerializableStruct& value) { + if (!m_outer->EnterContainer()) { + return; + } + // Attribute pass: attribute members write into the still-open start tag; every + // other member routes to the null serializer and produces nothing. Running it + // unconditionally is output-identical to gating on "has attributes" and does + // not depend on the members being declared on the struct's own schema. + value.SerializeMembers(m_outer->StructAttribute()); + m_outer->ClosePendingTag(); + value.SerializeMembers(m_outer->StructElement()); + m_outer->ExitContainer(); +} + +void XmlShapeSerializer::Impl::ValueSerializer::WriteList(const Schema& schema, size_t, + const std::function& consumer) { + if (!m_outer->EnterContainer()) { + return; + } + m_outer->ClosePendingTag(); + const Aws::String itemName = Impl::IsFlattened(schema) ? Impl::GetXmlName(schema) : Impl::GetListItemName(schema); + ListItemSerializer itemSerializer(m_outer, itemName, Aws::String()); + consumer(itemSerializer); + m_outer->ExitContainer(); +} + +void XmlShapeSerializer::Impl::ValueSerializer::WriteMap(const Schema& schema, size_t, + const std::function& consumer) { + if (!m_outer->EnterContainer()) { + return; + } + m_outer->ClosePendingTag(); + const Aws::String entryName = Impl::IsFlattened(schema) ? Impl::GetXmlName(schema) : Impl::GetMapEntryName(schema); + XmlMapEntrySerializer entrySerializer(m_outer, entryName, Impl::GetMapKeyName(schema), Impl::GetMapValueName(schema)); + consumer(entrySerializer); + m_outer->ExitContainer(); +} + +void XmlShapeSerializer::Impl::ValueSerializer::WriteBoolean(const Schema&, bool value) { + m_outer->ClosePendingTag(); + m_outer->AppendRaw(value ? "true" : "false"); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteInteger(const Schema&, int value) { + m_outer->ClosePendingTag(); + m_outer->AppendRaw(StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteLong(const Schema&, int64_t value) { + m_outer->ClosePendingTag(); + m_outer->AppendRaw(StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteFloat(const Schema&, float value) { + m_outer->ClosePendingTag(); + m_outer->AppendRaw(StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteDouble(const Schema&, double value) { + m_outer->ClosePendingTag(); + m_outer->AppendRaw(StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteString(const Schema&, const Aws::String& value) { + m_outer->ClosePendingTag(); + m_outer->AppendEscaped(value); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteTimestamp(const Schema&, const Aws::Utils::DateTime& value) { + m_outer->ClosePendingTag(); + m_outer->AppendRaw(value.ToGmtString(Aws::Utils::DateFormat::ISO_8601)); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteBlob(const Schema&, const Aws::Utils::ByteBuffer& value) { + m_outer->ClosePendingTag(); + m_outer->AppendRaw(HashingUtils::Base64Encode(value)); +} +void XmlShapeSerializer::Impl::ValueSerializer::WriteEnum(const Schema& schema, int value) { WriteInteger(schema, value); } +void XmlShapeSerializer::Impl::ValueSerializer::WriteNull(const Schema&) { m_outer->ClosePendingTag(); } + +// --- StructElementSerializer --- + +ShapeSerializer& XmlShapeSerializer::Impl::StructElementSerializer::Before(const Schema& schema) { + if (Impl::IsAttribute(schema)) { + return m_outer->Null(); + } + if (Impl::IsFlattened(schema)) { + return m_outer->Value(); + } + m_outer->WriteStartOpen(Impl::GetXmlName(schema), Impl::ResolveNamespace(schema)); + return m_outer->Value(); +} + +void XmlShapeSerializer::Impl::StructElementSerializer::After(const Schema& schema) { + if (Impl::IsAttribute(schema) || Impl::IsFlattened(schema)) { + return; + } + m_outer->WriteCloseTag(Impl::GetXmlName(schema)); +} + +// --- StructAttributeSerializer --- + +ShapeSerializer& XmlShapeSerializer::Impl::StructAttributeSerializer::Before(const Schema& schema) { + if (Impl::IsAttribute(schema)) { + return m_outer->InlineAttribute(); + } + return m_outer->Null(); +} + +// --- InlineAttributeSerializer --- + +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteAttr(const Schema& schema, const Aws::String& value) { + m_outer->AppendRaw(" "); + m_outer->AppendRaw(Impl::GetXmlName(schema)); + m_outer->AppendRaw("=\""); + m_outer->AppendEscaped(value); + m_outer->AppendRaw("\""); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteBoolean(const Schema& schema, bool value) { + WriteAttr(schema, value ? "true" : "false"); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteInteger(const Schema& schema, int value) { + WriteAttr(schema, StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteLong(const Schema& schema, int64_t value) { + WriteAttr(schema, StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteFloat(const Schema& schema, float value) { + WriteAttr(schema, StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteDouble(const Schema& schema, double value) { + WriteAttr(schema, StringUtils::to_string(value)); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteString(const Schema& schema, const Aws::String& value) { + WriteAttr(schema, value); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteTimestamp(const Schema& schema, + const Aws::Utils::DateTime& value) { + WriteAttr(schema, value.ToGmtString(Aws::Utils::DateFormat::ISO_8601)); +} +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteEnum(const Schema& schema, int value) { + WriteAttr(schema, StringUtils::to_string(value)); +} + +// --- ListItemSerializer --- + +ShapeSerializer& XmlShapeSerializer::Impl::ListItemSerializer::Before(const Schema&) { + m_outer->WriteStartOpen(m_itemName, m_itemNamespace); + return m_outer->Value(); +} +void XmlShapeSerializer::Impl::ListItemSerializer::After(const Schema&) { m_outer->WriteCloseTag(m_itemName); } + +// --- XmlMapEntrySerializer --- + +void XmlShapeSerializer::Impl::XmlMapEntrySerializer::WriteEntry(const Aws::String& key, + const std::function& value) { + m_outer->WriteFullOpenTag(m_entryName); + m_outer->WriteFullOpenTag(m_keyName); + m_outer->AppendEscaped(key); + m_outer->WriteCloseTag(m_keyName); + m_outer->WriteStartOpen(m_valueName, Aws::String()); + value(m_outer->Value()); + m_outer->WriteCloseTag(m_valueName); + m_outer->WriteCloseTag(m_entryName); +} + XmlShapeSerializer::XmlShapeSerializer() : m_impl(Aws::MakeUnique("XmlShapeSerializer")) {} XmlShapeSerializer::~XmlShapeSerializer() = default; -bool XmlShapeSerializer::BeginStructure(const Schema& schema) { return m_impl->BeginStructure(schema); } -void XmlShapeSerializer::EndStructure() { m_impl->EndStructure(); } +void XmlShapeSerializer::WriteStruct(const Schema& schema, const SerializableStruct& value) { m_impl->WriteStruct(schema, value); } +void XmlShapeSerializer::WriteList(const Schema& schema, size_t size, const std::function& consumer) { + m_impl->WriteList(schema, size, consumer); +} +void XmlShapeSerializer::WriteMap(const Schema& schema, size_t size, const std::function& consumer) { + m_impl->WriteMap(schema, size, consumer); +} void XmlShapeSerializer::WriteBoolean(const Schema& schema, bool value) { m_impl->WriteBoolean(schema, value); } void XmlShapeSerializer::WriteInteger(const Schema& schema, int value) { m_impl->WriteInteger(schema, value); } void XmlShapeSerializer::WriteLong(const Schema& schema, int64_t value) { m_impl->WriteLong(schema, value); } @@ -401,12 +480,5 @@ void XmlShapeSerializer::WriteTimestamp(const Schema& schema, const DateTime& va void XmlShapeSerializer::WriteBlob(const Schema& schema, const ByteBuffer& value) { m_impl->WriteBlob(schema, value); } void XmlShapeSerializer::WriteEnum(const Schema& schema, int value) { m_impl->WriteEnum(schema, value); } void XmlShapeSerializer::WriteNull(const Schema& schema) { m_impl->WriteNull(schema); } -bool XmlShapeSerializer::BeginList(const Schema& schema, size_t count) { return m_impl->BeginList(schema, count); } -void XmlShapeSerializer::EndList() { m_impl->EndList(); } -bool XmlShapeSerializer::BeginMap(const Schema& schema, size_t count) { return m_impl->BeginMap(schema, count); } -void XmlShapeSerializer::WriteMapKey(const Aws::String& key) { m_impl->WriteMapKey(key); } -void XmlShapeSerializer::EndMap() { m_impl->EndMap(); } -bool XmlShapeSerializer::BeginNestedStructure(const Schema& schema) { return m_impl->BeginNestedStructure(schema); } -void XmlShapeSerializer::EndNestedStructure() { m_impl->EndNestedStructure(); } + XmlShapeSerializer::SerializerOutcome XmlShapeSerializer::GetPayload() { return m_impl->GetPayload(); } -void XmlShapeSerializer::WriteAttribute(const Schema& schema, const Aws::String& value) { m_impl->WriteAttribute(schema, value); } diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp index cdd1a391eb4e..66a985d501f7 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp @@ -6,9 +6,14 @@ #include #include #include +#include #include #include +#include + +#include "SchemaSerializerTestHelpers.h" + using namespace smithy::schema; class CborShapeDeserializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; @@ -18,10 +23,9 @@ class CborShapeDeserializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; TEST_F(CborShapeDeserializerTest, BooleanTrue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("enabled"); - s.WriteBoolean(*root, true); - s.EndStructure(); + auto member = Schema::CreateMember("enabled", ShapeType::Boolean); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, true); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -40,10 +44,9 @@ TEST_F(CborShapeDeserializerTest, BooleanTrue) { TEST_F(CborShapeDeserializerTest, BooleanFalse) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("ok"); - s.WriteBoolean(*root, false); - s.EndStructure(); + auto member = Schema::CreateMember("ok", ShapeType::Boolean); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, false); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -61,10 +64,9 @@ TEST_F(CborShapeDeserializerTest, BooleanFalse) { TEST_F(CborShapeDeserializerTest, IntegerSmall) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*root, 7); - s.EndStructure(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 7); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -82,10 +84,9 @@ TEST_F(CborShapeDeserializerTest, IntegerSmall) { TEST_F(CborShapeDeserializerTest, IntegerNegative) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*root, -42); - s.EndStructure(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, -42); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -103,10 +104,9 @@ TEST_F(CborShapeDeserializerTest, IntegerNegative) { TEST_F(CborShapeDeserializerTest, LongValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("big"); - s.WriteLong(*root, 5000000000LL); - s.EndStructure(); + auto member = Schema::CreateMember("big", ShapeType::Long); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteLong(*member, 5000000000LL); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -124,10 +124,9 @@ TEST_F(CborShapeDeserializerTest, LongValue) { TEST_F(CborShapeDeserializerTest, DoubleValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("d"); - s.WriteDouble(*root, 3.14); - s.EndStructure(); + auto member = Schema::CreateMember("d", ShapeType::Double); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteDouble(*member, 3.14); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -146,10 +145,9 @@ TEST_F(CborShapeDeserializerTest, DoubleWholeNumber) { // CRT encodes 5.0 as integer 5 — deserializer must handle this CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("d"); - s.WriteDouble(*root, 5.0); - s.EndStructure(); + auto member = Schema::CreateMember("d", ShapeType::Double); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteDouble(*member, 5.0); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -167,10 +165,9 @@ TEST_F(CborShapeDeserializerTest, DoubleWholeNumber) { TEST_F(CborShapeDeserializerTest, FloatValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("f"); - s.WriteFloat(*root, 1.5f); - s.EndStructure(); + auto member = Schema::CreateMember("f", ShapeType::Float); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteFloat(*member, 1.5f); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -188,10 +185,9 @@ TEST_F(CborShapeDeserializerTest, FloatValue) { TEST_F(CborShapeDeserializerTest, StringValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("name"); - s.WriteString(*root, "hello"); - s.EndStructure(); + auto member = Schema::CreateMember("name", ShapeType::String); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -214,10 +210,9 @@ TEST_F(CborShapeDeserializerTest, BlobValue) { blob[1] = 0xAD; blob[2] = 0xBE; blob[3] = 0xEF; - s.BeginStructure(*root); - s.WriteMapKey("data"); - s.WriteBlob(*root, blob); - s.EndStructure(); + auto member = Schema::CreateMember("data", ShapeType::Blob); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBlob(*member, blob); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -240,10 +235,9 @@ TEST_F(CborShapeDeserializerTest, TimestampValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); Aws::Utils::DateTime dt(1234567890.0); // seconds since epoch - s.BeginStructure(*root); - s.WriteMapKey("ts"); - s.WriteTimestamp(*root, dt); - s.EndStructure(); + auto member = Schema::CreateMember("ts", ShapeType::Timestamp); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteTimestamp(*member, dt); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -261,10 +255,9 @@ TEST_F(CborShapeDeserializerTest, TimestampValue) { TEST_F(CborShapeDeserializerTest, NullValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("item"); - s.WriteNull(*root); - s.EndStructure(); + auto member = Schema::CreateMember("item", ShapeType::String); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteNull(*member); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -283,14 +276,16 @@ TEST_F(CborShapeDeserializerTest, NullValue) { TEST_F(CborShapeDeserializerTest, ListOfIntegers) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("nums"); - s.BeginList(*root, 3); - s.WriteInteger(*root, 10); - s.WriteInteger(*root, 20); - s.WriteInteger(*root, 30); - s.EndList(); - s.EndStructure(); + auto listMember = Schema::CreateMember("nums", ShapeType::List); + auto elem = Schema::CreateMember("member", ShapeType::Integer); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteInteger(*elem, 10); + lser.WriteInteger(*elem, 20); + lser.WriteInteger(*elem, 30); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -317,15 +312,15 @@ TEST_F(CborShapeDeserializerTest, ListOfIntegers) { TEST_F(CborShapeDeserializerTest, MapOfStrings) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("headers"); - s.BeginMap(*root, 2); - s.WriteMapKey("foo"); - s.WriteString(*root, "bar"); - s.WriteMapKey("baz"); - s.WriteString(*root, "qux"); - s.EndMap(); - s.EndStructure(); + auto mapMember = Schema::CreateMember("headers", ShapeType::Map); + auto valSchema = Schema::CreateMember("value", ShapeType::String); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 2, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("foo", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "bar"); }); + mapSer.WriteEntry("baz", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "qux"); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -355,13 +350,12 @@ TEST_F(CborShapeDeserializerTest, MapOfStrings) { TEST_F(CborShapeDeserializerTest, NestedStructure) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("meta"); - s.BeginNestedStructure(*root); - s.WriteMapKey("key"); - s.WriteString(*root, "val"); - s.EndNestedStructure(); - s.EndStructure(); + auto nested = Schema::CreateMember("meta", ShapeType::Structure); + auto inner = Schema::CreateMember("key", ShapeType::String); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*nested, LambdaStruct(*nested, [&](ShapeSerializer& ser2) { ser2.WriteString(*inner, "val"); })); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -387,14 +381,15 @@ TEST_F(CborShapeDeserializerTest, NestedStructure) { TEST_F(CborShapeDeserializerTest, SkipUnknownField) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("known"); - s.WriteInteger(*root, 1); - s.WriteMapKey("unknown"); - s.WriteString(*root, "skip me"); - s.WriteMapKey("also_known"); - s.WriteInteger(*root, 2); - s.EndStructure(); + auto known = Schema::CreateMember("known", ShapeType::Integer); + auto unknown = Schema::CreateMember("unknown", ShapeType::String); + auto alsoKnown = Schema::CreateMember("also_known", ShapeType::Integer); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteInteger(*known, 1); + ser.WriteString(*unknown, "skip me"); + ser.WriteInteger(*alsoKnown, 2); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -422,17 +417,18 @@ TEST_F(CborShapeDeserializerTest, SkipUnknownField) { TEST_F(CborShapeDeserializerTest, SkipNestedUnknown) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("unknown_struct"); - s.BeginNestedStructure(*root); - s.WriteMapKey("a"); - s.WriteInteger(*root, 1); - s.WriteMapKey("b"); - s.WriteString(*root, "nested"); - s.EndNestedStructure(); - s.WriteMapKey("known"); - s.WriteInteger(*root, 42); - s.EndStructure(); + auto unknownStruct = Schema::CreateMember("unknown_struct", ShapeType::Structure); + auto a = Schema::CreateMember("a", ShapeType::Integer); + auto b = Schema::CreateMember("b", ShapeType::String); + auto known = Schema::CreateMember("known", ShapeType::Integer); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*unknownStruct, LambdaStruct(*unknownStruct, [&](ShapeSerializer& ser2) { + ser2.WriteInteger(*a, 1); + ser2.WriteString(*b, "nested"); + })); + ser.WriteInteger(*known, 42); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -456,14 +452,15 @@ TEST_F(CborShapeDeserializerTest, SkipNestedUnknown) { TEST_F(CborShapeDeserializerTest, MultipleScalars) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("a"); - s.WriteBoolean(*root, true); - s.WriteMapKey("b"); - s.WriteInteger(*root, 7); - s.WriteMapKey("c"); - s.WriteString(*root, "x"); - s.EndStructure(); + auto m1 = Schema::CreateMember("a", ShapeType::Boolean); + auto m2 = Schema::CreateMember("b", ShapeType::Integer); + auto m3 = Schema::CreateMember("c", ShapeType::String); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteBoolean(*m1, true); + ser.WriteInteger(*m2, 7); + ser.WriteString(*m3, "x"); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -502,10 +499,9 @@ TEST_F(CborShapeDeserializerTest, EmptyOptionalOnEmptyPayload) { TEST_F(CborShapeDeserializerTest, EmptyOptionalOnTypeMismatch) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("val"); - s.WriteString(*root, "hello"); - s.EndStructure(); + auto member = Schema::CreateMember("val", ShapeType::String); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -520,10 +516,9 @@ TEST_F(CborShapeDeserializerTest, EmptyOptionalOnTypeMismatch) { TEST_F(CborShapeDeserializerTest, ValidOptionalOnSuccess) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*root, 42); - s.EndStructure(); + auto member = Schema::CreateMember("n", ShapeType::Integer); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 42); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); @@ -567,10 +562,9 @@ TEST_F(CborShapeDeserializerTest, BeginStructDefiniteLengthMap) { TEST_F(CborShapeDeserializerTest, BeginStructIndefiniteLengthMap) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.WriteMapKey("x"); - s.WriteInteger(*root, 99); - s.EndStructure(); + auto member = Schema::CreateMember("x", ShapeType::Integer); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 99); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); CborShapeDeserializer d(reinterpret_cast(payload.data()), payload.size()); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp index bbf6d0fd2591..95a0b530da80 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp @@ -5,10 +5,14 @@ #include #include #include +#include #include #include #include +#include + +#include "SchemaSerializerTestHelpers.h" using namespace smithy::schema; @@ -23,8 +27,8 @@ Aws::String Bytes(const char* data, size_t len) { return Aws::String(data, len); TEST_F(CborShapeSerializerTest, EmptyStructure) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.EndStructure(); + LambdaStruct rootStruct(*root, [](ShapeSerializer&) {}); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); // indefinite map start + break @@ -35,10 +39,8 @@ TEST_F(CborShapeSerializerTest, BooleanTrue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("enabled", ShapeType::Boolean); - s.BeginStructure(*root); - s.WriteMapKey("enabled"); - s.WriteBoolean(*member, true); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, true); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -57,10 +59,8 @@ TEST_F(CborShapeSerializerTest, BooleanFalse) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("ok", ShapeType::Boolean); - s.BeginStructure(*root); - s.WriteMapKey("ok"); - s.WriteBoolean(*member, false); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, false); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -77,10 +77,8 @@ TEST_F(CborShapeSerializerTest, IntegerSmall) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*member, 1); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 1); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -97,10 +95,8 @@ TEST_F(CborShapeSerializerTest, IntegerOneByte) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*member, 42); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 42); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -118,10 +114,8 @@ TEST_F(CborShapeSerializerTest, IntegerNegative) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*member, -1); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, -1); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -138,10 +132,8 @@ TEST_F(CborShapeSerializerTest, IntegerNegativeLarge) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*member, -100); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, -100); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -159,10 +151,8 @@ TEST_F(CborShapeSerializerTest, LongValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("big", ShapeType::Long); - s.BeginStructure(*root); - s.WriteMapKey("big"); - s.WriteLong(*member, 1000000LL); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteLong(*member, 1000000LL); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -184,10 +174,8 @@ TEST_F(CborShapeSerializerTest, DoubleValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("d", ShapeType::Double); - s.BeginStructure(*root); - s.WriteMapKey("d"); - s.WriteDouble(*member, 3.14); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteDouble(*member, 3.14); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -214,10 +202,8 @@ TEST_F(CborShapeSerializerTest, StringValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("name", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("name"); - s.WriteString(*member, "hello"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -235,10 +221,8 @@ TEST_F(CborShapeSerializerTest, EmptyString) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("s", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("s"); - s.WriteString(*member, ""); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, ""); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -255,12 +239,10 @@ TEST_F(CborShapeSerializerTest, BlobValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("data", ShapeType::Blob); - s.BeginStructure(*root); - s.WriteMapKey("data"); unsigned char raw[] = {0xDE, 0xAD, 0xBE, 0xEF}; Aws::Utils::ByteBuffer buf(raw, 4); - s.WriteBlob(*member, buf); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBlob(*member, buf); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -281,10 +263,8 @@ TEST_F(CborShapeSerializerTest, NullValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("item", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("item"); - s.WriteNull(*member); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteNull(*member); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -301,12 +281,10 @@ TEST_F(CborShapeSerializerTest, TimestampIntegerSeconds) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("ts", ShapeType::Timestamp); - s.BeginStructure(*root); - s.WriteMapKey("ts"); // DateTime(int64_t) takes milliseconds; 1234567000ms = 1234567 seconds (no fractional part) Aws::Utils::DateTime dt(static_cast(1234567000)); - s.WriteTimestamp(*member, dt); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteTimestamp(*member, dt); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -330,11 +308,9 @@ TEST_F(CborShapeSerializerTest, TimestampFractionalSeconds) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("ts", ShapeType::Timestamp); - s.BeginStructure(*root); - s.WriteMapKey("ts"); Aws::Utils::DateTime dt(1234567890.5); - s.WriteTimestamp(*member, dt); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteTimestamp(*member, dt); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -357,14 +333,12 @@ TEST_F(CborShapeSerializerTest, MultipleScalars) { auto m1 = Schema::CreateMember("a", ShapeType::Boolean); auto m2 = Schema::CreateMember("b", ShapeType::Integer); auto m3 = Schema::CreateMember("c", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("a"); - s.WriteBoolean(*m1, true); - s.WriteMapKey("b"); - s.WriteInteger(*m2, 7); - s.WriteMapKey("c"); - s.WriteString(*m3, "x"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteBoolean(*m1, true); + ser.WriteInteger(*m2, 7); + ser.WriteString(*m3, "x"); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -391,13 +365,10 @@ TEST_F(CborShapeSerializerTest, NestedStructure) { auto root = Schema::StructureBuilder("Root").Build(); auto nested = Schema::CreateMember("meta", ShapeType::Structure); auto inner = Schema::CreateMember("key", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("meta"); - s.BeginNestedStructure(*nested); - s.WriteMapKey("key"); - s.WriteString(*inner, "val"); - s.EndNestedStructure(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*nested, LambdaStruct(*nested, [&](ShapeSerializer& ser2) { ser2.WriteString(*inner, "val"); })); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -421,16 +392,12 @@ TEST_F(CborShapeSerializerTest, DeeplyNestedStructure) { auto l1 = Schema::CreateMember("l1", ShapeType::Structure); auto l2 = Schema::CreateMember("l2", ShapeType::Structure); auto leaf = Schema::CreateMember("v", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("l1"); - s.BeginNestedStructure(*l1); - s.WriteMapKey("l2"); - s.BeginNestedStructure(*l2); - s.WriteMapKey("v"); - s.WriteInteger(*leaf, 99); - s.EndNestedStructure(); - s.EndNestedStructure(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*l1, LambdaStruct(*l1, [&](ShapeSerializer& ser2) { + ser2.WriteStruct(*l2, LambdaStruct(*l2, [&](ShapeSerializer& ser3) { ser3.WriteInteger(*leaf, 99); })); + })); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -459,14 +426,14 @@ TEST_F(CborShapeSerializerTest, ListOfIntegers) { auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("nums", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("nums"); - s.BeginList(*listMember, 3); - s.WriteInteger(*elem, 1); - s.WriteInteger(*elem, 2); - s.WriteInteger(*elem, 3); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteInteger(*elem, 1); + lser.WriteInteger(*elem, 2); + lser.WriteInteger(*elem, 3); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -486,11 +453,8 @@ TEST_F(CborShapeSerializerTest, EmptyList) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("items", ShapeType::List); - s.BeginStructure(*root); - s.WriteMapKey("items"); - s.BeginList(*listMember, 0); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteList(*listMember, 0, [](ShapeSerializer&) {}); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -508,13 +472,13 @@ TEST_F(CborShapeSerializerTest, ListOfStrings) { auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("tags", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("tags"); - s.BeginList(*listMember, 2); - s.WriteString(*elem, "ab"); - s.WriteString(*elem, "cd"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "ab"); + lser.WriteString(*elem, "cd"); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -537,19 +501,13 @@ TEST_F(CborShapeSerializerTest, ListOfStructures) { auto listMember = Schema::CreateMember("items", ShapeType::List); auto structElem = Schema::CreateMember("member", ShapeType::Structure); auto field = Schema::CreateMember("id", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("items"); - s.BeginList(*listMember, 2); - s.BeginNestedStructure(*structElem); - s.WriteMapKey("id"); - s.WriteInteger(*field, 1); - s.EndNestedStructure(); - s.BeginNestedStructure(*structElem); - s.WriteMapKey("id"); - s.WriteInteger(*field, 2); - s.EndNestedStructure(); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteStruct(*structElem, LambdaStruct(*structElem, [&](ShapeSerializer& es) { es.WriteInteger(*field, 1); })); + lser.WriteStruct(*structElem, LambdaStruct(*structElem, [&](ShapeSerializer& es) { es.WriteInteger(*field, 2); })); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -579,15 +537,13 @@ TEST_F(CborShapeSerializerTest, MapOfStrings) { auto root = Schema::StructureBuilder("Root").Build(); auto mapMember = Schema::CreateMember("headers", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("headers"); - s.BeginMap(*mapMember, 2); - s.WriteMapKey("foo"); - s.WriteString(*valSchema, "bar"); - s.WriteMapKey("baz"); - s.WriteString(*valSchema, "qux"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 2, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("foo", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "bar"); }); + mapSer.WriteEntry("baz", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "qux"); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -612,11 +568,8 @@ TEST_F(CborShapeSerializerTest, EmptyMap) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto mapMember = Schema::CreateMember("tags", ShapeType::Map); - s.BeginStructure(*root); - s.WriteMapKey("tags"); - s.BeginMap(*mapMember, 0); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteMap(*mapMember, 0, [](MapSerializer&) {}); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -635,16 +588,14 @@ TEST_F(CborShapeSerializerTest, MapOfStructures) { auto mapMember = Schema::CreateMember("nodes", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::Structure); auto field = Schema::CreateMember("val", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("nodes"); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("a"); - s.BeginNestedStructure(*valSchema); - s.WriteMapKey("val"); - s.WriteInteger(*field, 1); - s.EndNestedStructure(); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("a", [&](ShapeSerializer& vser) { + vser.WriteStruct(*valSchema, LambdaStruct(*valSchema, [&](ShapeSerializer& vs) { vs.WriteInteger(*field, 1); })); + }); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -671,8 +622,8 @@ TEST_F(CborShapeSerializerTest, MapOfStructures) { TEST_F(CborShapeSerializerTest, GetPayloadCalledTwice) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.EndStructure(); + LambdaStruct rootStruct(*root, [](ShapeSerializer&) {}); + s.WriteStruct(*root, rootStruct); auto outcome1 = s.GetPayload(); ASSERT_TRUE(outcome1.IsSuccess()); auto outcome2 = s.GetPayload(); @@ -686,10 +637,8 @@ TEST_F(CborShapeSerializerTest, EnumValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("status", ShapeType::Enum); - s.BeginStructure(*root); - s.WriteMapKey("status"); - s.WriteEnum(*member, 3); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteEnum(*member, 3); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -713,19 +662,14 @@ TEST_F(CborShapeSerializerTest, StructureWithListAndMap) { auto mapMember = Schema::CreateMember("meta", ShapeType::Map); auto mapVal = Schema::CreateMember("value", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("name"); - s.WriteString(*strMember, "hi"); - s.WriteMapKey("tags"); - s.BeginList(*listMember, 1); - s.WriteString(*listElem, "t1"); - s.EndList(); - s.WriteMapKey("meta"); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("k"); - s.WriteInteger(*mapVal, 5); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteString(*strMember, "hi"); + ser.WriteList(*listMember, 1, [&](ShapeSerializer& lser) { lser.WriteString(*listElem, "t1"); }); + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteInteger(*mapVal, 5); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); @@ -755,10 +699,8 @@ TEST_F(CborShapeSerializerTest, IntegerZero) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("z", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("z"); - s.WriteInteger(*member, 0); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 0); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -775,10 +717,8 @@ TEST_F(CborShapeSerializerTest, IntegerTwoByte) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*member, 1000); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 1000); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -799,14 +739,14 @@ TEST_F(CborShapeSerializerTest, SparseList) { auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("items", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("items"); - s.BeginList(*listMember, 3); - s.WriteString(*elem, "a"); - s.WriteNull(*elem); - s.WriteString(*elem, "b"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "a"); + lser.WriteNull(*elem); + lser.WriteString(*elem, "b"); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -830,10 +770,8 @@ TEST_F(CborShapeSerializerTest, IntegerFourByte) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteInteger(*member, 70000); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 70000); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -854,10 +792,8 @@ TEST_F(CborShapeSerializerTest, LongEightByte) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Long); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteLong(*member, 5000000000LL); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteLong(*member, 5000000000LL); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -882,10 +818,8 @@ TEST_F(CborShapeSerializerTest, LargeNegativeInteger) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("n", ShapeType::Long); - s.BeginStructure(*root); - s.WriteMapKey("n"); - s.WriteLong(*member, -1000000LL); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteLong(*member, -1000000LL); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -907,10 +841,8 @@ TEST_F(CborShapeSerializerTest, DoubleWholeNumberEncodedAsInt) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("d", ShapeType::Double); - s.BeginStructure(*root); - s.WriteMapKey("d"); - s.WriteDouble(*member, 5.0); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteDouble(*member, 5.0); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -929,10 +861,8 @@ TEST_F(CborShapeSerializerTest, DoubleNegativeWholeNumberEncodedAsNegInt) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("d", ShapeType::Double); - s.BeginStructure(*root); - s.WriteMapKey("d"); - s.WriteDouble(*member, -3.0); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteDouble(*member, -3.0); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -949,10 +879,8 @@ TEST_F(CborShapeSerializerTest, UnicodeString) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("s", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("s"); - s.WriteString(*member, "\xC3\xA9\xC3\xA8"); // "éè" in UTF-8 (4 bytes) - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "\xC3\xA9\xC3\xA8"); }); // "éè" in UTF-8 (4 bytes) + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -972,18 +900,16 @@ TEST_F(CborShapeSerializerTest, NestedListInList) { auto outerList = Schema::CreateMember("data", ShapeType::List); auto innerList = Schema::CreateMember("member", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("data"); - s.BeginList(*outerList, 2); - s.BeginList(*innerList, 2); - s.WriteInteger(*elem, 1); - s.WriteInteger(*elem, 2); - s.EndList(); - s.BeginList(*innerList, 1); - s.WriteInteger(*elem, 3); - s.EndList(); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*outerList, 2, [&](ShapeSerializer& lser) { + lser.WriteList(*innerList, 2, [&](ShapeSerializer& lser2) { + lser2.WriteInteger(*elem, 1); + lser2.WriteInteger(*elem, 2); + }); + lser.WriteList(*innerList, 1, [&](ShapeSerializer& lser2) { lser2.WriteInteger(*elem, 3); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -1006,17 +932,14 @@ TEST_F(CborShapeSerializerTest, MapWithMultipleEntries) { auto root = Schema::StructureBuilder("Root").Build(); auto mapMember = Schema::CreateMember("m", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteMapKey("m"); - s.BeginMap(*mapMember, 3); - s.WriteMapKey("x"); - s.WriteInteger(*valSchema, 1); - s.WriteMapKey("y"); - s.WriteInteger(*valSchema, 2); - s.WriteMapKey("z"); - s.WriteInteger(*valSchema, 3); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 3, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("x", [&](ShapeSerializer& vser) { vser.WriteInteger(*valSchema, 1); }); + mapSer.WriteEntry("y", [&](ShapeSerializer& vser) { vser.WriteInteger(*valSchema, 2); }); + mapSer.WriteEntry("z", [&](ShapeSerializer& vser) { vser.WriteInteger(*valSchema, 3); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -1042,10 +965,8 @@ TEST_F(CborShapeSerializerTest, FloatValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("f", ShapeType::Float); - s.BeginStructure(*root); - s.WriteMapKey("f"); - s.WriteFloat(*member, 1.5f); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteFloat(*member, 1.5f); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -1068,10 +989,8 @@ TEST_F(CborShapeSerializerTest, FloatWholeNumberEncodedAsInt) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("f", ShapeType::Float); - s.BeginStructure(*root); - s.WriteMapKey("f"); - s.WriteFloat(*member, 7.0f); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteFloat(*member, 7.0f); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -1088,11 +1007,9 @@ TEST_F(CborShapeSerializerTest, TimestampEpochZero) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("ts", ShapeType::Timestamp); - s.BeginStructure(*root); - s.WriteMapKey("ts"); Aws::Utils::DateTime dt(0.0); - s.WriteTimestamp(*member, dt); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteTimestamp(*member, dt); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -1111,14 +1028,12 @@ TEST_F(CborShapeSerializerTest, LargeBlob) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("b", ShapeType::Blob); - s.BeginStructure(*root); - s.WriteMapKey("b"); Aws::Utils::ByteBuffer blob(300); for (size_t i = 0; i < 300; i++) { blob[i] = static_cast(i % 256); } - s.WriteBlob(*member, blob); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBlob(*member, blob); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); @@ -1140,13 +1055,10 @@ TEST_F(CborShapeSerializerTest, UnionAsStructure) { auto root = Schema::StructureBuilder("Root").Build(); auto unionMember = Schema::CreateMember("result", ShapeType::Union); auto field = Schema::CreateMember("message", ShapeType::String); - s.BeginStructure(*root); - s.WriteMapKey("result"); - s.BeginNestedStructure(*unionMember); - s.WriteMapKey("message"); - s.WriteString(*field, "ok"); - s.EndNestedStructure(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*unionMember, LambdaStruct(*unionMember, [&](ShapeSerializer& ser2) { ser2.WriteString(*field, "ok"); })); + }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); const auto& payload = outcome.GetResult(); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp index 22876355adff..24394aa95d15 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp @@ -6,9 +6,14 @@ #include #include #include +#include #include #include +#include + +#include "SchemaSerializerTestHelpers.h" + using namespace smithy::schema; class JsonShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; @@ -18,8 +23,8 @@ class JsonShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; TEST_F(JsonShapeSerializerTest, EmptyStructure) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - s.BeginStructure(*root); - s.EndStructure(); + LambdaStruct rootStruct(*root, [](ShapeSerializer&) {}); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); EXPECT_EQ(outcome.GetResult(), "{}"); @@ -29,9 +34,8 @@ TEST_F(JsonShapeSerializerTest, BooleanTrue) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("enabled", ShapeType::Boolean); - s.BeginStructure(*root); - s.WriteBoolean(*member, true); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, true); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"enabled\":true"), Aws::String::npos); } @@ -39,9 +43,8 @@ TEST_F(JsonShapeSerializerTest, BooleanFalse) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("enabled", ShapeType::Boolean); - s.BeginStructure(*root); - s.WriteBoolean(*member, false); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, false); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"enabled\":false"), Aws::String::npos); } @@ -49,9 +52,8 @@ TEST_F(JsonShapeSerializerTest, Integer) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("count", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteInteger(*member, 42); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 42); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"count\":42"), Aws::String::npos); } @@ -59,9 +61,8 @@ TEST_F(JsonShapeSerializerTest, Long) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("bigNum", ShapeType::Long); - s.BeginStructure(*root); - s.WriteLong(*member, 9876543210LL); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteLong(*member, 9876543210LL); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"bigNum\":9876543210"), Aws::String::npos); } @@ -69,9 +70,8 @@ TEST_F(JsonShapeSerializerTest, Double) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("ratio", ShapeType::Double); - s.BeginStructure(*root); - s.WriteDouble(*member, 3.14); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteDouble(*member, 3.14); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"ratio\":3.14"), Aws::String::npos); } @@ -79,9 +79,8 @@ TEST_F(JsonShapeSerializerTest, String) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("name", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "hello"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"name\":\"hello\""), Aws::String::npos); } @@ -89,9 +88,8 @@ TEST_F(JsonShapeSerializerTest, EmptyString) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("name", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, ""); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, ""); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"name\":\"\""), Aws::String::npos); } @@ -99,10 +97,9 @@ TEST_F(JsonShapeSerializerTest, Timestamp) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("created", ShapeType::Timestamp); - s.BeginStructure(*root); Aws::Utils::DateTime dt(1234567890.0); - s.WriteTimestamp(*member, dt); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteTimestamp(*member, dt); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"created\":"), Aws::String::npos); } @@ -110,11 +107,10 @@ TEST_F(JsonShapeSerializerTest, Blob) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("data", ShapeType::Blob); - s.BeginStructure(*root); unsigned char raw[] = {0x66, 0x6f, 0x6f}; Aws::Utils::ByteBuffer buf(raw, 3); - s.WriteBlob(*member, buf); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBlob(*member, buf); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"data\":\"Zm9v\""), Aws::String::npos); } @@ -122,9 +118,8 @@ TEST_F(JsonShapeSerializerTest, NullValue) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("item", ShapeType::String); - s.BeginStructure(*root); - s.WriteNull(*member); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteNull(*member); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"item\":null"), Aws::String::npos); } @@ -134,11 +129,12 @@ TEST_F(JsonShapeSerializerTest, MultipleScalars) { auto m1 = Schema::CreateMember("a", ShapeType::Boolean); auto m2 = Schema::CreateMember("b", ShapeType::Integer); auto m3 = Schema::CreateMember("c", ShapeType::String); - s.BeginStructure(*root); - s.WriteBoolean(*m1, true); - s.WriteInteger(*m2, 7); - s.WriteString(*m3, "x"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteBoolean(*m1, true); + ser.WriteInteger(*m2, 7); + ser.WriteString(*m3, "x"); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("\"a\":true"), Aws::String::npos); EXPECT_NE(payload.find("\"b\":7"), Aws::String::npos); @@ -152,11 +148,10 @@ TEST_F(JsonShapeSerializerTest, NestedStructure) { auto root = Schema::StructureBuilder("Root").Build(); auto nested = Schema::CreateMember("metadata", ShapeType::Structure); auto inner = Schema::CreateMember("key", ShapeType::String); - s.BeginStructure(*root); - s.BeginNestedStructure(*nested); - s.WriteString(*inner, "val"); - s.EndNestedStructure(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*nested, LambdaStruct(*nested, [&](ShapeSerializer& ser2) { ser2.WriteString(*inner, "val"); })); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"metadata\":{\"key\":\"val\"}"), Aws::String::npos); } @@ -166,13 +161,14 @@ TEST_F(JsonShapeSerializerTest, DeeplyNestedStructure) { auto level1 = Schema::CreateMember("l1", ShapeType::Structure); auto level2 = Schema::CreateMember("l2", ShapeType::Structure); auto leaf = Schema::CreateMember("val", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginNestedStructure(*level1); - s.BeginNestedStructure(*level2); - s.WriteInteger(*leaf, 99); - s.EndNestedStructure(); - s.EndNestedStructure(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*level1, LambdaStruct(*level1, [&](ShapeSerializer& ser2) { + ser2.WriteStruct(*level2, LambdaStruct(*level2, [&](ShapeSerializer& ser3) { + ser3.WriteInteger(*leaf, 99); + })); + })); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"l1\":{\"l2\":{\"val\":99}}"), Aws::String::npos); } @@ -183,13 +179,14 @@ TEST_F(JsonShapeSerializerTest, ListOfStrings) { auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("tags", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.BeginList(*listMember, 3); - s.WriteString(*elem, "a"); - s.WriteString(*elem, "b"); - s.WriteString(*elem, "c"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "a"); + lser.WriteString(*elem, "b"); + lser.WriteString(*elem, "c"); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"tags\":[\"a\",\"b\",\"c\"]"), Aws::String::npos); } @@ -198,13 +195,14 @@ TEST_F(JsonShapeSerializerTest, ListOfIntegers) { auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("nums", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginList(*listMember, 3); - s.WriteInteger(*elem, 1); - s.WriteInteger(*elem, 2); - s.WriteInteger(*elem, 3); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteInteger(*elem, 1); + lser.WriteInteger(*elem, 2); + lser.WriteInteger(*elem, 3); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"nums\":[1,2,3]"), Aws::String::npos); } @@ -212,10 +210,8 @@ TEST_F(JsonShapeSerializerTest, EmptyList) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("items", ShapeType::List); - s.BeginStructure(*root); - s.BeginList(*listMember, 0); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteList(*listMember, 0, [](ShapeSerializer&) {}); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"items\":[]"), Aws::String::npos); } @@ -225,16 +221,13 @@ TEST_F(JsonShapeSerializerTest, ListOfStructures) { auto listMember = Schema::CreateMember("items", ShapeType::List); auto structElem = Schema::CreateMember("member", ShapeType::Structure); auto field = Schema::CreateMember("id", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginList(*listMember, 2); - s.BeginNestedStructure(*structElem); - s.WriteInteger(*field, 1); - s.EndNestedStructure(); - s.BeginNestedStructure(*structElem); - s.WriteInteger(*field, 2); - s.EndNestedStructure(); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteStruct(*structElem, LambdaStruct(*structElem, [&](ShapeSerializer& es) { es.WriteInteger(*field, 1); })); + lser.WriteStruct(*structElem, LambdaStruct(*structElem, [&](ShapeSerializer& es) { es.WriteInteger(*field, 2); })); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"items\":[{\"id\":1},{\"id\":2}]"), Aws::String::npos); } @@ -243,13 +236,14 @@ TEST_F(JsonShapeSerializerTest, SparseList) { auto root = Schema::StructureBuilder("Root").Build(); auto listMember = Schema::CreateMember("items", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.BeginList(*listMember, 3); - s.WriteString(*elem, "a"); - s.WriteNull(*elem); - s.WriteString(*elem, "b"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "a"); + lser.WriteNull(*elem); + lser.WriteString(*elem, "b"); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"items\":[\"a\",null,\"b\"]"), Aws::String::npos); } @@ -260,14 +254,13 @@ TEST_F(JsonShapeSerializerTest, MapOfStrings) { auto root = Schema::StructureBuilder("Root").Build(); auto mapMember = Schema::CreateMember("headers", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 2); - s.WriteMapKey("x-foo"); - s.WriteString(*valSchema, "bar"); - s.WriteMapKey("x-baz"); - s.WriteString(*valSchema, "qux"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 2, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("x-foo", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "bar"); }); + mapSer.WriteEntry("x-baz", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "qux"); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("\"x-foo\":\"bar\""), Aws::String::npos); EXPECT_NE(payload.find("\"x-baz\":\"qux\""), Aws::String::npos); @@ -277,10 +270,8 @@ TEST_F(JsonShapeSerializerTest, EmptyMap) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto mapMember = Schema::CreateMember("tags", ShapeType::Map); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 0); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteMap(*mapMember, 0, [](MapSerializer&) {}); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"tags\":{}"), Aws::String::npos); } @@ -290,14 +281,14 @@ TEST_F(JsonShapeSerializerTest, MapOfStructures) { auto mapMember = Schema::CreateMember("nodes", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::Structure); auto field = Schema::CreateMember("val", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("a"); - s.BeginNestedStructure(*valSchema); - s.WriteInteger(*field, 1); - s.EndNestedStructure(); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("a", [&](ShapeSerializer& vser) { + vser.WriteStruct(*valSchema, LambdaStruct(*valSchema, [&](ShapeSerializer& vs) { vs.WriteInteger(*field, 1); })); + }); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"nodes\":{\"a\":{\"val\":1}}"), Aws::String::npos); } @@ -306,14 +297,13 @@ TEST_F(JsonShapeSerializerTest, SparseMap) { auto root = Schema::StructureBuilder("Root").Build(); auto mapMember = Schema::CreateMember("data", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 2); - s.WriteMapKey("present"); - s.WriteString(*valSchema, "yes"); - s.WriteMapKey("absent"); - s.WriteNull(*valSchema); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 2, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("present", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "yes"); }); + mapSer.WriteEntry("absent", [&](ShapeSerializer& vser) { vser.WriteNull(*valSchema); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("\"present\":\"yes\""), Aws::String::npos); EXPECT_NE(payload.find("\"absent\":null"), Aws::String::npos); @@ -330,17 +320,17 @@ TEST_F(JsonShapeSerializerTest, StructureWithListAndMap) { auto mapMember = Schema::CreateMember("meta", ShapeType::Map); auto mapVal = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*strMember, "test"); - s.BeginList(*listMember, 2); - s.WriteString(*listElem, "t1"); - s.WriteString(*listElem, "t2"); - s.EndList(); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("k"); - s.WriteString(*mapVal, "v"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteString(*strMember, "test"); + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteString(*listElem, "t1"); + lser.WriteString(*listElem, "t2"); + }); + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteString(*mapVal, "v"); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("\"name\":\"test\""), Aws::String::npos); @@ -355,15 +345,17 @@ TEST_F(JsonShapeSerializerTest, MapContainingList) { auto listSchema = Schema::CreateMember("value", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("nums"); - s.BeginList(*listSchema, 2); - s.WriteInteger(*elem, 1); - s.WriteInteger(*elem, 2); - s.EndList(); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("nums", [&](ShapeSerializer& vser) { + vser.WriteList(*listSchema, 2, [&](ShapeSerializer& lser) { + lser.WriteInteger(*elem, 1); + lser.WriteInteger(*elem, 2); + }); + }); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"data\":{\"nums\":[1,2]}"), Aws::String::npos); } @@ -374,9 +366,8 @@ TEST_F(JsonShapeSerializerTest, EscapesQuotesInString) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("msg", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "say \"hello\""); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "say \"hello\""); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"msg\":\"say \\\"hello\\\"\""), Aws::String::npos); } @@ -384,9 +375,8 @@ TEST_F(JsonShapeSerializerTest, EscapesBackslash) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("path", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "C:\\Users\\test"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "C:\\Users\\test"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"path\":\"C:\\\\Users\\\\test\""), Aws::String::npos); } @@ -394,9 +384,8 @@ TEST_F(JsonShapeSerializerTest, EscapesControlCharacters) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("text", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "line1\nline2\ttab"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "line1\nline2\ttab"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"text\":\"line1\\nline2\\ttab\""), Aws::String::npos); } @@ -404,12 +393,11 @@ TEST_F(JsonShapeSerializerTest, EscapesNullByte) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("data", ShapeType::String); - s.BeginStructure(*root); Aws::String val("ab"); val += '\0'; val += "cd"; - s.WriteString(*member, val); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, val); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"data\":\"ab\\u0000cd\""), Aws::String::npos); } @@ -418,12 +406,12 @@ TEST_F(JsonShapeSerializerTest, EscapesInMapKey) { auto root = Schema::StructureBuilder("Root").Build(); auto mapMember = Schema::CreateMember("m", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("key\"with\"quotes"); - s.WriteString(*valSchema, "v"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("key\"with\"quotes", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "v"); }); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"key\\\"with\\\"quotes\":\"v\""), Aws::String::npos); } @@ -433,11 +421,15 @@ TEST_F(JsonShapeSerializerTest, MaxDepthEnforcement) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto nested = Schema::CreateMember("n", ShapeType::Structure); - s.BeginStructure(*root); - // Nest 1000+ times to exceed MAX_DEPTH - for (int i = 0; i < 1000; i++) { - s.BeginNestedStructure(*nested); - } + // Nest well past MAX_DEPTH; the serializer stops and reports the error. + std::function nest = [&](ShapeSerializer& ser, int remaining) { + if (remaining <= 0) { + return; + } + ser.WriteStruct(*nested, LambdaStruct(*nested, [&, remaining](ShapeSerializer& inner) { nest(inner, remaining - 1); })); + }; + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { nest(ser, 200); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_FALSE(outcome.IsSuccess()); EXPECT_NE(outcome.GetError().GetMessage().find("depth"), Aws::String::npos); @@ -448,10 +440,10 @@ TEST_F(JsonShapeSerializerTest, MaxDepthEnforcement) { TEST_F(JsonShapeSerializerTest, JsonNameOverridesMemberName) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); - auto member = Schema::CreateMember("internalName", ShapeType::String, {{JsonNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")}}); - s.BeginStructure(*root); - s.WriteString(*member, "hello"); - s.EndStructure(); + auto member = Schema::CreateMember("internalName", ShapeType::String, + {{JsonNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")}}); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("\"ExternalName\":\"hello\""), Aws::String::npos); EXPECT_EQ(payload.find("\"internalName\""), Aws::String::npos); @@ -461,9 +453,8 @@ TEST_F(JsonShapeSerializerTest, NoJsonNameUsesGetMemberName) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("fieldName", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "value"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "value"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"fieldName\":\"value\""), Aws::String::npos); } @@ -471,9 +462,8 @@ TEST_F(JsonShapeSerializerTest, FloatValue) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("f", ShapeType::Float); - s.BeginStructure(*root); - s.WriteFloat(*member, 1.5f); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteFloat(*member, 1.5f); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); EXPECT_EQ(outcome.GetResult(), "{\"f\":1.5}"); @@ -483,9 +473,8 @@ TEST_F(JsonShapeSerializerTest, FloatNegativeValue) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto member = Schema::CreateMember("f", ShapeType::Float); - s.BeginStructure(*root); - s.WriteFloat(*member, -2.25f); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteFloat(*member, -2.25f); }); + s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); ASSERT_TRUE(outcome.IsSuccess()); EXPECT_EQ(outcome.GetResult(), "{\"f\":-2.25}"); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h new file mode 100644 index 000000000000..11281ca2a109 --- /dev/null +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h @@ -0,0 +1,39 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#pragma once + +#include +#include +#include + +#include +#include + +namespace smithy { +namespace schema { + +// Test-only SerializableStruct that writes its members from a lambda, so a test +// can express a struct body inline instead of defining a generated shape type: +// LambdaStruct s(*schema, [&](ShapeSerializer& ser){ ser.WriteString(*member, "v"); }); +// serializer.WriteStruct(*schema, s); +class LambdaStruct final : public SerializableStruct { + public: + LambdaStruct(const Schema& schema, std::function members) + : m_schema(schema), m_members(std::move(members)) {} + + const Schema& GetSchema() const override { return m_schema; } + void SerializeMembers(ShapeSerializer& serializer) const override { + if (m_members) { + m_members(serializer); + } + } + + private: + const Schema& m_schema; + std::function m_members; +}; + +} // namespace schema +} // namespace smithy diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp index 75cdf7c90679..4a18d9496ef4 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp @@ -4,11 +4,16 @@ */ #include #include +#include #include #include #include #include +#include + +#include "SchemaSerializerTestHelpers.h" + using namespace smithy::schema; class XmlShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; @@ -18,8 +23,8 @@ class XmlShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; TEST_F(XmlShapeSerializerTest, EmptyStructure) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); - s.BeginStructure(*root); - s.EndStructure(); + LambdaStruct rootStruct(*root, [](ShapeSerializer&) {}); + s.WriteStruct(*root, rootStruct); EXPECT_EQ(s.GetPayload().GetResult(), ""); } @@ -27,9 +32,8 @@ TEST_F(XmlShapeSerializerTest, BooleanTrue) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("enabled", ShapeType::Boolean); - s.BeginStructure(*root); - s.WriteBoolean(*member, true); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, true); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("true"), Aws::String::npos); } @@ -37,9 +41,8 @@ TEST_F(XmlShapeSerializerTest, BooleanFalse) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("enabled", ShapeType::Boolean); - s.BeginStructure(*root); - s.WriteBoolean(*member, false); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBoolean(*member, false); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("false"), Aws::String::npos); } @@ -47,9 +50,8 @@ TEST_F(XmlShapeSerializerTest, Integer) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("count", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteInteger(*member, 42); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*member, 42); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("42"), Aws::String::npos); } @@ -57,9 +59,8 @@ TEST_F(XmlShapeSerializerTest, Long) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("bigNum", ShapeType::Long); - s.BeginStructure(*root); - s.WriteLong(*member, 9876543210LL); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteLong(*member, 9876543210LL); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("9876543210"), Aws::String::npos); } @@ -67,9 +68,8 @@ TEST_F(XmlShapeSerializerTest, Double) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("ratio", ShapeType::Double); - s.BeginStructure(*root); - s.WriteDouble(*member, 3.14); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteDouble(*member, 3.14); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("3.14"), Aws::String::npos); } @@ -77,9 +77,8 @@ TEST_F(XmlShapeSerializerTest, String) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("name", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "hello"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("hello"), Aws::String::npos); } @@ -87,9 +86,8 @@ TEST_F(XmlShapeSerializerTest, EmptyString) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("name", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, ""); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, ""); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find(""), Aws::String::npos); } @@ -97,10 +95,9 @@ TEST_F(XmlShapeSerializerTest, Timestamp) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("created", ShapeType::Timestamp); - s.BeginStructure(*root); Aws::Utils::DateTime dt(1234567890.0); - s.WriteTimestamp(*member, dt); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteTimestamp(*member, dt); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("2009-02-13T23:31:30Z"), Aws::String::npos); } @@ -108,23 +105,22 @@ TEST_F(XmlShapeSerializerTest, Blob) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("data", ShapeType::Blob); - s.BeginStructure(*root); unsigned char raw[] = {0x66, 0x6f, 0x6f}; Aws::Utils::ByteBuffer buf(raw, 3); - s.WriteBlob(*member, buf); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteBlob(*member, buf); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("Zm9v"), Aws::String::npos); } -TEST_F(XmlShapeSerializerTest, NullValueOmitted) { +TEST_F(XmlShapeSerializerTest, NullValueWritesEmptyElement) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("item", ShapeType::String); - s.BeginStructure(*root); - s.WriteNull(*member); - s.EndStructure(); - // Null values are omitted in XML - EXPECT_EQ(s.GetPayload().GetResult(), ""); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteNull(*member); }); + s.WriteStruct(*root, rootStruct); + // An explicit null writes an empty element; generated code omits absent + // members by not calling WriteNull at all. + EXPECT_EQ(s.GetPayload().GetResult(), ""); } TEST_F(XmlShapeSerializerTest, MultipleScalars) { @@ -133,11 +129,12 @@ TEST_F(XmlShapeSerializerTest, MultipleScalars) { auto m1 = Schema::CreateMember("a", ShapeType::Boolean); auto m2 = Schema::CreateMember("b", ShapeType::Integer); auto m3 = Schema::CreateMember("c", ShapeType::String); - s.BeginStructure(*root); - s.WriteBoolean(*m1, true); - s.WriteInteger(*m2, 7); - s.WriteString(*m3, "x"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteBoolean(*m1, true); + ser.WriteInteger(*m2, 7); + ser.WriteString(*m3, "x"); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("true"), Aws::String::npos); EXPECT_NE(payload.find("7"), Aws::String::npos); @@ -151,11 +148,10 @@ TEST_F(XmlShapeSerializerTest, NestedStructure) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto nested = Schema::CreateMember("metadata", ShapeType::Structure); auto inner = Schema::CreateMember("key", ShapeType::String); - s.BeginStructure(*root); - s.BeginNestedStructure(*nested); - s.WriteString(*inner, "val"); - s.EndNestedStructure(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*nested, LambdaStruct(*nested, [&](ShapeSerializer& ser2) { ser2.WriteString(*inner, "val"); })); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("val"), Aws::String::npos); } @@ -165,13 +161,14 @@ TEST_F(XmlShapeSerializerTest, DeeplyNestedStructure) { auto level1 = Schema::CreateMember("l1", ShapeType::Structure); auto level2 = Schema::CreateMember("l2", ShapeType::Structure); auto leaf = Schema::CreateMember("val", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginNestedStructure(*level1); - s.BeginNestedStructure(*level2); - s.WriteInteger(*leaf, 99); - s.EndNestedStructure(); - s.EndNestedStructure(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteStruct(*level1, LambdaStruct(*level1, [&](ShapeSerializer& ser2) { + ser2.WriteStruct(*level2, LambdaStruct(*level2, [&](ShapeSerializer& ser3) { + ser3.WriteInteger(*leaf, 99); + })); + })); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("99"), Aws::String::npos); } @@ -182,13 +179,14 @@ TEST_F(XmlShapeSerializerTest, ListOfStrings) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto listMember = Schema::CreateMember("tags", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.BeginList(*listMember, 3); - s.WriteString(*elem, "a"); - s.WriteString(*elem, "b"); - s.WriteString(*elem, "c"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "a"); + lser.WriteString(*elem, "b"); + lser.WriteString(*elem, "c"); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("abc"), Aws::String::npos); } @@ -197,13 +195,14 @@ TEST_F(XmlShapeSerializerTest, ListOfIntegers) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto listMember = Schema::CreateMember("nums", ShapeType::List); auto elem = Schema::CreateMember("member", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginList(*listMember, 3); - s.WriteInteger(*elem, 1); - s.WriteInteger(*elem, 2); - s.WriteInteger(*elem, 3); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteInteger(*elem, 1); + lser.WriteInteger(*elem, 2); + lser.WriteInteger(*elem, 3); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("123"), Aws::String::npos); } @@ -211,10 +210,8 @@ TEST_F(XmlShapeSerializerTest, EmptyList) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto listMember = Schema::CreateMember("items", ShapeType::List); - s.BeginStructure(*root); - s.BeginList(*listMember, 0); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteList(*listMember, 0, [](ShapeSerializer&) {}); }); + s.WriteStruct(*root, rootStruct); // Empty list still produces the wrapper element EXPECT_NE(s.GetPayload().GetResult().find(""), Aws::String::npos); } @@ -225,16 +222,13 @@ TEST_F(XmlShapeSerializerTest, ListOfStructures) { auto listMember = Schema::CreateMember("items", ShapeType::List); auto structElem = Schema::CreateMember("member", ShapeType::Structure); auto field = Schema::CreateMember("id", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginList(*listMember, 2); - s.BeginNestedStructure(*structElem); - s.WriteInteger(*field, 1); - s.EndNestedStructure(); - s.BeginNestedStructure(*structElem); - s.WriteInteger(*field, 2); - s.EndNestedStructure(); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteStruct(*structElem, LambdaStruct(*structElem, [&](ShapeSerializer& es) { es.WriteInteger(*field, 1); })); + lser.WriteStruct(*structElem, LambdaStruct(*structElem, [&](ShapeSerializer& es) { es.WriteInteger(*field, 2); })); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("12"), Aws::String::npos); } @@ -245,14 +239,13 @@ TEST_F(XmlShapeSerializerTest, MapOfStrings) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto mapMember = Schema::CreateMember("headers", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 2); - s.WriteMapKey("foo"); - s.WriteString(*valSchema, "bar"); - s.WriteMapKey("baz"); - s.WriteString(*valSchema, "qux"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 2, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("foo", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "bar"); }); + mapSer.WriteEntry("baz", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "qux"); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("foobar"), Aws::String::npos); EXPECT_NE(payload.find("bazqux"), Aws::String::npos); @@ -264,10 +257,8 @@ TEST_F(XmlShapeSerializerTest, EmptyMap) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto mapMember = Schema::CreateMember("tags", ShapeType::Map); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 0); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteMap(*mapMember, 0, [](MapSerializer&) {}); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find(""), Aws::String::npos); } @@ -277,14 +268,14 @@ TEST_F(XmlShapeSerializerTest, MapOfStructures) { auto mapMember = Schema::CreateMember("nodes", ShapeType::Map); auto valSchema = Schema::CreateMember("value", ShapeType::Structure); auto field = Schema::CreateMember("val", ShapeType::Integer); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("a"); - s.BeginNestedStructure(*valSchema); - s.WriteInteger(*field, 1); - s.EndNestedStructure(); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("a", [&](ShapeSerializer& vser) { + vser.WriteStruct(*valSchema, LambdaStruct(*valSchema, [&](ShapeSerializer& vs) { vs.WriteInteger(*field, 1); })); + }); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("a1"), Aws::String::npos); } @@ -299,17 +290,17 @@ TEST_F(XmlShapeSerializerTest, StructureWithListAndMap) { auto mapMember = Schema::CreateMember("meta", ShapeType::Map); auto mapVal = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*strMember, "test"); - s.BeginList(*listMember, 2); - s.WriteString(*listElem, "t1"); - s.WriteString(*listElem, "t2"); - s.EndList(); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("k"); - s.WriteString(*mapVal, "v"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteString(*strMember, "test"); + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteString(*listElem, "t1"); + lser.WriteString(*listElem, "t2"); + }); + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteString(*mapVal, "v"); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("test"), Aws::String::npos); @@ -323,9 +314,8 @@ TEST_F(XmlShapeSerializerTest, EscapesAmpersand) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("msg", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "a&b"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "a&b"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("a&b"), Aws::String::npos); } @@ -333,9 +323,8 @@ TEST_F(XmlShapeSerializerTest, EscapesLessThan) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("msg", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "aa<b"), Aws::String::npos); } @@ -343,9 +332,8 @@ TEST_F(XmlShapeSerializerTest, EscapesGreaterThan) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("msg", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "a>b"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "a>b"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("a>b"), Aws::String::npos); } @@ -353,9 +341,8 @@ TEST_F(XmlShapeSerializerTest, EscapesQuotes) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("msg", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "say \"hello\""); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "say \"hello\""); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("say "hello""), Aws::String::npos); } @@ -363,9 +350,8 @@ TEST_F(XmlShapeSerializerTest, EscapesMultipleSpecialChars) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("expr", ShapeType::String); - s.BeginStructure(*root); - s.WriteString(*member, "x < 5 & y > 3"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "x < 5 & y > 3"); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("x < 5 & y > 3"), Aws::String::npos); } @@ -375,14 +361,16 @@ TEST_F(XmlShapeSerializerTest, MaxDepthEnforcement) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto nested = Schema::CreateMember("n", ShapeType::Structure); - s.BeginStructure(*root); - bool hitLimit = false; - for (int i = 0; i < 1000; i++) { - if (!s.BeginNestedStructure(*nested)) { - hitLimit = true; - break; + // Nest well past the depth limit; the serializer stops and reports the error. + std::function nest = [&](ShapeSerializer& ser, int remaining) { + if (remaining <= 0) { + return; } - } + ser.WriteStruct(*nested, LambdaStruct(*nested, [&, remaining](ShapeSerializer& inner) { nest(inner, remaining - 1); })); + }; + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { nest(ser, 1000); }); + s.WriteStruct(*root, rootStruct); + bool hitLimit = !s.GetPayload().IsSuccess(); EXPECT_TRUE(hitLimit); } @@ -392,9 +380,8 @@ TEST_F(XmlShapeSerializerTest, XmlNameOverridesMemberName) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("internalName", ShapeType::String, {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")}}); - s.BeginStructure(*root); - s.WriteString(*member, "hello"); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("hello"), Aws::String::npos); EXPECT_EQ(payload.find(""), Aws::String::npos); @@ -404,9 +391,8 @@ TEST_F(XmlShapeSerializerTest, XmlNameOnStructure) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("MyStruct", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "CustomRoot")}}).Build(); auto field = Schema::CreateMember("val", ShapeType::Integer); - s.BeginStructure(*root); - s.WriteInteger(*field, 42); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteInteger(*field, 42); }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("42"), Aws::String::npos); } @@ -417,13 +403,14 @@ TEST_F(XmlShapeSerializerTest, FlattenedListOfStrings) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto listMember = Schema::CreateMember("item", ShapeType::List, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}}); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.BeginList(*listMember, 3); - s.WriteString(*elem, "a"); - s.WriteString(*elem, "b"); - s.WriteString(*elem, "c"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "a"); + lser.WriteString(*elem, "b"); + lser.WriteString(*elem, "c"); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); // Flattened: no wrapper, items repeat with list's xmlName EXPECT_NE(payload.find("abc"), Aws::String::npos); @@ -436,12 +423,13 @@ TEST_F(XmlShapeSerializerTest, FlattenedListWithXmlName) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto listMember = Schema::CreateMember("items", ShapeType::List, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}, {XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Tag")}}); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.BeginList(*listMember, 2); - s.WriteString(*elem, "x"); - s.WriteString(*elem, "y"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "x"); + lser.WriteString(*elem, "y"); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("xy"), Aws::String::npos); } @@ -452,12 +440,13 @@ TEST_F(XmlShapeSerializerTest, CustomListItemName) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto listMember = Schema::CreateMember("things", ShapeType::List, {{XmlListItemNameTrait::KEY(), Aws::MakeShared("Schema", "item")}}); auto elem = Schema::CreateMember("member", ShapeType::String); - s.BeginStructure(*root); - s.BeginList(*listMember, 2); - s.WriteString(*elem, "a"); - s.WriteString(*elem, "b"); - s.EndList(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { + lser.WriteString(*elem, "a"); + lser.WriteString(*elem, "b"); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("ab"), Aws::String::npos); } @@ -468,12 +457,12 @@ TEST_F(XmlShapeSerializerTest, CustomMapNames) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto mapMember = Schema::CreateMember("tags", ShapeType::Map, {{XmlMapEntryNameTrait::KEY(), Aws::MakeShared("Schema", "item")}, {XmlMapKeyNameTrait::KEY(), Aws::MakeShared("Schema", "tagKey")}, {XmlMapValueNameTrait::KEY(), Aws::MakeShared("Schema", "tagValue")}}); auto valSchema = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 1); - s.WriteMapKey("color"); - s.WriteString(*valSchema, "red"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("color", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "red"); }); + }); + }); + s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("colorred"), Aws::String::npos); } @@ -482,14 +471,13 @@ TEST_F(XmlShapeSerializerTest, FlattenedMap) { auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto mapMember = Schema::CreateMember("tag", ShapeType::Map, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}}); auto valSchema = Schema::CreateMember("value", ShapeType::String); - s.BeginStructure(*root); - s.BeginMap(*mapMember, 2); - s.WriteMapKey("k1"); - s.WriteString(*valSchema, "v1"); - s.WriteMapKey("k2"); - s.WriteString(*valSchema, "v2"); - s.EndMap(); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { + ser.WriteMap(*mapMember, 2, [&](MapSerializer& mapSer) { + mapSer.WriteEntry("k1", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "v1"); }); + mapSer.WriteEntry("k2", [&](ShapeSerializer& vser) { vser.WriteString(*valSchema, "v2"); }); + }); + }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); // Flattened map: no wrapper, entry uses the map's xmlName EXPECT_NE(payload.find("k1v1"), Aws::String::npos); @@ -500,9 +488,8 @@ TEST_F(XmlShapeSerializerTest, FloatValue) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("temp", ShapeType::Float); - s.BeginStructure(*root); - s.WriteFloat(*member, 1.5f); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteFloat(*member, 1.5f); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("1.5"), Aws::String::npos); } @@ -511,9 +498,8 @@ TEST_F(XmlShapeSerializerTest, FloatNegativeValue) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto member = Schema::CreateMember("val", ShapeType::Float); - s.BeginStructure(*root); - s.WriteFloat(*member, -2.25f); - s.EndStructure(); + LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteFloat(*member, -2.25f); }); + s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); EXPECT_NE(payload.find("-2.25"), Aws::String::npos); } From a2248d121b7d05bd4bacaff03fa4ca6ce7534a0a Mon Sep 17 00:00:00 2001 From: Snigdha Date: Tue, 18 Aug 2026 14:51:02 -0400 Subject: [PATCH 3/4] removing non-essential comments --- .../client/schema/CborShapeSerializer.cpp | 15 ++------ .../client/schema/JsonShapeSerializer.cpp | 17 ++------- .../source/smithy/client/schema/Schema.cpp | 24 ------------- .../client/schema/XmlShapeSerializer.cpp | 36 ------------------- .../schema/CborShapeDeserializerTest.cpp | 14 -------- .../client/schema/CborShapeSerializerTest.cpp | 20 ----------- .../client/schema/JsonShapeSerializerTest.cpp | 17 --------- .../client/schema/XmlShapeSerializerTest.cpp | 24 ------------- 8 files changed, 6 insertions(+), 161 deletions(-) diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp index 6422739ee95a..fe68969fb74f 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp @@ -13,27 +13,22 @@ using namespace smithy::schema; using namespace Aws::Utils; using SerializerOutcome = Aws::Utils::Outcome>; -// Outer serializer: writes bare CBOR values and container framing (indefinite -// map for structs, definite array/map for lists/maps). Struct members are map -// entries, so the struct context writes the member name as the map key before -// the value; list/map contexts add no key. CBOR is length- or break-delimited, -// so there is no separator bookkeeping. class CborShapeSerializer::Impl final : public ShapeSerializer { public: - void WriteStruct(const Schema& /*schema*/, const SerializableStruct& value) override { + void WriteStruct(const Schema&, const SerializableStruct& value) override { m_encoder.WriteIndefMapStart(); StructContext ctx(this); value.SerializeMembers(ctx); m_encoder.WriteBreak(); } - void WriteList(const Schema& /*schema*/, size_t size, const std::function& consumer) override { + void WriteList(const Schema&, size_t size, const std::function& consumer) override { m_encoder.WriteArrayStart(size); ListContext ctx(this); consumer(ctx); } - void WriteMap(const Schema& /*schema*/, size_t size, const std::function& consumer) override { + void WriteMap(const Schema&, size_t size, const std::function& consumer) override { m_encoder.WriteMapStart(size); MapContext ctx(this); consumer(ctx); @@ -55,7 +50,6 @@ class CborShapeSerializer::Impl final : public ShapeSerializer { void WriteEnum(const Schema& schema, int value) override { WriteInteger(schema, value); } void WriteNull(const Schema&) override { m_encoder.WriteNull(); } - // Used by the context objects: a struct member's map key, and a map entry key. void WriteMemberKey(const Schema& schema) { WriteText(schema.GetMemberName()); } void WriteText(const Aws::String& str) { m_encoder.WriteText(Aws::Crt::ByteCursorFromArray(reinterpret_cast(str.data()), str.size())); @@ -73,7 +67,6 @@ class CborShapeSerializer::Impl final : public ShapeSerializer { } private: - // Struct members: member name as the map key, then the value. class StructContext final : public ShapeSerializer { public: explicit StructContext(Impl* outer) : m_outer(outer) {} @@ -96,7 +89,6 @@ class CborShapeSerializer::Impl final : public ShapeSerializer { Impl* m_outer; }; - // List elements: value only (the array carries the count). class ListContext final : public ShapeSerializer { public: explicit ListContext(Impl* outer) : m_outer(outer) {} @@ -119,7 +111,6 @@ class CborShapeSerializer::Impl final : public ShapeSerializer { Impl* m_outer; }; - // Map entries: text key, then the value. class MapContext final : public MapSerializer { public: explicit MapContext(Impl* outer) : m_outer(outer) {} diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp index 332066d1561e..5c10d8343c45 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp @@ -20,17 +20,11 @@ using SerializerOutcome = Aws::Utils::Outcome& consumer) override { + void WriteList(const Schema&, size_t, const std::function& consumer) override { if (!OpenContainer('[')) { return; } @@ -48,7 +42,7 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { CloseContainer(']'); } - void WriteMap(const Schema& /*schema*/, size_t, const std::function& consumer) override { + void WriteMap(const Schema&, size_t, const std::function& consumer) override { if (!OpenContainer('{')) { return; } @@ -57,7 +51,6 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { CloseContainer('}'); } - // Bare scalar writers: value only, no prefix. void WriteBoolean(const Schema&, bool value) override { m_buf += value ? "true" : "false"; } void WriteInteger(const Schema&, int value) override { m_buf += StringUtils::to_string(value); } void WriteLong(const Schema&, int64_t value) override { m_buf += StringUtils::to_string(value); } @@ -75,7 +68,6 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { void WriteEnum(const Schema& schema, int value) override { WriteInteger(schema, value); } void WriteNull(const Schema&) override { m_buf += "null"; } - // Prefix primitives, used by the context objects. void WriteCommaIfNeeded() { if (m_needsComma[m_depth]) { m_buf += ','; @@ -106,7 +98,6 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { } private: - // Struct members: field name, then the value written bare by the outer. class StructContext final : public ShapeSerializer { public: explicit StructContext(Impl* outer) : m_outer(outer) {} @@ -129,7 +120,6 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { Impl* m_outer; }; - // List elements: comma, then the value written bare by the outer. class ListContext final : public ShapeSerializer { public: explicit ListContext(Impl* outer) : m_outer(outer) {} @@ -152,7 +142,6 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { Impl* m_outer; }; - // Map entries: comma, key, then the value written bare by the outer. class MapContext final : public MapSerializer { public: explicit MapContext(Impl* outer) : m_outer(outer) {} diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp index 794a2fe5c9a9..e8c5929276bc 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp @@ -25,8 +25,6 @@ TraitMap ToTraitMap(TraitList traits) { return map; } -// Compose a member id from its containing shape id and member name, e.g. -// "com.example#Foo$bar". Purely informational; used for GetId(). Aws::String MakeMemberId(const Aws::String& shapeId, const Aws::String& memberName) { Aws::String id = shapeId; id += "$"; @@ -34,7 +32,6 @@ Aws::String MakeMemberId(const Aws::String& shapeId, const Aws::String& memberNa return id; } -// A leaf shape with no members. class ScalarSchema final : public Schema { public: ScalarSchema(ShapeType type, const char* id, TraitList traits) @@ -48,11 +45,6 @@ class ScalarSchema final : public Schema { Aws::String m_id; }; -// A named member of an aggregate shape. Delegates its type to the shape it -// targets. A member normally owns its target; the weak overload is used only for -// recursive members, where the target is kept alive by the definition site so -// the graph does not form a reference cycle. Either way GetMemberTarget() hands -// back a shared_ptr that lifetime-extends the target while the caller holds it. class MemberSchema final : public Schema { public: MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::shared_ptr target, @@ -96,9 +88,6 @@ class MemberSchema final : public Schema { std::weak_ptr m_weakTarget; }; -// A shape that carries members (structure, union, list, map). Owns its member -// nodes and any eagerly-built target shapes; recursively referenced targets are -// kept alive by the definition site, not by this shape. class RootSchema final : public Schema { public: RootSchema(ShapeType type, const Aws::String& id, TraitMap traits) : m_type(type), m_id(id) { @@ -125,10 +114,6 @@ class RootSchema final : public Schema { uint16_t GetMemberCount() const override { return static_cast(m_members.size()); } - // Used only by SchemaBuilder while assembling the shape. Member names must be - // unique within a shape; a duplicate is a codegen/programming error, so reject - // it rather than shadowing the earlier member (which would leave the first - // unreachable by name yet still counted in GetMemberCount()). void AddMember(const std::shared_ptr& member) { const auto inserted = m_nameToIndex.emplace(member->GetMemberName(), static_cast(m_members.size())); assert(inserted.second && "duplicate member name in schema"); @@ -149,7 +134,6 @@ std::shared_ptr MakeScalar(ShapeType type, const char* id, TraitLi return Aws::MakeShared(SCHEMA_ALLOC_TAG, type, id, traits); } -// An empty shape of the given type, used as the target of a standalone member. std::shared_ptr MakeEmptyShape(ShapeType type, const char* id) { switch (type) { case ShapeType::Structure: @@ -217,8 +201,6 @@ std::shared_ptr Schema::CreateMember(const char* name, ShapeType t MakeEmptyShape(targetType, name), ToTraitMap(traits)); } -// A pending member captured before Build(). Exactly one of eagerTarget / -// deferredTarget is set. class SchemaBuilder::SchemaBuilderImpl { public: SchemaBuilderImpl(ShapeType type, const char* id, TraitList traits) @@ -252,9 +234,6 @@ class SchemaBuilder::SchemaBuilderImpl { return m_builtShape; } - // Publish the shell before resolving members so a member that targets this - // same shape (directly or transitively) sees the in-progress shape rather - // than recursing forever. auto shell = Aws::MakeShared(SCHEMA_ALLOC_TAG, m_type, m_id, m_traits); m_builtShape = shell; @@ -262,12 +241,9 @@ class SchemaBuilder::SchemaBuilderImpl { for (auto& pending : m_members) { std::shared_ptr member; if (pending.eagerTarget) { - // Non-recursive member owns its target directly. member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, pending.eagerTarget, pending.traits); } else if (pending.deferredTarget != nullptr) { - // Recursive member holds a weak reference to a target kept alive by the - // definition site, so the schema graph does not form a reference cycle. std::weak_ptr target = pending.deferredTarget->Build(); member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, target, pending.traits); diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp index 8d981781ac2a..72a3455dd80d 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp @@ -48,16 +48,8 @@ void AppendXmlEscaped(Aws::String& buf, const Aws::String& value) { } // namespace -// XML serializer following smithy-java's SmithyXmlSerializer: an outer -// InterceptingSerializer wraps each value in its element (Before writes the -// start tag, After the end tag), delegating the element content to a value -// serializer. Structs are two-pass — attributes are written into the still-open -// start tag first, the tag is then closed, then child-element members are -// written. Names, namespaces, flattening, and attribute-ness are resolved from -// schema traits rather than precomputed tables. class XmlShapeSerializer::Impl final : public InterceptingSerializer { public: - // Writes an element's content (the wrapping element is written by the caller). class ValueSerializer final : public ShapeSerializer { public: explicit ValueSerializer(Impl* outer) : m_outer(outer) {} @@ -79,9 +71,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { Impl* m_outer; }; - // Routes each struct member: skips attributes (handled in the attribute pass), - // writes an element wrapper for ordinary members, and skips the wrapper for - // flattened list/map members. class StructElementSerializer final : public InterceptingSerializer { public: explicit StructElementSerializer(Impl* outer) : m_outer(outer) {} @@ -94,8 +83,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { Impl* m_outer; }; - // Attribute pass: routes attribute members to the inline attribute writer and - // discards everything else. class StructAttributeSerializer final : public InterceptingSerializer { public: explicit StructAttributeSerializer(Impl* outer) : m_outer(outer) {} @@ -107,7 +94,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { Impl* m_outer; }; - // Writes a scalar member as an attribute on the currently-open start tag. class InlineAttributeSerializer final : public SpecificShapeSerializer { public: explicit InlineAttributeSerializer(Impl* outer) : m_outer(outer) {} @@ -125,7 +111,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { Impl* m_outer; }; - // Wraps each list element in the resolved item element. class ListItemSerializer final : public InterceptingSerializer { public: ListItemSerializer(Impl* outer, Aws::String itemName, Aws::String itemNamespace) @@ -141,7 +126,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { Aws::String m_itemNamespace; }; - // Writes each map entry as ..... class XmlMapEntrySerializer final : public MapSerializer { public: XmlMapEntrySerializer(Impl* outer, Aws::String entryName, Aws::String keyName, Aws::String valueName) @@ -176,8 +160,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { return std::move(m_buf); } - // Guards against unbounded nesting. Returns false (and records an error) once - // the depth limit is reached, so the container body is skipped. bool EnterContainer() { if (!m_errorMessage.empty()) { return false; @@ -191,7 +173,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { } void ExitContainer() { --m_depth; } - // Tag primitives. void ClosePendingTag() { if (m_pendingClose) { m_buf += '>'; @@ -217,7 +198,6 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { void AppendRaw(const Aws::String& text) { m_buf += text; } void AppendEscaped(const Aws::String& text) { AppendXmlEscaped(m_buf, text); } - // Trait-resolved shape metadata. static Aws::String GetXmlName(const Schema& schema) { const auto trait = schema.GetTrait(XmlNameTrait::KEY()); if (trait) { @@ -299,16 +279,10 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { SpecificShapeSerializer m_nullSerializer; }; -// --- ValueSerializer --- - void XmlShapeSerializer::Impl::ValueSerializer::WriteStruct(const Schema&, const SerializableStruct& value) { if (!m_outer->EnterContainer()) { return; } - // Attribute pass: attribute members write into the still-open start tag; every - // other member routes to the null serializer and produces nothing. Running it - // unconditionally is output-identical to gating on "has attributes" and does - // not depend on the members being declared on the struct's own schema. value.SerializeMembers(m_outer->StructAttribute()); m_outer->ClosePendingTag(); value.SerializeMembers(m_outer->StructElement()); @@ -374,8 +348,6 @@ void XmlShapeSerializer::Impl::ValueSerializer::WriteBlob(const Schema&, const A void XmlShapeSerializer::Impl::ValueSerializer::WriteEnum(const Schema& schema, int value) { WriteInteger(schema, value); } void XmlShapeSerializer::Impl::ValueSerializer::WriteNull(const Schema&) { m_outer->ClosePendingTag(); } -// --- StructElementSerializer --- - ShapeSerializer& XmlShapeSerializer::Impl::StructElementSerializer::Before(const Schema& schema) { if (Impl::IsAttribute(schema)) { return m_outer->Null(); @@ -394,8 +366,6 @@ void XmlShapeSerializer::Impl::StructElementSerializer::After(const Schema& sche m_outer->WriteCloseTag(Impl::GetXmlName(schema)); } -// --- StructAttributeSerializer --- - ShapeSerializer& XmlShapeSerializer::Impl::StructAttributeSerializer::Before(const Schema& schema) { if (Impl::IsAttribute(schema)) { return m_outer->InlineAttribute(); @@ -403,8 +373,6 @@ ShapeSerializer& XmlShapeSerializer::Impl::StructAttributeSerializer::Before(con return m_outer->Null(); } -// --- InlineAttributeSerializer --- - void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteAttr(const Schema& schema, const Aws::String& value) { m_outer->AppendRaw(" "); m_outer->AppendRaw(Impl::GetXmlName(schema)); @@ -438,16 +406,12 @@ void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteEnum(const Schema WriteAttr(schema, StringUtils::to_string(value)); } -// --- ListItemSerializer --- - ShapeSerializer& XmlShapeSerializer::Impl::ListItemSerializer::Before(const Schema&) { m_outer->WriteStartOpen(m_itemName, m_itemNamespace); return m_outer->Value(); } void XmlShapeSerializer::Impl::ListItemSerializer::After(const Schema&) { m_outer->WriteCloseTag(m_itemName); } -// --- XmlMapEntrySerializer --- - void XmlShapeSerializer::Impl::XmlMapEntrySerializer::WriteEntry(const Aws::String& key, const std::function& value) { m_outer->WriteFullOpenTag(m_entryName); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp index 66a985d501f7..3e5cfd7e00dc 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp @@ -18,8 +18,6 @@ using namespace smithy::schema; class CborShapeDeserializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; -// --- Scalars --- - TEST_F(CborShapeDeserializerTest, BooleanTrue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -271,8 +269,6 @@ TEST_F(CborShapeDeserializerTest, NullValue) { d.EndStruct(); } -// --- Collections --- - TEST_F(CborShapeDeserializerTest, ListOfIntegers) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -376,8 +372,6 @@ TEST_F(CborShapeDeserializerTest, NestedStructure) { d.EndStruct(); } -// --- Skip unknown fields --- - TEST_F(CborShapeDeserializerTest, SkipUnknownField) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -447,8 +441,6 @@ TEST_F(CborShapeDeserializerTest, SkipNestedUnknown) { d.EndStruct(); } -// --- Multiple fields --- - TEST_F(CborShapeDeserializerTest, MultipleScalars) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -487,8 +479,6 @@ TEST_F(CborShapeDeserializerTest, MultipleScalars) { d.EndStruct(); } -// --- Error handling (Optional returns empty on failure) --- - TEST_F(CborShapeDeserializerTest, EmptyOptionalOnEmptyPayload) { const unsigned char empty[1] = {0}; CborShapeDeserializer d(empty, 0); @@ -531,8 +521,6 @@ TEST_F(CborShapeDeserializerTest, ValidOptionalOnSuccess) { EXPECT_EQ(val.value(), 42); } -// --- BeginStruct returns size for definite-length maps --- - TEST_F(CborShapeDeserializerTest, BeginStructDefiniteLengthMap) { // Definite-length map with 2 entries: // A2 -- map(2) @@ -581,8 +569,6 @@ TEST_F(CborShapeDeserializerTest, BeginStructIndefiniteLengthMap) { d.EndStruct(); } -// --- Timestamp handling --- - TEST_F(CborShapeDeserializerTest, TimestampFromFloat) { // tag(1) followed by float64 1234567890.5 // C1 = tag(1), FB = float64, 41D26580B4A00000 = IEEE 754 1234567890.5 diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp index 95a0b530da80..ae4f3782ecbe 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp @@ -22,8 +22,6 @@ namespace { Aws::String Bytes(const char* data, size_t len) { return Aws::String(data, len); } } // namespace -// --- Scalars --- - TEST_F(CborShapeSerializerTest, EmptyStructure) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -325,8 +323,6 @@ TEST_F(CborShapeSerializerTest, TimestampFractionalSeconds) { EXPECT_EQ(static_cast(payload[10]), 0xFF); } -// --- Multiple fields --- - TEST_F(CborShapeSerializerTest, MultipleScalars) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -358,8 +354,6 @@ TEST_F(CborShapeSerializerTest, MultipleScalars) { EXPECT_EQ(payload, expected); } -// --- Nested structures --- - TEST_F(CborShapeSerializerTest, NestedStructure) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -419,8 +413,6 @@ TEST_F(CborShapeSerializerTest, DeeplyNestedStructure) { EXPECT_EQ(payload, expected); } -// --- Lists --- - TEST_F(CborShapeSerializerTest, ListOfIntegers) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -530,8 +522,6 @@ TEST_F(CborShapeSerializerTest, ListOfStructures) { EXPECT_EQ(payload, expected); } -// --- Maps --- - TEST_F(CborShapeSerializerTest, MapOfStrings) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -615,10 +605,6 @@ TEST_F(CborShapeSerializerTest, MapOfStructures) { EXPECT_EQ(payload, expected); } -// --- Depth limit --- - -// --- GetPayload error cases --- - TEST_F(CborShapeSerializerTest, GetPayloadCalledTwice) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -631,8 +617,6 @@ TEST_F(CborShapeSerializerTest, GetPayloadCalledTwice) { EXPECT_NE(outcome2.GetError().GetMessage().find("finalized"), Aws::String::npos); } -// --- Enum --- - TEST_F(CborShapeSerializerTest, EnumValue) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -651,8 +635,6 @@ TEST_F(CborShapeSerializerTest, EnumValue) { EXPECT_EQ(payload, expected); } -// --- Combinations --- - TEST_F(CborShapeSerializerTest, StructureWithListAndMap) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -764,8 +746,6 @@ TEST_F(CborShapeSerializerTest, SparseList) { EXPECT_EQ(payload, expected); } -// --- Additional coverage --- - TEST_F(CborShapeSerializerTest, IntegerFourByte) { CborShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp index 24394aa95d15..01795b2558a7 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp @@ -18,8 +18,6 @@ using namespace smithy::schema; class JsonShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; -// --- Scalars --- - TEST_F(JsonShapeSerializerTest, EmptyStructure) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -141,8 +139,6 @@ TEST_F(JsonShapeSerializerTest, MultipleScalars) { EXPECT_NE(payload.find("\"c\":\"x\""), Aws::String::npos); } -// --- Nested structures --- - TEST_F(JsonShapeSerializerTest, NestedStructure) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -172,8 +168,6 @@ TEST_F(JsonShapeSerializerTest, DeeplyNestedStructure) { EXPECT_NE(s.GetPayload().GetResult().find("\"l1\":{\"l2\":{\"val\":99}}"), Aws::String::npos); } -// --- Lists --- - TEST_F(JsonShapeSerializerTest, ListOfStrings) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -247,8 +241,6 @@ TEST_F(JsonShapeSerializerTest, SparseList) { EXPECT_NE(s.GetPayload().GetResult().find("\"items\":[\"a\",null,\"b\"]"), Aws::String::npos); } -// --- Maps --- - TEST_F(JsonShapeSerializerTest, MapOfStrings) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -309,8 +301,6 @@ TEST_F(JsonShapeSerializerTest, SparseMap) { EXPECT_NE(payload.find("\"absent\":null"), Aws::String::npos); } -// --- Combinations --- - TEST_F(JsonShapeSerializerTest, StructureWithListAndMap) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -360,8 +350,6 @@ TEST_F(JsonShapeSerializerTest, MapContainingList) { EXPECT_NE(s.GetPayload().GetResult().find("\"data\":{\"nums\":[1,2]}"), Aws::String::npos); } -// --- JSON Escaping --- - TEST_F(JsonShapeSerializerTest, EscapesQuotesInString) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); @@ -415,13 +403,10 @@ TEST_F(JsonShapeSerializerTest, EscapesInMapKey) { EXPECT_NE(s.GetPayload().GetResult().find("\"key\\\"with\\\"quotes\":\"v\""), Aws::String::npos); } -// --- Depth limit --- - TEST_F(JsonShapeSerializerTest, MaxDepthEnforcement) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); auto nested = Schema::CreateMember("n", ShapeType::Structure); - // Nest well past MAX_DEPTH; the serializer stops and reports the error. std::function nest = [&](ShapeSerializer& ser, int remaining) { if (remaining <= 0) { return; @@ -435,8 +420,6 @@ TEST_F(JsonShapeSerializerTest, MaxDepthEnforcement) { EXPECT_NE(outcome.GetError().GetMessage().find("depth"), Aws::String::npos); } -// --- JsonNameTrait --- - TEST_F(JsonShapeSerializerTest, JsonNameOverridesMemberName) { JsonShapeSerializer s; auto root = Schema::StructureBuilder("Root").Build(); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp index 4a18d9496ef4..c925a7c06809 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp @@ -18,8 +18,6 @@ using namespace smithy::schema; class XmlShapeSerializerTest : public Aws::Testing::AwsCppSdkGTestSuite {}; -// --- Scalars --- - TEST_F(XmlShapeSerializerTest, EmptyStructure) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -141,8 +139,6 @@ TEST_F(XmlShapeSerializerTest, MultipleScalars) { EXPECT_NE(payload.find("x"), Aws::String::npos); } -// --- Nested structures --- - TEST_F(XmlShapeSerializerTest, NestedStructure) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -172,8 +168,6 @@ TEST_F(XmlShapeSerializerTest, DeeplyNestedStructure) { EXPECT_NE(s.GetPayload().GetResult().find("99"), Aws::String::npos); } -// --- Lists --- - TEST_F(XmlShapeSerializerTest, ListOfStrings) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -212,7 +206,6 @@ TEST_F(XmlShapeSerializerTest, EmptyList) { auto listMember = Schema::CreateMember("items", ShapeType::List); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteList(*listMember, 0, [](ShapeSerializer&) {}); }); s.WriteStruct(*root, rootStruct); - // Empty list still produces the wrapper element EXPECT_NE(s.GetPayload().GetResult().find(""), Aws::String::npos); } @@ -232,8 +225,6 @@ TEST_F(XmlShapeSerializerTest, ListOfStructures) { EXPECT_NE(s.GetPayload().GetResult().find("12"), Aws::String::npos); } -// --- Maps --- - TEST_F(XmlShapeSerializerTest, MapOfStrings) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -279,8 +270,6 @@ TEST_F(XmlShapeSerializerTest, MapOfStructures) { EXPECT_NE(s.GetPayload().GetResult().find("a1"), Aws::String::npos); } -// --- Combinations --- - TEST_F(XmlShapeSerializerTest, StructureWithListAndMap) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -308,8 +297,6 @@ TEST_F(XmlShapeSerializerTest, StructureWithListAndMap) { EXPECT_NE(payload.find("kv"), Aws::String::npos); } -// --- XML Escaping --- - TEST_F(XmlShapeSerializerTest, EscapesAmpersand) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -355,13 +342,10 @@ TEST_F(XmlShapeSerializerTest, EscapesMultipleSpecialChars) { EXPECT_NE(s.GetPayload().GetResult().find("x < 5 & y > 3"), Aws::String::npos); } -// --- Depth limit --- - TEST_F(XmlShapeSerializerTest, MaxDepthEnforcement) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); auto nested = Schema::CreateMember("n", ShapeType::Structure); - // Nest well past the depth limit; the serializer stops and reports the error. std::function nest = [&](ShapeSerializer& ser, int remaining) { if (remaining <= 0) { return; @@ -374,8 +358,6 @@ TEST_F(XmlShapeSerializerTest, MaxDepthEnforcement) { EXPECT_TRUE(hitLimit); } -// --- xmlName trait --- - TEST_F(XmlShapeSerializerTest, XmlNameOverridesMemberName) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -396,8 +378,6 @@ TEST_F(XmlShapeSerializerTest, XmlNameOnStructure) { EXPECT_NE(s.GetPayload().GetResult().find("42"), Aws::String::npos); } -// --- Flattened lists --- - TEST_F(XmlShapeSerializerTest, FlattenedListOfStrings) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -433,8 +413,6 @@ TEST_F(XmlShapeSerializerTest, FlattenedListWithXmlName) { EXPECT_NE(s.GetPayload().GetResult().find("xy"), Aws::String::npos); } -// --- Custom list item name --- - TEST_F(XmlShapeSerializerTest, CustomListItemName) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); @@ -450,8 +428,6 @@ TEST_F(XmlShapeSerializerTest, CustomListItemName) { EXPECT_NE(s.GetPayload().GetResult().find("ab"), Aws::String::npos); } -// --- Custom map entry/key/value names --- - TEST_F(XmlShapeSerializerTest, CustomMapNames) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); From deb889e5534c35253583c16dde74413767c27ee7 Mon Sep 17 00:00:00 2001 From: Snigdha Date: Tue, 18 Aug 2026 15:02:31 -0400 Subject: [PATCH 4/4] Applying clang-format --- .../client/schema/InterceptingSerializer.h | 6 +- .../smithy/client/schema/MapSerializer.h | 4 +- .../include/smithy/client/schema/Schema.h | 16 +- .../smithy/client/schema/SchemaBuilder.h | 6 +- .../smithy/client/schema/SerializableStruct.h | 6 +- .../smithy/client/schema/ShapeSerializer.h | 16 +- .../client/schema/SpecificShapeSerializer.h | 6 +- .../client/schema/CborShapeSerializer.cpp | 69 +++++++-- .../client/schema/JsonShapeSerializer.cpp | 138 ++++++++++++++---- .../source/smithy/client/schema/Schema.cpp | 76 +++------- .../client/schema/XmlShapeSerializer.cpp | 34 +++-- .../schema/CborShapeDeserializerTest.cpp | 6 +- .../client/schema/CborShapeSerializerTest.cpp | 9 +- .../client/schema/JsonShapeSerializerTest.cpp | 11 +- .../schema/SchemaSerializerTestHelpers.h | 3 +- .../client/schema/XmlShapeSerializerTest.cpp | 29 ++-- 16 files changed, 247 insertions(+), 188 deletions(-) diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h index 80bb7d86a310..fe05f4136a23 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/InterceptingSerializer.h @@ -8,10 +8,8 @@ namespace smithy { namespace schema { -// A ShapeSerializer that routes each write through Before()/After(). Before() -// returns the serializer that actually performs the write, so a subclass can -// act as a per-shape router (e.g. wrap a value in an XML element, then delegate -// the content to a value serializer). After() runs once the delegate returns. +// Routes each write through Before()/After(). Before() returns the serializer +// that performs the write; After() runs once it returns. class SMITHY_API InterceptingSerializer : public ShapeSerializer { public: void WriteStruct(const Schema& schema, const SerializableStruct& value) override { diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h index 08c469b35eed..80a106e07d27 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/MapSerializer.h @@ -10,9 +10,7 @@ namespace schema { class ShapeSerializer; -// Handed to the WriteMap consumer. Each entry writes its key, then the value -// through a nested consumer that receives the same underlying serializer, so map -// values can themselves be scalars, structs, lists, or maps. +// Handed to the WriteMap consumer; writes each entry's key then its value. class SMITHY_API MapSerializer { public: virtual ~MapSerializer() = default; diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h index fabcc97a85c3..531aaa7e8cb8 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/Schema.h @@ -39,19 +39,15 @@ enum class ShapeType : uint8_t { Service }; -// A single trait supplied at construction time. Schemas are immutable once -// built, so traits are attached through the factories and SchemaBuilder rather -// than mutated afterwards. +// A single trait supplied at construction time. struct TraitEntry { const TraitKeyBase& key; std::shared_ptr value; }; using TraitList = std::initializer_list; -// Abstract, immutable description of a shape. Concrete variants (scalar, member, -// structure/list/map/union root) live in the translation unit and are reached -// only through the factories below and SchemaBuilder. Serializers and -// deserializers hold a Schema only by const reference. +// Abstract, immutable description of a shape. Concrete variants are created +// through the factories below and SchemaBuilder. class SMITHY_API Schema { public: virtual ~Schema() = default; @@ -75,7 +71,7 @@ class SMITHY_API Schema { bool HasTrait(const TraitKeyBase& key) const { return m_traits.Has(key); } - // Scalar factories. No members, so no builder is needed. + // Scalar factories. static std::shared_ptr CreateBoolean(const char* id, TraitList traits = {}); static std::shared_ptr CreateByte(const char* id, TraitList traits = {}); static std::shared_ptr CreateShort(const char* id, TraitList traits = {}); @@ -93,11 +89,9 @@ class SMITHY_API Schema { static std::shared_ptr CreateDocument(const char* id, TraitList traits = {}); // Standalone member node targeting an (otherwise empty) shape of targetType. - // Convenience for the positional serializer/deserializer API, where a caller - // hands members one at a time rather than driving them off a parent shape. static std::shared_ptr CreateMember(const char* name, ShapeType targetType, TraitList traits = {}); - // Aggregate builders. Shapes that carry members are assembled incrementally. + // Aggregate builders. static SchemaBuilder StructureBuilder(const char* id, TraitList traits = {}); static SchemaBuilder UnionBuilder(const char* id, TraitList traits = {}); static SchemaBuilder ListBuilder(const char* id, TraitList traits = {}); diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h index f5fae323d225..75ac75342487 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/SchemaBuilder.h @@ -9,10 +9,8 @@ namespace smithy { namespace schema { -// Assembles a shape that carries members (structure, union, list, map). Members -// may target shapes that are already built, or other builders that are not yet -// built to describe recursive shapes. Once Build() is called the builder is -// spent. Move-only; obtained from Schema::StructureBuilder and friends. +// Assembles a shape that carries members (structure, union, list, map). Move-only; +// obtained from Schema::StructureBuilder and friends. class SMITHY_API SchemaBuilder final { public: ~SchemaBuilder(); diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h index c9fef8f1fd60..4ecb1e16667c 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/SerializableStruct.h @@ -8,10 +8,8 @@ namespace schema { class ShapeSerializer; -// Implemented by generated shapes. A shape knows its own Schema and how to write -// its members to a serializer; the wire format is decided entirely by which -// ShapeSerializer is passed in. This is the protocol-agnostic hook that lets one -// SerializeMembers() implementation produce JSON, XML, or CBOR. +// Implemented by generated shapes: knows its Schema and how to write its members +// to whichever ShapeSerializer is passed in. class SMITHY_API SerializableStruct { public: virtual ~SerializableStruct() = default; diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h index 831cb81de4b9..fbc79ab1925a 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/ShapeSerializer.h @@ -15,23 +15,15 @@ namespace schema { class SerializableStruct; class MapSerializer; -// Push-based serializer: the model drives serialization by calling these -// methods, and the serializer owns all wire-format structure (delimiters, -// element boundaries). Aggregates hand control back through a consumer callback -// so nesting is expressed by re-entrancy rather than begin/end bookkeeping. -// -// smithy-java parameterizes the list/map consumers on a caller-supplied state -// type to avoid capturing lambdas; C++ virtual methods cannot be templated, so -// the consumer is a std::function and any state is captured by the closure. +// Push-based serializer: the model drives serialization and the serializer owns +// all wire-format structure. Aggregates hand control back through a consumer. class SMITHY_API ShapeSerializer { public: virtual ~ShapeSerializer() = default; virtual void WriteStruct(const Schema& schema, const SerializableStruct& value) = 0; - virtual void WriteList(const Schema& schema, size_t size, - const std::function& consumer) = 0; - virtual void WriteMap(const Schema& schema, size_t size, - const std::function& consumer) = 0; + virtual void WriteList(const Schema& schema, size_t size, const std::function& consumer) = 0; + virtual void WriteMap(const Schema& schema, size_t size, const std::function& consumer) = 0; virtual void WriteBoolean(const Schema& schema, bool value) = 0; virtual void WriteInteger(const Schema& schema, int value) = 0; diff --git a/src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h b/src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h index 6d240b26c264..2e17c8fd4279 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/schema/SpecificShapeSerializer.h @@ -8,10 +8,8 @@ namespace smithy { namespace schema { -// A ShapeSerializer whose writes all default to no-ops. Subclasses override only -// the writes they support; unsupported writes are silently ignored (the SDK does -// not use exceptions). Also usable directly as a "null" serializer to discard a -// member that should not be written in the current pass. +// A ShapeSerializer whose writes default to no-ops; subclasses override only the +// writes they support. Also usable directly as a null/discard serializer. class SMITHY_API SpecificShapeSerializer : public ShapeSerializer { public: void WriteStruct(const Schema&, const SerializableStruct&) override {} diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp index fe68969fb74f..c5d19bb962b8 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/CborShapeSerializer.cpp @@ -71,19 +71,58 @@ class CborShapeSerializer::Impl final : public ShapeSerializer { public: explicit StructContext(Impl* outer) : m_outer(outer) {} - void WriteStruct(const Schema& s, const SerializableStruct& v) override { m_outer->WriteMemberKey(s); m_outer->WriteStruct(s, v); } - void WriteList(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteMemberKey(s); m_outer->WriteList(s, n, c); } - void WriteMap(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteMemberKey(s); m_outer->WriteMap(s, n, c); } - void WriteBoolean(const Schema& s, bool v) override { m_outer->WriteMemberKey(s); m_outer->WriteBoolean(s, v); } - void WriteInteger(const Schema& s, int v) override { m_outer->WriteMemberKey(s); m_outer->WriteInteger(s, v); } - void WriteLong(const Schema& s, int64_t v) override { m_outer->WriteMemberKey(s); m_outer->WriteLong(s, v); } - void WriteFloat(const Schema& s, float v) override { m_outer->WriteMemberKey(s); m_outer->WriteFloat(s, v); } - void WriteDouble(const Schema& s, double v) override { m_outer->WriteMemberKey(s); m_outer->WriteDouble(s, v); } - void WriteString(const Schema& s, const Aws::String& v) override { m_outer->WriteMemberKey(s); m_outer->WriteString(s, v); } - void WriteTimestamp(const Schema& s, const DateTime& v) override { m_outer->WriteMemberKey(s); m_outer->WriteTimestamp(s, v); } - void WriteBlob(const Schema& s, const ByteBuffer& v) override { m_outer->WriteMemberKey(s); m_outer->WriteBlob(s, v); } - void WriteEnum(const Schema& s, int v) override { m_outer->WriteMemberKey(s); m_outer->WriteEnum(s, v); } - void WriteNull(const Schema& s) override { m_outer->WriteMemberKey(s); m_outer->WriteNull(s); } + void WriteStruct(const Schema& s, const SerializableStruct& v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteStruct(s, v); + } + void WriteList(const Schema& s, size_t n, const std::function& c) override { + m_outer->WriteMemberKey(s); + m_outer->WriteList(s, n, c); + } + void WriteMap(const Schema& s, size_t n, const std::function& c) override { + m_outer->WriteMemberKey(s); + m_outer->WriteMap(s, n, c); + } + void WriteBoolean(const Schema& s, bool v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteBoolean(s, v); + } + void WriteInteger(const Schema& s, int v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteInteger(s, v); + } + void WriteLong(const Schema& s, int64_t v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteLong(s, v); + } + void WriteFloat(const Schema& s, float v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteFloat(s, v); + } + void WriteDouble(const Schema& s, double v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteDouble(s, v); + } + void WriteString(const Schema& s, const Aws::String& v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteString(s, v); + } + void WriteTimestamp(const Schema& s, const DateTime& v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteTimestamp(s, v); + } + void WriteBlob(const Schema& s, const ByteBuffer& v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteBlob(s, v); + } + void WriteEnum(const Schema& s, int v) override { + m_outer->WriteMemberKey(s); + m_outer->WriteEnum(s, v); + } + void WriteNull(const Schema& s) override { + m_outer->WriteMemberKey(s); + m_outer->WriteNull(s); + } private: Impl* m_outer; @@ -139,9 +178,7 @@ class CborShapeSerializer::Impl final : public ShapeSerializer { CborShapeSerializer::CborShapeSerializer() : m_impl(Aws::MakeUnique("CborShapeSerializer")) {} CborShapeSerializer::~CborShapeSerializer() = default; -void CborShapeSerializer::WriteStruct(const Schema& schema, const SerializableStruct& value) { - m_impl->WriteStruct(schema, value); -} +void CborShapeSerializer::WriteStruct(const Schema& schema, const SerializableStruct& value) { m_impl->WriteStruct(schema, value); } void CborShapeSerializer::WriteList(const Schema& schema, size_t size, const std::function& consumer) { m_impl->WriteList(schema, size, consumer); } diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp index 5c10d8343c45..1a7d6d8911fe 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/JsonShapeSerializer.cpp @@ -57,9 +57,7 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { void WriteFloat(const Schema&, float value) override { m_buf += StringUtils::to_string(value); } void WriteDouble(const Schema&, double value) override { m_buf += StringUtils::to_string(value); } void WriteString(const Schema&, const Aws::String& value) override { Aws::Schema::WriteQuotedJsonString(m_buf, value); } - void WriteTimestamp(const Schema&, const DateTime& value) override { - m_buf += StringUtils::to_string(value.SecondsWithMSPrecision()); - } + void WriteTimestamp(const Schema&, const DateTime& value) override { m_buf += StringUtils::to_string(value.SecondsWithMSPrecision()); } void WriteBlob(const Schema&, const ByteBuffer& value) override { m_buf += '"'; m_buf += HashingUtils::Base64Encode(value); @@ -102,19 +100,58 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { public: explicit StructContext(Impl* outer) : m_outer(outer) {} - void WriteStruct(const Schema& s, const SerializableStruct& v) override { m_outer->WriteFieldName(s); m_outer->WriteStruct(s, v); } - void WriteList(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteFieldName(s); m_outer->WriteList(s, n, c); } - void WriteMap(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteFieldName(s); m_outer->WriteMap(s, n, c); } - void WriteBoolean(const Schema& s, bool v) override { m_outer->WriteFieldName(s); m_outer->WriteBoolean(s, v); } - void WriteInteger(const Schema& s, int v) override { m_outer->WriteFieldName(s); m_outer->WriteInteger(s, v); } - void WriteLong(const Schema& s, int64_t v) override { m_outer->WriteFieldName(s); m_outer->WriteLong(s, v); } - void WriteFloat(const Schema& s, float v) override { m_outer->WriteFieldName(s); m_outer->WriteFloat(s, v); } - void WriteDouble(const Schema& s, double v) override { m_outer->WriteFieldName(s); m_outer->WriteDouble(s, v); } - void WriteString(const Schema& s, const Aws::String& v) override { m_outer->WriteFieldName(s); m_outer->WriteString(s, v); } - void WriteTimestamp(const Schema& s, const DateTime& v) override { m_outer->WriteFieldName(s); m_outer->WriteTimestamp(s, v); } - void WriteBlob(const Schema& s, const ByteBuffer& v) override { m_outer->WriteFieldName(s); m_outer->WriteBlob(s, v); } - void WriteEnum(const Schema& s, int v) override { m_outer->WriteFieldName(s); m_outer->WriteEnum(s, v); } - void WriteNull(const Schema& s) override { m_outer->WriteFieldName(s); m_outer->WriteNull(s); } + void WriteStruct(const Schema& s, const SerializableStruct& v) override { + m_outer->WriteFieldName(s); + m_outer->WriteStruct(s, v); + } + void WriteList(const Schema& s, size_t n, const std::function& c) override { + m_outer->WriteFieldName(s); + m_outer->WriteList(s, n, c); + } + void WriteMap(const Schema& s, size_t n, const std::function& c) override { + m_outer->WriteFieldName(s); + m_outer->WriteMap(s, n, c); + } + void WriteBoolean(const Schema& s, bool v) override { + m_outer->WriteFieldName(s); + m_outer->WriteBoolean(s, v); + } + void WriteInteger(const Schema& s, int v) override { + m_outer->WriteFieldName(s); + m_outer->WriteInteger(s, v); + } + void WriteLong(const Schema& s, int64_t v) override { + m_outer->WriteFieldName(s); + m_outer->WriteLong(s, v); + } + void WriteFloat(const Schema& s, float v) override { + m_outer->WriteFieldName(s); + m_outer->WriteFloat(s, v); + } + void WriteDouble(const Schema& s, double v) override { + m_outer->WriteFieldName(s); + m_outer->WriteDouble(s, v); + } + void WriteString(const Schema& s, const Aws::String& v) override { + m_outer->WriteFieldName(s); + m_outer->WriteString(s, v); + } + void WriteTimestamp(const Schema& s, const DateTime& v) override { + m_outer->WriteFieldName(s); + m_outer->WriteTimestamp(s, v); + } + void WriteBlob(const Schema& s, const ByteBuffer& v) override { + m_outer->WriteFieldName(s); + m_outer->WriteBlob(s, v); + } + void WriteEnum(const Schema& s, int v) override { + m_outer->WriteFieldName(s); + m_outer->WriteEnum(s, v); + } + void WriteNull(const Schema& s) override { + m_outer->WriteFieldName(s); + m_outer->WriteNull(s); + } private: Impl* m_outer; @@ -124,19 +161,58 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { public: explicit ListContext(Impl* outer) : m_outer(outer) {} - void WriteStruct(const Schema& s, const SerializableStruct& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteStruct(s, v); } - void WriteList(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteList(s, n, c); } - void WriteMap(const Schema& s, size_t n, const std::function& c) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteMap(s, n, c); } - void WriteBoolean(const Schema& s, bool v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteBoolean(s, v); } - void WriteInteger(const Schema& s, int v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteInteger(s, v); } - void WriteLong(const Schema& s, int64_t v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteLong(s, v); } - void WriteFloat(const Schema& s, float v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteFloat(s, v); } - void WriteDouble(const Schema& s, double v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteDouble(s, v); } - void WriteString(const Schema& s, const Aws::String& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteString(s, v); } - void WriteTimestamp(const Schema& s, const DateTime& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteTimestamp(s, v); } - void WriteBlob(const Schema& s, const ByteBuffer& v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteBlob(s, v); } - void WriteEnum(const Schema& s, int v) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteEnum(s, v); } - void WriteNull(const Schema& s) override { m_outer->WriteCommaIfNeeded(); m_outer->WriteNull(s); } + void WriteStruct(const Schema& s, const SerializableStruct& v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteStruct(s, v); + } + void WriteList(const Schema& s, size_t n, const std::function& c) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteList(s, n, c); + } + void WriteMap(const Schema& s, size_t n, const std::function& c) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteMap(s, n, c); + } + void WriteBoolean(const Schema& s, bool v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteBoolean(s, v); + } + void WriteInteger(const Schema& s, int v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteInteger(s, v); + } + void WriteLong(const Schema& s, int64_t v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteLong(s, v); + } + void WriteFloat(const Schema& s, float v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteFloat(s, v); + } + void WriteDouble(const Schema& s, double v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteDouble(s, v); + } + void WriteString(const Schema& s, const Aws::String& v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteString(s, v); + } + void WriteTimestamp(const Schema& s, const DateTime& v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteTimestamp(s, v); + } + void WriteBlob(const Schema& s, const ByteBuffer& v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteBlob(s, v); + } + void WriteEnum(const Schema& s, int v) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteEnum(s, v); + } + void WriteNull(const Schema& s) override { + m_outer->WriteCommaIfNeeded(); + m_outer->WriteNull(s); + } private: Impl* m_outer; @@ -185,9 +261,7 @@ class JsonShapeSerializer::Impl final : public ShapeSerializer { JsonShapeSerializer::JsonShapeSerializer() : m_impl(Aws::MakeUnique("JsonShapeSerializer")) {} JsonShapeSerializer::~JsonShapeSerializer() = default; -void JsonShapeSerializer::WriteStruct(const Schema& schema, const SerializableStruct& value) { - m_impl->WriteStruct(schema, value); -} +void JsonShapeSerializer::WriteStruct(const Schema& schema, const SerializableStruct& value) { m_impl->WriteStruct(schema, value); } void JsonShapeSerializer::WriteList(const Schema& schema, size_t size, const std::function& consumer) { m_impl->WriteList(schema, size, consumer); } diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp index e8c5929276bc..c26f40c568c1 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/Schema.cpp @@ -34,8 +34,7 @@ Aws::String MakeMemberId(const Aws::String& shapeId, const Aws::String& memberNa class ScalarSchema final : public Schema { public: - ScalarSchema(ShapeType type, const char* id, TraitList traits) - : Schema(traits), m_type(type), m_id(id) {} + ScalarSchema(ShapeType type, const char* id, TraitList traits) : Schema(traits), m_type(type), m_id(id) {} ShapeType GetType() const override { return m_type; } const char* GetId() const override { return m_id.c_str(); } @@ -47,14 +46,12 @@ class ScalarSchema final : public Schema { class MemberSchema final : public Schema { public: - MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::shared_ptr target, - TraitMap traits) + MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::shared_ptr target, TraitMap traits) : m_memberName(name), m_id(id), m_memberIndex(index), m_ownedTarget(std::move(target)) { m_traits = std::move(traits); } - MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::weak_ptr target, - TraitMap traits) + MemberSchema(const Aws::String& name, const Aws::String& id, int index, std::weak_ptr target, TraitMap traits) : m_memberName(name), m_id(id), m_memberIndex(index), m_weakTarget(std::move(target)) { m_traits = std::move(traits); } @@ -77,9 +74,7 @@ class MemberSchema final : public Schema { } private: - std::shared_ptr ResolvedTarget() const { - return m_ownedTarget ? m_ownedTarget : m_weakTarget.lock(); - } + std::shared_ptr ResolvedTarget() const { return m_ownedTarget ? m_ownedTarget : m_weakTarget.lock(); } Aws::String m_memberName; Aws::String m_id; @@ -90,9 +85,7 @@ class MemberSchema final : public Schema { class RootSchema final : public Schema { public: - RootSchema(ShapeType type, const Aws::String& id, TraitMap traits) : m_type(type), m_id(id) { - m_traits = std::move(traits); - } + RootSchema(ShapeType type, const Aws::String& id, TraitMap traits) : m_type(type), m_id(id) { m_traits = std::move(traits); } ShapeType GetType() const override { return m_type; } const char* GetId() const override { return m_id.c_str(); } @@ -150,45 +143,23 @@ std::shared_ptr MakeEmptyShape(ShapeType type, const char* id) { Schema::Schema(TraitList traits) : m_traits(ToTraitMap(traits)) {} -std::shared_ptr Schema::CreateBoolean(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Boolean, id, traits); -} -std::shared_ptr Schema::CreateByte(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Byte, id, traits); -} -std::shared_ptr Schema::CreateShort(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Short, id, traits); -} -std::shared_ptr Schema::CreateInteger(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Integer, id, traits); -} -std::shared_ptr Schema::CreateLong(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Long, id, traits); -} -std::shared_ptr Schema::CreateFloat(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Float, id, traits); -} -std::shared_ptr Schema::CreateDouble(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Double, id, traits); -} +std::shared_ptr Schema::CreateBoolean(const char* id, TraitList traits) { return MakeScalar(ShapeType::Boolean, id, traits); } +std::shared_ptr Schema::CreateByte(const char* id, TraitList traits) { return MakeScalar(ShapeType::Byte, id, traits); } +std::shared_ptr Schema::CreateShort(const char* id, TraitList traits) { return MakeScalar(ShapeType::Short, id, traits); } +std::shared_ptr Schema::CreateInteger(const char* id, TraitList traits) { return MakeScalar(ShapeType::Integer, id, traits); } +std::shared_ptr Schema::CreateLong(const char* id, TraitList traits) { return MakeScalar(ShapeType::Long, id, traits); } +std::shared_ptr Schema::CreateFloat(const char* id, TraitList traits) { return MakeScalar(ShapeType::Float, id, traits); } +std::shared_ptr Schema::CreateDouble(const char* id, TraitList traits) { return MakeScalar(ShapeType::Double, id, traits); } std::shared_ptr Schema::CreateBigInteger(const char* id, TraitList traits) { return MakeScalar(ShapeType::BigInteger, id, traits); } std::shared_ptr Schema::CreateBigDecimal(const char* id, TraitList traits) { return MakeScalar(ShapeType::BigDecimal, id, traits); } -std::shared_ptr Schema::CreateString(const char* id, TraitList traits) { - return MakeScalar(ShapeType::String, id, traits); -} -std::shared_ptr Schema::CreateEnum(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Enum, id, traits); -} -std::shared_ptr Schema::CreateIntEnum(const char* id, TraitList traits) { - return MakeScalar(ShapeType::IntEnum, id, traits); -} -std::shared_ptr Schema::CreateBlob(const char* id, TraitList traits) { - return MakeScalar(ShapeType::Blob, id, traits); -} +std::shared_ptr Schema::CreateString(const char* id, TraitList traits) { return MakeScalar(ShapeType::String, id, traits); } +std::shared_ptr Schema::CreateEnum(const char* id, TraitList traits) { return MakeScalar(ShapeType::Enum, id, traits); } +std::shared_ptr Schema::CreateIntEnum(const char* id, TraitList traits) { return MakeScalar(ShapeType::IntEnum, id, traits); } +std::shared_ptr Schema::CreateBlob(const char* id, TraitList traits) { return MakeScalar(ShapeType::Blob, id, traits); } std::shared_ptr Schema::CreateTimestamp(const char* id, TraitList traits) { return MakeScalar(ShapeType::Timestamp, id, traits); } @@ -197,14 +168,13 @@ std::shared_ptr Schema::CreateDocument(const char* id, TraitList t } std::shared_ptr Schema::CreateMember(const char* name, ShapeType targetType, TraitList traits) { - return Aws::MakeShared(SCHEMA_ALLOC_TAG, Aws::String(name), Aws::String(name), 0, - MakeEmptyShape(targetType, name), ToTraitMap(traits)); + return Aws::MakeShared(SCHEMA_ALLOC_TAG, Aws::String(name), Aws::String(name), 0, MakeEmptyShape(targetType, name), + ToTraitMap(traits)); } class SchemaBuilder::SchemaBuilderImpl { public: - SchemaBuilderImpl(ShapeType type, const char* id, TraitList traits) - : m_type(type), m_id(id), m_traits(ToTraitMap(traits)) {} + SchemaBuilderImpl(ShapeType type, const char* id, TraitList traits) : m_type(type), m_id(id), m_traits(ToTraitMap(traits)) {} struct PendingMember { Aws::String name; @@ -241,12 +211,12 @@ class SchemaBuilder::SchemaBuilderImpl { for (auto& pending : m_members) { std::shared_ptr member; if (pending.eagerTarget) { - member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, - pending.eagerTarget, pending.traits); + member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, pending.eagerTarget, + pending.traits); } else if (pending.deferredTarget != nullptr) { std::weak_ptr target = pending.deferredTarget->Build(); - member = Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, - target, pending.traits); + member = + Aws::MakeShared(SCHEMA_ALLOC_TAG, pending.name, MakeMemberId(m_id, pending.name), index, target, pending.traits); } shell->AddMember(member); ++index; diff --git a/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp b/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp index 72a3455dd80d..c683d89d7e2f 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/schema/XmlShapeSerializer.cpp @@ -35,11 +35,21 @@ void AppendXmlEscaped(Aws::String& buf, const Aws::String& value) { } if (i < len) { switch (data[i]) { - case '&': buf += "&"; break; - case '<': buf += "<"; break; - case '>': buf += ">"; break; - case '"': buf += """; break; - case '\'': buf += "'"; break; + case '&': + buf += "&"; + break; + case '<': + buf += "<"; + break; + case '>': + buf += ">"; + break; + case '"': + buf += """; + break; + case '\'': + buf += "'"; + break; } i++; } @@ -129,10 +139,7 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { class XmlMapEntrySerializer final : public MapSerializer { public: XmlMapEntrySerializer(Impl* outer, Aws::String entryName, Aws::String keyName, Aws::String valueName) - : m_outer(outer), - m_entryName(std::move(entryName)), - m_keyName(std::move(keyName)), - m_valueName(std::move(valueName)) {} + : m_outer(outer), m_entryName(std::move(entryName)), m_keyName(std::move(keyName)), m_valueName(std::move(valueName)) {} void WriteEntry(const Aws::String& key, const std::function& value) override; private: @@ -142,11 +149,7 @@ class XmlShapeSerializer::Impl final : public InterceptingSerializer { Aws::String m_valueName; }; - Impl() - : m_valueSerializer(this), - m_structElementSerializer(this), - m_structAttributeSerializer(this), - m_inlineAttributeSerializer(this) { + Impl() : m_valueSerializer(this), m_structElementSerializer(this), m_structAttributeSerializer(this), m_inlineAttributeSerializer(this) { m_buf.reserve(8192); } @@ -398,8 +401,7 @@ void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteDouble(const Sche void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteString(const Schema& schema, const Aws::String& value) { WriteAttr(schema, value); } -void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteTimestamp(const Schema& schema, - const Aws::Utils::DateTime& value) { +void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteTimestamp(const Schema& schema, const Aws::Utils::DateTime& value) { WriteAttr(schema, value.ToGmtString(Aws::Utils::DateFormat::ISO_8601)); } void XmlShapeSerializer::Impl::InlineAttributeSerializer::WriteEnum(const Schema& schema, int value) { diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp index 3e5cfd7e00dc..d4c6178901eb 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeDeserializerTest.cpp @@ -417,9 +417,9 @@ TEST_F(CborShapeDeserializerTest, SkipNestedUnknown) { auto known = Schema::CreateMember("known", ShapeType::Integer); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteStruct(*unknownStruct, LambdaStruct(*unknownStruct, [&](ShapeSerializer& ser2) { - ser2.WriteInteger(*a, 1); - ser2.WriteString(*b, "nested"); - })); + ser2.WriteInteger(*a, 1); + ser2.WriteString(*b, "nested"); + })); ser.WriteInteger(*known, 42); }); s.WriteStruct(*root, rootStruct); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp index ae4f3782ecbe..541944d3316c 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/CborShapeSerializerTest.cpp @@ -388,8 +388,8 @@ TEST_F(CborShapeSerializerTest, DeeplyNestedStructure) { auto leaf = Schema::CreateMember("v", ShapeType::Integer); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteStruct(*l1, LambdaStruct(*l1, [&](ShapeSerializer& ser2) { - ser2.WriteStruct(*l2, LambdaStruct(*l2, [&](ShapeSerializer& ser3) { ser3.WriteInteger(*leaf, 99); })); - })); + ser2.WriteStruct(*l2, LambdaStruct(*l2, [&](ShapeSerializer& ser3) { ser3.WriteInteger(*leaf, 99); })); + })); }); s.WriteStruct(*root, rootStruct); auto outcome = s.GetPayload(); @@ -647,9 +647,8 @@ TEST_F(CborShapeSerializerTest, StructureWithListAndMap) { LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*strMember, "hi"); ser.WriteList(*listMember, 1, [&](ShapeSerializer& lser) { lser.WriteString(*listElem, "t1"); }); - ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { - mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteInteger(*mapVal, 5); }); - }); + ser.WriteMap(*mapMember, 1, + [&](MapSerializer& mapSer) { mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteInteger(*mapVal, 5); }); }); }); s.WriteStruct(*root, rootStruct); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp index 01795b2558a7..add47ad7b794 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/JsonShapeSerializerTest.cpp @@ -159,10 +159,8 @@ TEST_F(JsonShapeSerializerTest, DeeplyNestedStructure) { auto leaf = Schema::CreateMember("val", ShapeType::Integer); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteStruct(*level1, LambdaStruct(*level1, [&](ShapeSerializer& ser2) { - ser2.WriteStruct(*level2, LambdaStruct(*level2, [&](ShapeSerializer& ser3) { - ser3.WriteInteger(*leaf, 99); - })); - })); + ser2.WriteStruct(*level2, LambdaStruct(*level2, [&](ShapeSerializer& ser3) { ser3.WriteInteger(*leaf, 99); })); + })); }); s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("\"l1\":{\"l2\":{\"val\":99}}"), Aws::String::npos); @@ -316,9 +314,8 @@ TEST_F(JsonShapeSerializerTest, StructureWithListAndMap) { lser.WriteString(*listElem, "t1"); lser.WriteString(*listElem, "t2"); }); - ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { - mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteString(*mapVal, "v"); }); - }); + ser.WriteMap(*mapMember, 1, + [&](MapSerializer& mapSer) { mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteString(*mapVal, "v"); }); }); }); s.WriteStruct(*root, rootStruct); diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h index 11281ca2a109..d8aa2b3f141b 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/SchemaSerializerTestHelpers.h @@ -20,8 +20,7 @@ namespace schema { // serializer.WriteStruct(*schema, s); class LambdaStruct final : public SerializableStruct { public: - LambdaStruct(const Schema& schema, std::function members) - : m_schema(schema), m_members(std::move(members)) {} + LambdaStruct(const Schema& schema, std::function members) : m_schema(schema), m_members(std::move(members)) {} const Schema& GetSchema() const override { return m_schema; } void SerializeMembers(ShapeSerializer& serializer) const override { diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp index c925a7c06809..d701bdd00819 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/schema/XmlShapeSerializerTest.cpp @@ -159,10 +159,8 @@ TEST_F(XmlShapeSerializerTest, DeeplyNestedStructure) { auto leaf = Schema::CreateMember("val", ShapeType::Integer); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteStruct(*level1, LambdaStruct(*level1, [&](ShapeSerializer& ser2) { - ser2.WriteStruct(*level2, LambdaStruct(*level2, [&](ShapeSerializer& ser3) { - ser3.WriteInteger(*leaf, 99); - })); - })); + ser2.WriteStruct(*level2, LambdaStruct(*level2, [&](ShapeSerializer& ser3) { ser3.WriteInteger(*leaf, 99); })); + })); }); s.WriteStruct(*root, rootStruct); EXPECT_NE(s.GetPayload().GetResult().find("99"), Aws::String::npos); @@ -285,9 +283,8 @@ TEST_F(XmlShapeSerializerTest, StructureWithListAndMap) { lser.WriteString(*listElem, "t1"); lser.WriteString(*listElem, "t2"); }); - ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) { - mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteString(*mapVal, "v"); }); - }); + ser.WriteMap(*mapMember, 1, + [&](MapSerializer& mapSer) { mapSer.WriteEntry("k", [&](ShapeSerializer& vser) { vser.WriteString(*mapVal, "v"); }); }); }); s.WriteStruct(*root, rootStruct); @@ -361,7 +358,8 @@ TEST_F(XmlShapeSerializerTest, MaxDepthEnforcement) { TEST_F(XmlShapeSerializerTest, XmlNameOverridesMemberName) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); - auto member = Schema::CreateMember("internalName", ShapeType::String, {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")}}); + auto member = Schema::CreateMember("internalName", ShapeType::String, + {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "ExternalName")}}); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteString(*member, "hello"); }); s.WriteStruct(*root, rootStruct); auto payload = s.GetPayload().GetResult(); @@ -381,7 +379,8 @@ TEST_F(XmlShapeSerializerTest, XmlNameOnStructure) { TEST_F(XmlShapeSerializerTest, FlattenedListOfStrings) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); - auto listMember = Schema::CreateMember("item", ShapeType::List, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}}); + auto listMember = + Schema::CreateMember("item", ShapeType::List, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}}); auto elem = Schema::CreateMember("member", ShapeType::String); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteList(*listMember, 3, [&](ShapeSerializer& lser) { @@ -401,7 +400,9 @@ TEST_F(XmlShapeSerializerTest, FlattenedListOfStrings) { TEST_F(XmlShapeSerializerTest, FlattenedListWithXmlName) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); - auto listMember = Schema::CreateMember("items", ShapeType::List, {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}, {XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Tag")}}); + auto listMember = Schema::CreateMember("items", ShapeType::List, + {{XmlFlattenedTrait::KEY(), Aws::MakeShared("Schema")}, + {XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Tag")}}); auto elem = Schema::CreateMember("member", ShapeType::String); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { @@ -416,7 +417,8 @@ TEST_F(XmlShapeSerializerTest, FlattenedListWithXmlName) { TEST_F(XmlShapeSerializerTest, CustomListItemName) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); - auto listMember = Schema::CreateMember("things", ShapeType::List, {{XmlListItemNameTrait::KEY(), Aws::MakeShared("Schema", "item")}}); + auto listMember = Schema::CreateMember("things", ShapeType::List, + {{XmlListItemNameTrait::KEY(), Aws::MakeShared("Schema", "item")}}); auto elem = Schema::CreateMember("member", ShapeType::String); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteList(*listMember, 2, [&](ShapeSerializer& lser) { @@ -431,7 +433,10 @@ TEST_F(XmlShapeSerializerTest, CustomListItemName) { TEST_F(XmlShapeSerializerTest, CustomMapNames) { XmlShapeSerializer s; auto root = Schema::StructureBuilder("Root", {{XmlNameTrait::KEY(), Aws::MakeShared("Schema", "Root")}}).Build(); - auto mapMember = Schema::CreateMember("tags", ShapeType::Map, {{XmlMapEntryNameTrait::KEY(), Aws::MakeShared("Schema", "item")}, {XmlMapKeyNameTrait::KEY(), Aws::MakeShared("Schema", "tagKey")}, {XmlMapValueNameTrait::KEY(), Aws::MakeShared("Schema", "tagValue")}}); + auto mapMember = Schema::CreateMember("tags", ShapeType::Map, + {{XmlMapEntryNameTrait::KEY(), Aws::MakeShared("Schema", "item")}, + {XmlMapKeyNameTrait::KEY(), Aws::MakeShared("Schema", "tagKey")}, + {XmlMapValueNameTrait::KEY(), Aws::MakeShared("Schema", "tagValue")}}); auto valSchema = Schema::CreateMember("value", ShapeType::String); LambdaStruct rootStruct(*root, [&](ShapeSerializer& ser) { ser.WriteMap(*mapMember, 1, [&](MapSerializer& mapSer) {