diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/json/JsonSerializer.h b/src/aws-cpp-sdk-core/include/aws/core/utils/json/JsonSerializer.h index 8b2ccc139bb5..ae98f6c18ff9 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/json/JsonSerializer.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/json/JsonSerializer.h @@ -94,6 +94,12 @@ namespace Aws JsonValue& WithString(const Aws::String& key, const Aws::String& value); JsonValue& WithString(const char* key, const Aws::String& value); + /** + * Adds a null value to the top level of this node with key. + */ + JsonValue& WithNull(const Aws::String& key); + JsonValue& WithNull(const char* key); + /** * Converts the current JSON node to a string. */ diff --git a/src/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp b/src/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp index 3cdcac1a8127..bbf44e5b57de 100644 --- a/src/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp +++ b/src/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp @@ -153,6 +153,23 @@ JsonValue& JsonValue::WithString(const Aws::String& key, const Aws::String& valu return WithString(key.c_str(), value); } +JsonValue& JsonValue::WithNull(const char* key) +{ + if (!m_value) + { + m_value = cJSON_AS4CPP_CreateObject(); + } + + const auto val = cJSON_AS4CPP_CreateNull(); + AddOrReplace(m_value, key, val); + return *this; +} + +JsonValue& JsonValue::WithNull(const Aws::String& key) +{ + return WithNull(key.c_str()); +} + JsonValue& JsonValue::AsString(const Aws::String& value) { Destroy(); diff --git a/tests/aws-cpp-sdk-core-tests/utils/json/JsonSerializerTest.cpp b/tests/aws-cpp-sdk-core-tests/utils/json/JsonSerializerTest.cpp index 12234707833f..00f313f9752d 100644 --- a/tests/aws-cpp-sdk-core-tests/utils/json/JsonSerializerTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/utils/json/JsonSerializerTest.cpp @@ -434,6 +434,39 @@ TEST_F(JsonSerializerTest, TestGetAllObjects) ASSERT_EQ(42, all["Key2"].AsInteger()); } +TEST_F(JsonSerializerTest, TestWithNull) +{ + JsonValue value; + value.WithString("Key1", "value1"); + value.WithNull("Key2"); + value.WithNull(Aws::String("Key3")); + value.WithInteger("Key4", 42); + + auto view = value.View(); + + ASSERT_TRUE(view.KeyExists("Key2")); + ASSERT_FALSE(view.ValueExists("Key2")); + ASSERT_TRUE(view.GetObject("Key2").IsNull()); + + ASSERT_TRUE(view.KeyExists("Key3")); + ASSERT_FALSE(view.ValueExists("Key3")); + ASSERT_TRUE(view.GetObject("Key3").IsNull()); + + ASSERT_STREQ("value1", view.GetString("Key1").c_str()); + ASSERT_EQ(42, view.GetInteger("Key4")); + + Aws::String serialized = view.WriteCompact(); + JsonValue reparsed(serialized); + ASSERT_TRUE(reparsed.WasParseSuccessful()); + auto reparsedView = reparsed.View(); + ASSERT_TRUE(reparsedView.KeyExists("Key2")); + ASSERT_FALSE(reparsedView.ValueExists("Key2")); + ASSERT_TRUE(reparsedView.GetObject("Key2").IsNull()); + ASSERT_TRUE(reparsedView.KeyExists("Key3")); + ASSERT_FALSE(reparsedView.ValueExists("Key3")); + ASSERT_TRUE(reparsedView.GetObject("Key3").IsNull()); +} + TEST_F(JsonSerializerTest, TestEquality) { auto input = R"({"AWS" : { diff --git a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/c2j/C2jShape.java b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/c2j/C2jShape.java index fdcde4780145..af13deb827bb 100644 --- a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/c2j/C2jShape.java +++ b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/c2j/C2jShape.java @@ -36,4 +36,5 @@ public class C2jShape { private boolean sensitive; private boolean document; private Map retryable; + private boolean sparse; } diff --git a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/Shape.java b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/Shape.java index fe953ce7a6b7..478056141298 100644 --- a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/Shape.java +++ b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/Shape.java @@ -63,6 +63,7 @@ public class Shape { private boolean overrideStreaming = false; private boolean requestCompressionRequired=false; private boolean requestCompressionRequiredGzip=false; + private boolean sparse=false; public boolean isMap() { return "map".equals(type.toLowerCase()); diff --git a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/cpp/CppViewHelper.java b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/cpp/CppViewHelper.java index 9c215a955ca3..21dcacd78429 100644 --- a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/cpp/CppViewHelper.java +++ b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/cpp/CppViewHelper.java @@ -26,6 +26,7 @@ public class CppViewHelper { private static final Map CORAL_TYPE_TO_CPP_TYPE_MAPPING = new HashMap<>(); + private static final Map CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING = new HashMap<>(); private static final Map CORAL_TYPE_TO_JSON_CPP_TYPE_MAPPING = new HashMap<>(); private static final Map CORAL_TYPE_TO_XML_CONVERSION_MAPPING = new HashMap<>(); private static final Map CORAL_TYPE_TO_DEFAULT_VALUES = new HashMap<>(); @@ -56,6 +57,22 @@ public class CppViewHelper { CORAL_TYPE_TO_CPP_TYPE_MAPPING.put("sensitive_double", "double"); CORAL_TYPE_TO_CPP_TYPE_MAPPING.put("sensitive_timestamp", "Aws::Utils::DateTime"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("long", "long long"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("integer", "int64_t"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("string", "Aws::String"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("timestamp", "Aws::Utils::DateTime"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("boolean", "bool"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("sensitive_boolean", "bool"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("double", "double"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("float", "double"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("blob", "Aws::Utils::ByteBuffer"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("sensitive_blob", "Aws::Utils::CryptoBuffer"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("sensitive_long", "long long"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("sensitive_integer", "int64_t"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("sensitive_float", "double"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("sensitive_double", "double"); + CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING.put("sensitive_timestamp", "Aws::Utils::DateTime"); + CORAL_TYPE_TO_JSON_CPP_TYPE_MAPPING.put("long", "Int64"); CORAL_TYPE_TO_JSON_CPP_TYPE_MAPPING.put("integer", "Integer"); CORAL_TYPE_TO_JSON_CPP_TYPE_MAPPING.put("string", "String"); @@ -225,12 +242,14 @@ else if(shape.isStructure() || shape.isEnum()) else if(shape.isList()) { String type = computeCppTypeInternal(shape.getListMember().getShape(), typeMapping); + type = shape.isSparse() ? String.format("Aws::Crt::Optional<%s>", type) : type; return String.format("Aws::Vector<%s>", type); } else if(shape.isMap()) { String key = computeCppTypeInternal(shape.getMapKey().getShape(), typeMapping); String value = computeCppTypeInternal(shape.getMapValue().getShape(), typeMapping); + value = shape.isSparse() ? String.format("Aws::Crt::Optional<%s>", value) : value; return String.format("Aws::Map<%s, %s>", key, value); } @@ -243,6 +262,16 @@ public static String computeCppType(Shape shape) { return computeCppTypeInternal(shape, CORAL_TYPE_TO_CPP_TYPE_MAPPING); } + public static String computeCborCppType(Shape shape) { + return computeCppTypeInternal(shape, CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING); + } + + public static String computeResultCppType(Shape shape, String protocol) { + return "smithy-rpc-v2-cbor".equals(protocol) + ? computeCppTypeInternal(shape, CORAL_TYPE_TO_CBOR_CPP_TYPE_MAPPING) + : computeCppTypeInternal(shape, CORAL_TYPE_TO_CPP_TYPE_MAPPING); + } + public static boolean isStreamingPayloadMember(Shape parent, String member) { if (!parent.getMembers().containsKey(member)) { throw new RuntimeException("Parent shape " + parent.getName() + @@ -275,6 +304,22 @@ public static String computeCppType(Shape parent, String member) { return computeCppType(childShape); } + public static String computeCborCppType(Shape parent, String member) { + if (!parent.getMembers().containsKey(member)) { + throw new RuntimeException("Parent shape " + parent.getName() + + " does not contain member key " + member); + } + ShapeMember shapeMember = parent.getMembers().get(member); + Shape childShape = shapeMember.getShape(); + + if (parent.getPayload() != null && parent.getPayload().equals(member) && parent.isResult()) { + if (shapeMember.isStreaming() || childShape.isBlob() || childShape.isString()) { + return "Aws::Utils::Stream::ResponseStream"; + } + } + return computeCborCppType(childShape); + } + public static String computeJsonCppType(Shape shape) { if(shape.isTimeStamp() && shape.getTimestampFormat() != null) { return CORAL_TYPE_TO_JSON_CPP_TYPE_MAPPING.get(shape.getTimestampFormat().toLowerCase()); @@ -387,6 +432,9 @@ public static Set computeHeaderIncludes(String projectName, Shape shape) headers.add(formatModelIncludeName(projectName, shapeInList)); } } + if (next.isSparse()) { + headers.add(""); + } if(!next.isPrimitive()) { if (next.isException() && !next.isModeledException()) { // C++ SDK code generator skips generating exceptions that can be expressed using diff --git a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/generators/cpp/CppProtocolTestGenerator.java b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/generators/cpp/CppProtocolTestGenerator.java index 43154aa5ad36..82c1746c8917 100644 --- a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/generators/cpp/CppProtocolTestGenerator.java +++ b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/generators/cpp/CppProtocolTestGenerator.java @@ -11,7 +11,6 @@ import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.Shape; import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.ShapeMember; -import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.cpp.CppCborViewHelper; import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.cpp.CppViewHelper; import com.amazonaws.util.awsclientgenerator.domainmodels.protocol_test.ProtocolTestModel; import com.amazonaws.util.awsclientgenerator.domainmodels.protocol_test.ProtocolTestSuite; @@ -115,11 +114,7 @@ protected final VelocityContext createContext() { context.put("testModel", testModel); context.put("input.encoding", StandardCharsets.UTF_8.name()); context.put("output.encoding", StandardCharsets.UTF_8.name()); - if(serviceModel.getMetadata().getProtocol().equals("smithy-rpc-v2-cbor")){ - context.put("CppViewHelper", CppCborViewHelper.class); - } else { - context.put("CppViewHelper", CppViewHelper.class); - } + context.put("CppViewHelper", CppViewHelper.class); return context; } diff --git a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java index 1838d2c7b59a..89ed4e05ab95 100644 --- a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java +++ b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java @@ -439,6 +439,10 @@ Shape convertShapeBasics(C2jShape c2jShape, String shapeName) { shape.setEvent(c2jShape.isEvent()); shape.setException(c2jShape.isException()); shape.setDocument(c2jShape.isDocument()); + shape.setSparse(c2jShape.isSparse()); + if (shape.isSparse() && !shape.isList() && !shape.isMap()) { + throw new SourceGenerationFailedException("The sparse trait is only applicable to list and map shapes, but was found on shape: " + shape.getName()); + } if (c2jShape.getXmlNamespace() != null) { XmlNamespace xmlns = new XmlNamespace(); @@ -850,6 +854,7 @@ Shape cloneShape(Shape shape) { cloned.setException(shape.isException()); cloned.setXmlNamespace(shape.getXmlNamespace()); cloned.setDocument(shape.isDocument()); + cloned.setSparse(shape.isSparse()); return cloned; } diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassHeaderMembersSource.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassHeaderMembersSource.vm index ba5ccc5bed0a..de43e1bd99a8 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassHeaderMembersSource.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassHeaderMembersSource.vm @@ -42,7 +42,11 @@ ${spaces}for(const auto& item : $memberVarName) ${spaces}{ ${spaces} ss << "${locationName}" << item.first; +#if($member.shape.sparse) + ${spaces} if(item.second.has_value()) { headers.emplace(ss.str(), item.second.value()); } +#else ${spaces} headers.emplace(ss.str(), item.second); +#end ${spaces} ss.str(""); ${spaces}} #elseif($member.shape.list) diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassMembersAndInlines.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassMembersAndInlines.vm index 19804fce8c45..5af591b469a0 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassMembersAndInlines.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ModelClassMembersAndInlines.vm @@ -111,6 +111,24 @@ #set($mapMember = $member.value.shape) #set($keyType = $CppViewHelper.computeCppType($mapMember.mapKey.shape)) #set($valueType = $CppViewHelper.computeCppType($mapMember.mapValue.shape)) +#if($mapMember.sparse) +#set($optionalValueType = "Aws::Crt::Optional<${valueType}>") +#if(!$mapMember.mapKey.shape.primitive && !$mapMember.mapKey.shape.enum && !$mapMember.mapValue.shape.primitive && !$mapMember.mapValue.shape.enum) +#set($keyTemplType = "${memberKeyWithFirstLetterCapitalized}KeyT") +#set($valueTemplType = "${memberKeyWithFirstLetterCapitalized}ValueT") + template + ${classNameRef} Add${memberKeyWithFirstLetterCapitalized}(${keyTemplType}&& key, ${valueTemplType}&& value) { + ${setHasBeenSet}${memberVariableName}.emplace(std::forward<${keyTemplType}>(key), std::forward<${valueTemplType}>(value)); return *this; + } +#else + ${inline}${classNameRef} Add${memberKeyWithFirstLetterCapitalized}(${keyType} key, ${valueType} value) { + ${setHasBeenSet}${memberVariableName}.emplace(key, value); return *this; + } +#end + ${inline}${classNameRef} Add${memberKeyWithFirstLetterCapitalized}(${keyType} key, ${optionalValueType} value) { + ${setHasBeenSet}${memberVariableName}.emplace(key, value); return *this; + } +#else #if(!$mapMember.mapKey.shape.primitive && !$mapMember.mapKey.shape.enum && !$mapMember.mapValue.shape.primitive && !$mapMember.mapValue.shape.enum) #set($keyTemplType = "${memberKeyWithFirstLetterCapitalized}KeyT") #set($valueTemplType = "${memberKeyWithFirstLetterCapitalized}ValueT") @@ -124,9 +142,21 @@ } #end #end +#end #if($member.value.shape.list) #set($listMember = $member.value.shape) #set($valueType = $CppViewHelper.computeCppType($listMember.listMember.shape)) +#if($listMember.sparse) +#set($optionalValueType = "Aws::Crt::Optional<${valueType}>") +#if(!$listMember.listMember.shape.primitive && !$listMember.listMember.shape.enum) +#set($valueTemplType = "${memberKeyWithFirstLetterCapitalized}T") + template + ${classNameRef} Add${memberKeyWithFirstLetterCapitalized}(${valueTemplType}&& value) { ${setHasBeenSet}${memberVariableName}.emplace_back(std::forward<${valueTemplType}>(value)); return *this; } +#else + ${inline}${classNameRef} Add${memberKeyWithFirstLetterCapitalized}(${valueType} value)$adderWithCopy +#end + ${inline}${classNameRef} Add${memberKeyWithFirstLetterCapitalized}(${optionalValueType} value)$adderWithCopy +#else #if(!$listMember.listMember.shape.primitive && !$listMember.listMember.shape.enum) #set($valueTemplType = "${memberKeyWithFirstLetterCapitalized}T") template @@ -134,6 +164,7 @@ #else ${inline}${classNameRef} Add${memberKeyWithFirstLetterCapitalized}(${valueType} value)$adderWithCopy #end +#end #end ///@} #end##if(!($CppViewHelper.isStreamingPayloadMember($shape, $member.key) && $shape.request)) diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeListValue.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeListValue.vm index 9a47a159e28b..6474947eaa89 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeListValue.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeListValue.vm @@ -1,7 +1,24 @@ +#set($parentListDepth = $recursionDepth - 1) +#if($member.shape.sparse) +{ + auto nullPeek_${recursionDepth} = decoder->PeekType(); + if (nullPeek_${recursionDepth}.has_value() && nullPeek_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::Null) { + decoder->ConsumeNextSingleElement(); +#if($parentListDepth == 0) + ${memberVarName}.emplace_back(); +#else + nestedList_${parentListDepth}.emplace_back(); +#end + } else { +#end #if($shapeMember.enum) auto ${containerVar} = decoder->PopNextTextVal(); if (${containerVar}.has_value()) { - ${value}.push_back(${shapeMember.name}Mapper::Get${shapeMember.name}ForName(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len))); +#if($parentListDepth == 0) + ${memberVarName}.push_back(${shapeMember.name}Mapper::Get${shapeMember.name}ForName(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len))); +#else + nestedList_${parentListDepth}.push_back(${shapeMember.name}Mapper::Get${shapeMember.name}ForName(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len))); +#end } #elseif($shapeMember.string) auto peekType_${recursionDepth} = decoder->PeekType(); @@ -9,7 +26,11 @@ if(peekType_${recursionDepth}.has_value()){ if (peekType_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::Text) { auto ${containerVar} = decoder->PopNextTextVal(); if (${containerVar}.has_value()) { - ${value}.push_back(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len)); +#if($parentListDepth == 0) + ${memberVarName}.push_back(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len)); +#else + nestedList_${parentListDepth}.push_back(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len)); +#end } } else { decoder->ConsumeNextSingleElement(); @@ -27,24 +48,40 @@ if(peekType_${recursionDepth}.has_value()){ ss_${recursionDepth} << Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len); } } - ${value}.push_back(ss_${recursionDepth}.str()); +#if($parentListDepth == 0) + ${memberVarName}.push_back(ss_${recursionDepth}.str()); +#else + nestedList_${parentListDepth}.push_back(ss_${recursionDepth}.str()); +#end ss_${recursionDepth}.clear(); } } #elseif($shapeMember.boolean) auto ${containerVar} = decoder->PopNextBooleanVal(); if (${containerVar}.has_value()) { - ${value}.push_back(${containerVar}.value()); +#if($parentListDepth == 0) + ${memberVarName}.push_back(${containerVar}.value()); +#else + nestedList_${parentListDepth}.push_back(${containerVar}.value()); +#end } #elseif($shapeMember.double) auto ${containerVar} = decoder->PopNextFloatVal(); if (${containerVar}.has_value()) { - ${value}.push_back(${containerVar}.value()); +#if($parentListDepth == 0) + ${memberVarName}.push_back(${containerVar}.value()); +#else + nestedList_${parentListDepth}.push_back(${containerVar}.value()); +#end } #elseif($shapeMember.float) auto ${containerVar} = decoder->PopNextFloatVal(); if (${containerVar}.has_value()) { - ${value}.push_back(${containerVar}.value()); +#if($parentListDepth == 0) + ${memberVarName}.push_back(${containerVar}.value()); +#else + nestedList_${parentListDepth}.push_back(${containerVar}.value()); +#end } #elseif($shapeMember.blob) auto peekType_${recursionDepth} = decoder->PeekType(); @@ -52,7 +89,11 @@ if(peekType_${recursionDepth}.has_value()){ if (peekType_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::Bytes) { auto ${containerVar} = decoder->PopNextBytesVal(); if (${containerVar}.has_value()) { - ${value}.push_back(Aws::Utils::ByteBuffer(${containerVar}.value().ptr, ${containerVar}.value().len)); +#if($parentListDepth == 0) + ${memberVarName}.push_back(Aws::Utils::ByteBuffer(${containerVar}.value().ptr, ${containerVar}.value().len)); +#else + nestedList_${parentListDepth}.push_back(Aws::Utils::ByteBuffer(${containerVar}.value().ptr, ${containerVar}.value().len)); +#end } } else { decoder->ConsumeNextSingleElement(); @@ -70,7 +111,11 @@ if(peekType_${recursionDepth}.has_value()){ ss_${recursionDepth} << Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len); } } - ${value}.push_back(Aws::Utils::ByteBuffer(ss_${recursionDepth}.str())); +#if($parentListDepth == 0) + ${memberVarName}.push_back(Aws::Utils::ByteBuffer(ss_${recursionDepth}.str())); +#else + nestedList_${parentListDepth}.push_back(Aws::Utils::ByteBuffer(ss_${recursionDepth}.str())); +#end ss_${recursionDepth}.clear(); } } @@ -85,23 +130,39 @@ if(peekType_${recursionDepth}.has_value()){ { auto ${containerVar} = decoder->PopNextFloatVal(); if (${containerVar}.has_value()) { - ${value}.push_back(Aws::Utils::DateTime(${containerVar}.value())); +#if($parentListDepth == 0) + ${memberVarName}.push_back(Aws::Utils::DateTime(${containerVar}.value())); +#else + nestedList_${parentListDepth}.push_back(Aws::Utils::DateTime(${containerVar}.value())); +#end } } else { auto ${containerVar} = decoder->PopNextUnsignedIntVal(); if (${containerVar}.has_value()) { - ${value}.push_back(Aws::Utils::DateTime(${containerVar}.value())); +#if($parentListDepth == 0) + ${memberVarName}.push_back(Aws::Utils::DateTime(${containerVar}.value())); +#else + nestedList_${parentListDepth}.push_back(Aws::Utils::DateTime(${containerVar}.value())); +#end } } } } #elseif($shapeMember.structure) #if($member.shape.isMutuallyReferencedWith($shape) || $member.shape.getName() == $shape.getName()) - ${value}.push_back(Aws::MakeShared<${shapeMember.name}>("${typeInfo.className}", ${shapeMember.name}(decoder))); +#if($parentListDepth == 0) + ${memberVarName}.push_back(Aws::MakeShared<${shapeMember.name}>("${typeInfo.className}", ${shapeMember.name}(decoder))); +#else + nestedList_${parentListDepth}.push_back(Aws::MakeShared<${shapeMember.name}>("${typeInfo.className}", ${shapeMember.name}(decoder))); +#end #else - ${value}.push_back(${shapeMember.name}(decoder)); +#if($parentListDepth == 0) + ${memberVarName}.push_back(${shapeMember.name}(decoder)); +#else + nestedList_${parentListDepth}.push_back(${shapeMember.name}(decoder)); +#end #end #elseif($shapeMember.list) #set($template.nestedShapeMember = $shapeMember.listMember.shape) @@ -145,7 +206,7 @@ if(peekType_${recursionDepth}.has_value()){ } #if($recursionDepth > 1) #set($parentDepth = $recursionDepth - 1) - nestedList_${parentDepth}.push_back(${value}); + nestedList_${parentDepth}.push_back(nestedList_${recursionDepth}); #else ${memberVarName}.push_back(nestedList_${recursionDepth}); #end @@ -191,7 +252,7 @@ if(peekType_${recursionDepth}.has_value()){ } #if($recursionDepth > 1) #set($parentDepth = $recursionDepth - 1) - nestedList_${parentDepth}.push_back(${value}); + nestedList_${parentDepth}.push_back(nestedMap_${recursionDepth}); #else ${memberVarName}.push_back(nestedMap_${recursionDepth}); #end @@ -202,13 +263,25 @@ if(peekType_${recursionDepth}.has_value()){ if(peekType_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::UInt){ auto ${containerVar} = decoder->PopNextUnsignedIntVal(); if (${containerVar}.has_value()) { - ${value}.push_back(static_cast(${containerVar}.value())); +#if($parentListDepth == 0) + ${memberVarName}.push_back(static_cast(${containerVar}.value())); +#else + nestedList_${parentListDepth}.push_back(static_cast(${containerVar}.value())); +#end } } else { auto ${containerVar} = decoder->PopNextNegativeIntVal(); if (${containerVar}.has_value()) { - ${value}.push_back(static_cast(1 - ${containerVar}.value())); +#if($parentListDepth == 0) + ${memberVarName}.push_back(static_cast(1 - ${containerVar}.value())); +#else + nestedList_${parentListDepth}.push_back(static_cast(1 - ${containerVar}.value())); +#end } } } -#end \ No newline at end of file +#end +#if($member.shape.sparse) + } // end else (non-null sparse element) +} +#end diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeMapValue.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeMapValue.vm index 29bd1683e133..c48255d584c0 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeMapValue.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborDecodeMapValue.vm @@ -1,10 +1,27 @@ +#set($parentMapDepth = $recursionDepth - 1) auto key_${recursionDepth} = decoder->PopNextTextVal(); if (key_${recursionDepth}.has_value()) { Aws::String keyStr_${recursionDepth} = Aws::String(reinterpret_cast(key_${recursionDepth}.value().ptr), key_${recursionDepth}.value().len); +#if($member.shape.sparse) + { + auto nullPeek_${recursionDepth} = decoder->PeekType(); + if (nullPeek_${recursionDepth}.has_value() && nullPeek_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::Null) { + decoder->ConsumeNextSingleElement(); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}]; +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}]; +#end + } else { +#end #if($shapeMember.enum) auto ${containerVar} = decoder->PopNextTextVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = ${shapeMember.name}Mapper::Get${shapeMember.name}ForName(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len)); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = ${shapeMember.name}Mapper::Get${shapeMember.name}ForName(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len)); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = ${shapeMember.name}Mapper::Get${shapeMember.name}ForName(Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len)); +#end } #elseif($shapeMember.string) auto peekType_${recursionDepth} = decoder->PeekType(); @@ -12,7 +29,11 @@ if(peekType_${recursionDepth}){ if (peekType_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::Text) { auto ${containerVar} = decoder->PopNextTextVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len); +#end } } else { decoder->ConsumeNextSingleElement(); @@ -30,24 +51,40 @@ if(peekType_${recursionDepth}){ ss_${recursionDepth} << Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len); } } - ${value}[keyStr_${recursionDepth}] = ss_${recursionDepth}.str(); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = ss_${recursionDepth}.str(); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = ss_${recursionDepth}.str(); +#end ss_${recursionDepth}.clear(); } } #elseif($shapeMember.boolean) auto ${containerVar} = decoder->PopNextBooleanVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#end } #elseif($shapeMember.double) auto ${containerVar} = decoder->PopNextFloatVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#end } #elseif($shapeMember.float) auto ${containerVar} = decoder->PopNextFloatVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = ${containerVar}.value(); +#end } #elseif($shapeMember.blob) auto peekType_${recursionDepth} = decoder->PeekType(); @@ -55,7 +92,11 @@ if(peekType_${recursionDepth}){ if (peekType_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::Bytes) { auto ${containerVar} = decoder->PopNextBytesVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = Aws::Utils::ByteBuffer(${containerVar}.value().ptr, ${containerVar}.value().len); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = Aws::Utils::ByteBuffer(${containerVar}.value().ptr, ${containerVar}.value().len); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = Aws::Utils::ByteBuffer(${containerVar}.value().ptr, ${containerVar}.value().len); +#end } } else { decoder->ConsumeNextSingleElement(); @@ -73,7 +114,11 @@ if(peekType_${recursionDepth}){ ss_${recursionDepth} << Aws::String(reinterpret_cast(${containerVar}.value().ptr), ${containerVar}.value().len); } } - ${value}[keyStr_${recursionDepth}] = Aws::Utils::ByteBuffer(ss_${recursionDepth}.str()); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = Aws::Utils::ByteBuffer(ss_${recursionDepth}.str()); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = Aws::Utils::ByteBuffer(ss_${recursionDepth}.str()); +#end ss_${recursionDepth}.clear(); } } @@ -88,23 +133,39 @@ if(peekType_${recursionDepth}){ { auto ${containerVar} = decoder->PopNextFloatVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = Aws::Utils::DateTime(${containerVar}.value()); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = Aws::Utils::DateTime(${containerVar}.value()); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = Aws::Utils::DateTime(${containerVar}.value()); +#end } } else { auto ${containerVar} = decoder->PopNextUnsignedIntVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = Aws::Utils::DateTime(${containerVar}.value()); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = Aws::Utils::DateTime(${containerVar}.value()); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = Aws::Utils::DateTime(${containerVar}.value()); +#end } } } } #elseif($shapeMember.structure) #if($member.shape.isMutuallyReferencedWith($shape) || $member.shape.getName() == $shape.getName()) - ${value}[keyStr_${recursionDepth}] = Aws::MakeShared<${shapeMember.name}>("${typeInfo.className}", ${shapeMember.name}(decoder)); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = Aws::MakeShared<${shapeMember.name}>("${typeInfo.className}", ${shapeMember.name}(decoder)); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = Aws::MakeShared<${shapeMember.name}>("${typeInfo.className}", ${shapeMember.name}(decoder)); +#end #else - ${value}[keyStr_${recursionDepth}] = ${shapeMember.name}(decoder); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = ${shapeMember.name}(decoder); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = ${shapeMember.name}(decoder); +#end #end #elseif($shapeMember.map) #set($template.nestedShapeMember = $shapeMember.mapValue.shape) @@ -144,9 +205,9 @@ if(peekType_${recursionDepth}){ #set($recursionDepth = $recursionDepth - 1) } } - #if($recursionDepth > 0) + #if($recursionDepth > 1) #set($parentDepth = $recursionDepth - 1) - nestedMap_${parentDepth}[keyStr_${recursionDepth}] = ${value}; + nestedMap_${parentDepth}[keyStr_${recursionDepth}] = nestedMap_${recursionDepth}; #else ${memberVarName}[keyStr_${recursionDepth}] = nestedMap_${recursionDepth}; #end @@ -193,7 +254,7 @@ if(peekType_${recursionDepth}){ } #if($recursionDepth > 1) #set($parentDepth = $recursionDepth - 1) - nestedMap_${parentDepth}[keyStr_${recursionDepth}] = ${value}; + nestedMap_${parentDepth}[keyStr_${recursionDepth}] = nestedList_${recursionDepth}; #else ${memberVarName}[keyStr_${recursionDepth}] = nestedList_${recursionDepth}; #end @@ -204,14 +265,26 @@ if(peekType_${recursionDepth}){ if(peekType_${recursionDepth}.value() == Aws::Crt::Cbor::CborType::UInt){ auto ${containerVar} = decoder->PopNextUnsignedIntVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = static_cast(${containerVar}.value()); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = static_cast(${containerVar}.value()); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = static_cast(${containerVar}.value()); +#end } } else { auto ${containerVar} = decoder->PopNextNegativeIntVal(); if (${containerVar}.has_value()) { - ${value}[keyStr_${recursionDepth}] = static_cast(1 - ${containerVar}.value()); +#if($parentMapDepth == 0) + ${memberVarName}[keyStr_${recursionDepth}] = static_cast(1 - ${containerVar}.value()); +#else + nestedMap_${parentMapDepth}[keyStr_${recursionDepth}] = static_cast(1 - ${containerVar}.value()); +#end } } } #end -} \ No newline at end of file +#if($member.shape.sparse) + } // end else (non-null sparse value) + } +#end +} diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm index 279d4d3dc78f..fd089e19d3d1 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm @@ -3,21 +3,43 @@ encoder.WriteText(Aws::Crt::ByteCursorFromCString(${shapeMember.name}Mapper::Get #elseif($shapeMember.list) encoder.WriteArrayStart(${value}.size()); for(const auto& item_${recursionDepth} : ${value}) { +#if($shapeMember.sparse) + if (!item_${recursionDepth}.has_value()) { encoder.WriteNull(); } else { + const auto& sparseItem_${recursionDepth} = *item_${recursionDepth}; +#set($value = "sparseItem_${recursionDepth}") #set($shapeMember = $shapeMember.listMember.shape) +#set($recursionDepth = $recursionDepth + 1) +#parse("com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm") +#set($recursionDepth = $recursionDepth - 1) + } +#else #set($value = "item_${recursionDepth}") +#set($shapeMember = $shapeMember.listMember.shape) #set($recursionDepth = $recursionDepth + 1) #parse("com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm") #set($recursionDepth = $recursionDepth - 1) +#end } #elseif($shapeMember.map) encoder.WriteMapStart(${value}.size()); for(const auto& item_${recursionDepth} : ${value}) { encoder.WriteText(Aws::Crt::ByteCursorFromCString(item_${recursionDepth}.first.c_str())); +#if($shapeMember.sparse) + if (!item_${recursionDepth}.second.has_value()) { encoder.WriteNull(); } else { + const auto& sparseVal_${recursionDepth} = *item_${recursionDepth}.second; +#set($value = "sparseVal_${recursionDepth}") #set($shapeMember = $shapeMember.mapValue.shape) +#set($recursionDepth = $recursionDepth + 1) +#parse("com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm") +#set($recursionDepth = $recursionDepth - 1) + } +#else #set($value = "item_${recursionDepth}.second") +#set($shapeMember = $shapeMember.mapValue.shape) #set($recursionDepth = $recursionDepth + 1) #parse("com/amazonaws/util/awsclientgenerator/velocity/cpp/cbor/CborEncodeValue.vm") #set($recursionDepth = $recursionDepth - 1) +#end } #elseif($shapeMember.blob) encoder.WriteBytes(Aws::Crt::ByteCursorFromCString(reinterpret_cast(${value}.GetUnderlyingData()))); @@ -40,4 +62,4 @@ encoder.WriteTag(1); //1 represents Epoch-based date/time. See https://www.rfc-e encoder.WriteUInt(${value}.Seconds()); #else (${value} >= 0) ? encoder.WriteUInt(${value}) : encoder.WriteNegInt(${value}); -#end \ No newline at end of file +#end diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonDeserializer.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonDeserializer.vm index 492de94d73bc..65d7afff006a 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonDeserializer.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonDeserializer.vm @@ -22,6 +22,13 @@ #end ${template.currentSpaces}for(auto& ${template.lowerCaseVarName}Item : ${template.lowerCaseVarName}JsonMap) ${template.currentSpaces}{ +#if($template.currentShape.sparse) + ${template.currentSpaces} if(${template.lowerCaseVarName}Item.second.IsNull()) + ${template.currentSpaces} { + ${template.currentSpaces} ${template.containerVar}[${template.lowerCaseVarName}Item.first]; + ${template.currentSpaces} continue; + ${template.currentSpaces} } +#end #if(!$template.currentShape.mapValue.shape.map && !$template.currentShape.mapValue.shape.list) #set($lvalue = "${template.containerVar}[${template.lowerCaseVarName}Item.first]") #set($rvalue = "${template.lowerCaseVarName}Item.second.As${CppViewHelper.computeJsonCppType($template.currentShape.mapValue.shape)}()") @@ -82,18 +89,41 @@ #end ${template.currentSpaces}for(unsigned ${template.lowerCaseVarName}Index = 0; ${template.lowerCaseVarName}Index < ${template.lowerCaseVarName}JsonList.GetLength(); ++${template.lowerCaseVarName}Index) ${template.currentSpaces}{ +#if($template.currentShape.sparse) + ${template.currentSpaces} if(${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].IsNull()) + ${template.currentSpaces} { + ${template.currentSpaces} ${template.containerVar}.emplace_back(); + ${template.currentSpaces} continue; + ${template.currentSpaces} } +#end #if(!$template.currentShape.listMember.shape.map && !$template.currentShape.listMember.shape.list) #set($template.atBottom = true) #if($template.currentShape.listMember.shape.enum) #set($enumName = $template.currentShape.listMember.shape.name) +#if($template.currentShape.sparse) + ${template.currentSpaces} ${template.containerVar}.emplace_back(${enumName}Mapper::Get${enumName}ForName(${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].AsString())); +#else ${template.currentSpaces} ${template.containerVar}.push_back(${enumName}Mapper::Get${enumName}ForName(${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].AsString())); +#end #elseif($template.currentShape.listMember.shape.blob) +#if($template.currentShape.sparse) + ${template.currentSpaces} ${template.containerVar}.emplace_back(HashingUtils::Base64Decode(${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}())); +#else ${template.currentSpaces} ${template.containerVar}.push_back(HashingUtils::Base64Decode(${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}())); +#end #elseif($template.currentShape.listMember.shape.timeStamp && $template.currentShape.listMember.shape.timestampFormat == "iso8601") +#if($template.currentShape.sparse) + ${template.currentSpaces} ${template.containerVar}.emplace_back(Aws::Utils::DateTime{${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}(), Aws::Utils::DateFormat::$CppViewHelper.computeTimestampFormatInQueryString($template.currentShape.listMember.shape)}); +#else ${template.currentSpaces} ${template.containerVar}.push_back(Aws::Utils::DateTime{${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}(), Aws::Utils::DateFormat::$CppViewHelper.computeTimestampFormatInQueryString($template.currentShape.listMember.shape)}); +#end +#else +#if($template.currentShape.sparse) + ${template.currentSpaces} ${template.containerVar}.emplace_back(${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}()); #else ${template.currentSpaces} ${template.containerVar}.push_back(${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}()); #end +#end #else #set($currentSpaces = $template.currentSpaces + " ") #set($currentShape = $template.currentShape.listMember.shape) diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonize.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonize.vm index 56c69280c330..6b102baaae5f 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonize.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/ModelInternalMapOrListJsonize.vm @@ -13,8 +13,31 @@ ${template.currentSpaces}JsonValue ${template.lowerCaseVarName}JsonMap; ${template.currentSpaces}for(auto& ${template.lowerCaseVarName}Item : ${template.containerVar}) ${template.currentSpaces}{ +#if($template.currentShape.sparse) + ${template.currentSpaces} if(!${template.lowerCaseVarName}Item.second.has_value()) + ${template.currentSpaces} { + ${template.currentSpaces} ${template.lowerCaseVarName}JsonMap.WithNull(${template.lowerCaseVarName}Item.first); + ${template.currentSpaces} continue; + ${template.currentSpaces} } +#end #if(!$template.currentShape.mapValue.shape.map && !$template.currentShape.mapValue.shape.list) #set($functionCall = "${template.lowerCaseVarName}JsonMap.With${CppViewHelper.computeJsonCppType($template.currentShape.mapValue.shape)}") +#if($template.currentShape.sparse) +#set($key = "${template.lowerCaseVarName}Item.first") +#set($value = "*${template.lowerCaseVarName}Item.second${CppViewHelper.computeJsonizeString($template.currentShape.mapValue.shape)}") +#if($template.currentShape.mapValue.shape.isBlob()) +#set($value = "HashingUtils::Base64Encode(*${template.lowerCaseVarName}Item.second${CppViewHelper.computeJsonizeString($template.currentShape.mapValue.shape)})") +#end +#if($template.currentShape.mapKey.shape.enum) +#set($enumName = $template.currentShape.mapKey.shape.name) +#set($key = "${enumName}Mapper::GetNameFor${enumName}(${template.lowerCaseVarName}Item.first)") +#end +#if($template.currentShape.mapValue.shape.enum) +#set($enumName = $template.currentShape.mapValue.shape.name) +#set($value = "${enumName}Mapper::GetNameFor${enumName}(*${template.lowerCaseVarName}Item.second)") +#set($functionCall = "${template.lowerCaseVarName}JsonMap.WithString") +#end +#else #set($key = "${template.lowerCaseVarName}Item.first") #set($value = "${template.lowerCaseVarName}Item.second${CppViewHelper.computeJsonizeString($template.currentShape.mapValue.shape)}") #if($template.currentShape.mapValue.shape.isBlob()) @@ -28,6 +51,7 @@ #set($enumName = $template.currentShape.mapValue.shape.name) #set($value = "${enumName}Mapper::GetNameFor${enumName}(${value})") #set($functionCall = "${template.lowerCaseVarName}JsonMap.WithString") +#end #end ${template.currentSpaces} ${functionCall}(${key}, ${value}); #set($template.atBottom = true) @@ -59,16 +83,35 @@ ${template.currentSpaces}${AwsArray} ${template.lowerCaseVarName}JsonList(${template.containerVar}.size()); ${template.currentSpaces}for(unsigned ${template.lowerCaseVarName}Index = 0; ${template.lowerCaseVarName}Index < ${template.lowerCaseVarName}JsonList.GetLength(); ++${template.lowerCaseVarName}Index) ${template.currentSpaces}{ +#if($template.currentShape.sparse) + ${template.currentSpaces} if(!${template.containerVar}[${template.lowerCaseVarName}Index].has_value()) + ${template.currentSpaces} { + ${template.currentSpaces} ${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].AsNull(); + ${template.currentSpaces} continue; + ${template.currentSpaces} } +#end #if(!$template.currentShape.listMember.shape.map && !$template.currentShape.listMember.shape.list) #set($template.atBottom = true) #if($template.currentShape.listMember.shape.enum) #set($enumName = $template.currentShape.listMember.shape.name) +#if($template.currentShape.sparse) + ${template.currentSpaces} ${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].AsString(${enumName}Mapper::GetNameFor${enumName}(*${template.containerVar}[${template.lowerCaseVarName}Index])); +#else ${template.currentSpaces} ${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].AsString(${enumName}Mapper::GetNameFor${enumName}(${template.containerVar}[${template.lowerCaseVarName}Index])); +#end #elseif($template.currentShape.listMember.shape.blob) +#if($template.currentShape.sparse) + ${template.currentSpaces} ${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}(HashingUtils::Base64Encode(*${template.containerVar}[${template.lowerCaseVarName}Index]${CppViewHelper.computeJsonizeString($template.currentShape.listMember.shape)})); +#else ${template.currentSpaces} ${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}(HashingUtils::Base64Encode(${template.containerVar}[${template.lowerCaseVarName}Index]${CppViewHelper.computeJsonizeString($template.currentShape.listMember.shape)})); +#end +#else +#if($template.currentShape.sparse) + ${template.currentSpaces} ${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}(*${template.containerVar}[${template.lowerCaseVarName}Index]${CppViewHelper.computeJsonizeString($template.currentShape.listMember.shape)}); #else ${template.currentSpaces} ${template.lowerCaseVarName}JsonList[${template.lowerCaseVarName}Index].As${CppViewHelper.computeJsonCppType($template.currentShape.listMember.shape)}(${template.containerVar}[${template.lowerCaseVarName}Index]${CppViewHelper.computeJsonizeString($template.currentShape.listMember.shape)}); #end +#end #else #set($currentSpaces = $template.currentSpaces + " ") #set($currentShape = $template.currentShape.listMember.shape) diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetListMacro.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetListMacro.vm index 98ee03ac1321..8b612eb14933 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetListMacro.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetListMacro.vm @@ -31,6 +31,18 @@ ${macro.spaces}{ ${macro.spaces}} #end##foreach #else## not (list || map || structure) +#if($listShape.sparse) +#set($macro.fieldAdder = "Add${CppViewHelper.capitalizeFirstChar($testInputParam.key)}") +#foreach($arrayItem in $testInputParam.value) +#if($arrayItem == "null") +${macro.spaces}${dstObject}.${macro.fieldAdder}(Aws::Crt::Optional<$CppViewHelper.computeCppType($macro.listMemberShape)>{}); +#elseif($macro.listMemberShape.list || $macro.listMemberShape.map) +${macro.spaces}${dstObject}.${macro.fieldAdder}($CppViewHelper.computeCppType($macro.listMemberShape)#SerializeSingleParameterMacro($macro.listMemberShape, $arrayItem)); +#else +${macro.spaces}${dstObject}.${macro.fieldAdder}(#SerializeSingleParameterMacro($macro.listMemberShape, $arrayItem)); +#end +#end +#else #set($macro.fieldSetter = "Set${CppViewHelper.capitalizeFirstChar($testInputParam.key)}") #set($macro.listResult="{") #foreach($arrayItem in $testInputParam.value) @@ -39,5 +51,6 @@ ${macro.spaces}} #end #set($macro.listResult=$macro.listResult + "}") ${spaces}${dstObject}.${macro.fieldSetter}($macro.listResult); +#end #end##(list || map || structure) #end##macro SetListMacro \ No newline at end of file diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetMapMacro.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetMapMacro.vm index 809e27ce2377..8b3d7287b5c0 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetMapMacro.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/request/SetMapMacro.vm @@ -29,6 +29,18 @@ ${macro.spaces}} #break #end ###----- the map value is not nested structure or document +#if($mapShape.sparse) +#set($macro.fieldAdder = "Add${CppViewHelper.capitalizeFirstChar($testInputParam.key)}") +#foreach($mapItem in $testInputParam.value.fields()) +#if($mapItem.value == "null") +${macro.spaces}${dstObject}.${macro.fieldAdder}("$mapItem.key", Aws::Crt::Optional<$CppViewHelper.computeCppType($mapShape.mapValue.shape)>{}); +#elseif($mapShape.mapValue.shape.list || $mapShape.mapValue.shape.map) +${macro.spaces}${dstObject}.${macro.fieldAdder}("$mapItem.key", $CppViewHelper.computeCppType($mapShape.mapValue.shape)#SerializeSingleParameterMacro($mapShape.mapValue.shape, $mapItem.value)); +#else +${macro.spaces}${dstObject}.${macro.fieldAdder}("$mapItem.key", #SerializeSingleParameterMacro($mapShape.mapValue.shape, $mapItem.value)); +#end +#end +#else #set($macro.mapResult="{") #foreach($mapItem in $testInputParam.value.fields()) #set($macro.mapItem="{" + '"' + "$mapItem.key" + '"' + ", ") @@ -38,4 +50,5 @@ ${macro.spaces}} #end #set($macro.mapResult=$macro.mapResult + "}") ${spaces}${dstObject}.${macro.fieldSetter}($macro.mapResult); +#end #end##macro SetMapMacro \ No newline at end of file diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateListMacro.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateListMacro.vm index 7c9070a317bd..7c9266760a49 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateListMacro.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateListMacro.vm @@ -23,17 +23,34 @@ #set($macro.listItemVarName = "${dstObject}${CppViewHelper.capitalizeFirstChar(${CppViewHelper.computeVariableName($testValidateParam.key)})}Item") #end #if($macro.listMemberShape.list || $macro.listMemberShape.map || $macro.listMemberShape.structure) +#if($listShape.sparse && $macro.listMemberShape.structure) +${macro.spaces}const Aws::Vector>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}; +${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.listItemVarName}.size()); +#foreach($arrayItem in $testValidateParamVal) +${macro.spaces}{ +#if($arrayItem.isNull()) + ${macro.spaces}EXPECT_FALSE(${macro.listItemVarName}.at(${foreach.index}).has_value()); +#else + ${macro.spaces}EXPECT_TRUE(${macro.listItemVarName}.at(${foreach.index}).has_value()); + ${macro.spaces}const ${macro.listMemberShape.name}& ${macro.listItemVarName}Ref = *${macro.listItemVarName}.at(${foreach.index}); +#foreach($innerParam in $arrayItem.fields()) +#ValidateParamsMacro("${macro.spaces} " "${macro.listItemVarName}Ref" $macro.listMemberShape $innerParam) +#end +#end +${macro.spaces}} +#end +#else ${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${dstObject}.${macro.fieldGetter}.size()); #foreach($arrayItem in $testValidateParamVal) ${macro.spaces}{ #if($macro.listMemberShape.list) - ${macro.spaces}const Aws::Vector<$CppViewHelper.computeCppType($macro.listMemberShape.listMember.shape)>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}.at(${foreach.index}); + ${macro.spaces}const Aws::Vector<$CppViewHelper.computeResultCppType($macro.listMemberShape.listMember.shape, $serviceModel.metadata.protocol)>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}.at(${foreach.index}); ${macro.spaces}EXPECT_EQ(${arrayItem.size()}U, ${macro.listItemVarName}.size()); #foreach($innerListEl in $arrayItem) ${macro.spaces}EXPECT_EQ(#ValidateSingleParameterMacro($macro.listMemberShape.listMember.shape, $innerListEl), ${macro.listItemVarName}.at(${foreach.index})); #end #elseif($macro.listMemberShape.map) - ${macro.spaces}const Aws::Map<$CppViewHelper.computeCppType($macro.listMemberShape.mapKey.shape), $CppViewHelper.computeCppType($macro.listMemberShape.mapValue.shape)>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}.at(${foreach.index}); + ${macro.spaces}const Aws::Map<$CppViewHelper.computeResultCppType($macro.listMemberShape.mapKey.shape, $serviceModel.metadata.protocol), $CppViewHelper.computeResultCppType($macro.listMemberShape.mapValue.shape, $serviceModel.metadata.protocol)>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}.at(${foreach.index}); ${macro.spaces}EXPECT_EQ(${arrayItem.size()}U, ${macro.listItemVarName}.size()); #foreach($innerMapEl in $arrayItem.fields()) ${macro.spaces}EXPECT_TRUE(${macro.listItemVarName}.find("$innerMapEl.key") != ${macro.listItemVarName}.end()); @@ -47,11 +64,25 @@ ${macro.spaces}{ #end##list ${macro.spaces}} #end##foreach +#end #else## not (list || map || structure) -${macro.spaces}const Aws::Vector<$CppViewHelper.computeCppType($macro.listMemberShape)>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}; +#if($listShape.sparse) +${macro.spaces}const Aws::Vector>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}; +${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.listItemVarName}.size()); +#foreach($arrayItem in $testValidateParamVal) +#if($arrayItem.isNull()) +${macro.spaces}EXPECT_FALSE(${macro.listItemVarName}.at(${foreach.index}).has_value()); +#else +${macro.spaces}EXPECT_TRUE(${macro.listItemVarName}.at(${foreach.index}).has_value()); +${macro.spaces}EXPECT_EQ(#ValidateSingleParameterMacro($macro.listMemberShape, $arrayItem), *${macro.listItemVarName}.at(${foreach.index})); +#end +#end +#else +${macro.spaces}const Aws::Vector<$CppViewHelper.computeResultCppType($macro.listMemberShape, $serviceModel.metadata.protocol)>& $macro.listItemVarName = ${dstObject}.${macro.fieldGetter}; ${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.listItemVarName}.size()); #foreach($arrayItem in $testValidateParamVal) ${macro.spaces}EXPECT_EQ(#ValidateSingleParameterMacro($macro.listMemberShape, $arrayItem), ${macro.listItemVarName}.at(${foreach.index})); #end +#end##sparse #end##(list || map || structure) #end##macro ValidateListMacro \ No newline at end of file diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateMapMacro.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateMapMacro.vm index 845748270b70..d2eb9830fb02 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateMapMacro.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateMapMacro.vm @@ -17,7 +17,7 @@ #end #set($macro.spaces = $spaces) #if($mapShape.mapValue.shape.document) -${macro.spaces}const Aws::Map<$CppViewHelper.computeCppType($mapShape.mapKey.shape), $CppViewHelper.computeCppType($mapShape.mapValue.shape)>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; +${macro.spaces}const Aws::Map<$CppViewHelper.computeResultCppType($mapShape.mapKey.shape, $serviceModel.metadata.protocol), $CppViewHelper.computeResultCppType($mapShape.mapValue.shape, $serviceModel.metadata.protocol)>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; ${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.mapVarName}.size()); #foreach($mapItem in $testValidateParamVal.fields()) ${macro.spaces}EXPECT_STREQ(R"j(${mapItem.value})j", ${macro.mapVarName}.at("$mapItem.key").View().WriteCompact().c_str()); @@ -25,21 +25,53 @@ ${macro.spaces}EXPECT_STREQ(R"j(${mapItem.value})j", ${macro.mapVarName}.at("$ma #break #end #if($mapShape.mapValue.shape.structure) -${macro.spaces}const Aws::Map<$CppViewHelper.computeCppType($mapShape.mapKey.shape), $CppViewHelper.computeCppType($mapShape.mapValue.shape)>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; +#if($mapShape.sparse) +${macro.spaces}const Aws::Map<$CppViewHelper.computeResultCppType($mapShape.mapKey.shape, $serviceModel.metadata.protocol), Aws::Crt::Optional<$CppViewHelper.computeResultCppType($mapShape.mapValue.shape, $serviceModel.metadata.protocol)>>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; ${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.mapVarName}.size()); #foreach($mapItem in $testValidateParamVal.fields()) ${macro.spaces}{ ${macro.spaces}EXPECT_TRUE(${macro.mapVarName}.find("$mapItem.key") != ${macro.mapVarName}.end()); - ${macro.spaces}const $CppViewHelper.computeCppType($mapShape.mapValue.shape)& $macro.mapItemVarName = ${macro.mapVarName}.at("$mapItem.key"); +#if($mapItem.value.isNull()) + ${macro.spaces}EXPECT_FALSE(${macro.mapVarName}.at("$mapItem.key").has_value()); +#else + ${macro.spaces}EXPECT_TRUE(${macro.mapVarName}.at("$mapItem.key").has_value()); + ${macro.spaces}const $CppViewHelper.computeResultCppType($mapShape.mapValue.shape, $serviceModel.metadata.protocol)& $macro.mapItemVarName = *${macro.mapVarName}.at("$mapItem.key"); +#foreach($innerParam in $mapItem.value.fields()) +#ValidateParamsMacro("${macro.spaces} " $macro.mapItemVarName $mapShape.mapValue.shape $innerParam) +#end +#end +${macro.spaces}} +#end +#else +${macro.spaces}const Aws::Map<$CppViewHelper.computeResultCppType($mapShape.mapKey.shape, $serviceModel.metadata.protocol), $CppViewHelper.computeResultCppType($mapShape.mapValue.shape, $serviceModel.metadata.protocol)>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; +${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.mapVarName}.size()); +#foreach($mapItem in $testValidateParamVal.fields()) +${macro.spaces}{ + ${macro.spaces}EXPECT_TRUE(${macro.mapVarName}.find("$mapItem.key") != ${macro.mapVarName}.end()); + ${macro.spaces}const $CppViewHelper.computeResultCppType($mapShape.mapValue.shape, $serviceModel.metadata.protocol)& $macro.mapItemVarName = ${macro.mapVarName}.at("$mapItem.key"); #foreach($innerParam in $mapItem.value.fields()) #ValidateParamsMacro("${macro.spaces} " $macro.mapItemVarName $mapShape.mapValue.shape $innerParam) #end ${macro.spaces}} #end +#end #break #end ###----- the map value is not nested structure or document -${macro.spaces}const Aws::Map<$CppViewHelper.computeCppType($mapShape.mapKey.shape), $CppViewHelper.computeCppType($mapShape.mapValue.shape)>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; +#if($mapShape.sparse) +${macro.spaces}const Aws::Map<$CppViewHelper.computeResultCppType($mapShape.mapKey.shape, $serviceModel.metadata.protocol), Aws::Crt::Optional<$CppViewHelper.computeResultCppType($mapShape.mapValue.shape, $serviceModel.metadata.protocol)>>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; +${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.mapVarName}.size()); +#foreach($mapItem in $testValidateParamVal.fields()) +${macro.spaces}EXPECT_TRUE(${macro.mapVarName}.find("$mapItem.key") != ${macro.mapVarName}.end()); +#if($mapItem.value.isNull()) +${macro.spaces}EXPECT_FALSE(${macro.mapVarName}.at("$mapItem.key").has_value()); +#else +${macro.spaces}EXPECT_TRUE(${macro.mapVarName}.at("$mapItem.key").has_value()); +${macro.spaces}EXPECT_EQ(#ValidateSingleParameterMacro($mapShape.mapValue.shape, $mapItem.value), *${macro.mapVarName}.at("$mapItem.key")); +#end +#end +#else +${macro.spaces}const Aws::Map<$CppViewHelper.computeResultCppType($mapShape.mapKey.shape, $serviceModel.metadata.protocol), $CppViewHelper.computeResultCppType($mapShape.mapValue.shape, $serviceModel.metadata.protocol)>& $macro.mapVarName = ${dstObject}.${macro.fieldGetter}; ${macro.spaces}EXPECT_EQ(${testValidateParamVal.size()}U, ${macro.mapVarName}.size()); #foreach($mapItem in $testValidateParamVal.fields()) ${macro.spaces}EXPECT_TRUE(${macro.mapVarName}.find("$mapItem.key") != ${macro.mapVarName}.end()); @@ -48,4 +80,5 @@ ${macro.spaces}EXPECT_TRUE(${macro.mapVarName}.find("$mapItem.key") != ${macro.m #set($macro.var = $macro.mapItemVarName) #ValidateSingleVariableMacro($macro.spaces, $mapShape.mapValue.shape, $mapItem.value, $macro.parentVarName, $macro.getter, $macro.var) #end +#end##sparse #end##macro ValidateMapMacro \ No newline at end of file diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateSingleParameterMacro.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateSingleParameterMacro.vm index 1e5ee6442cd1..7f3d0c0d6a5f 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateSingleParameterMacro.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/protocoltests/result/ValidateSingleParameterMacro.vm @@ -38,15 +38,14 @@ Aws::Utils::DateTime(static_cast(${value}))## #elseif($shape.enum) ${shape.name}Mapper::Get${shape.name}ForName(R"e(${value.asText()})e")## #elseif($shape.list) -#set($macro.listResult="Aws::Vector<$CppViewHelper.computeCppType($shape)>({") -#foreach($listItem in $value) +#set($macro.listResult="Aws::Vector<$CppViewHelper.computeResultCppType($shape.listMember.shape, $serviceModel.metadata.protocol)>({")#foreach($listItem in $value) #set($macro.listResult=$macro.listResult + "#ValidateSingleParameterMacro($shape.listMember.shape, $listItem)") #if($foreach.hasNext)#set($macro.listResult=$macro.listResult + ", ")#end #end #set($macro.listResult=$macro.listResult + "})") $macro.listResult## #elseif($shape.map) -#set($macro.mapResult="Aws::Map<$CppViewHelper.computeCppType($shape.mapKey.shape), $CppViewHelper.computeCppType($shape.mapValue.shape)>({") +#set($macro.mapResult="Aws::Map<$CppViewHelper.computeResultCppType($shape.mapKey.shape, $serviceModel.metadata.protocol), $CppViewHelper.computeResultCppType($shape.mapValue.shape, $serviceModel.metadata.protocol)>({") #foreach($mapItem in $value.fields()) #set($macro.mapItem="{" + '"' + "$mapItem.key" + '"' + ", ") #set($macro.mapItem=$macro.mapItem + "#ValidateSingleParameterMacro($shape.mapValue.shape, $mapItem.value)" + "}") diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryListElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryListElement.vm index 03c8ca9e6bab..f4e686065506 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryListElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryListElement.vm @@ -45,10 +45,23 @@ #end #end #if($member.shape.listMember.shape.structure) +#if($member.shape.sparse) + ${macro.spaces} if(item.has_value()) { + ${macro.spaces} item.value().OutputToStream(ss, "${macro.listLocation}.", ${varName}Count, ""); + ${macro.spaces} } +#else ${macro.spaces} item.OutputToStream(ss, "${macro.listLocation}.", ${varName}Count, ""); +#end +#else +#if($member.shape.sparse) + ${macro.spaces} if(item.has_value()) { + ${macro.spaces} ss << "${macro.listLocation}." << ${varName}Count << "=" + ${macro.spaces} << #serializeQuerySingleElementToText($macro.spaces, $member.shape.listMember, "item.value()") << "&"; + ${macro.spaces} } #else ${macro.spaces} ss << "${macro.listLocation}." << ${varName}Count << "=" ${macro.spaces} << #serializeQuerySingleElementToText($macro.spaces, $member.shape.listMember, "item") << "&"; +#end #end ${macro.spaces} ${varName}Count++; ${macro.spaces}} diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryMapElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryMapElement.vm index 751eca7c55ab..f797d4abb67a 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryMapElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeRequestQueryMapElement.vm @@ -35,14 +35,27 @@ #end ## --- MAP VALUE --- #if($member.shape.mapValue.shape.structure) +#if($member.shape.sparse) + ${spaces} if(item.second.has_value()) { + ${spaces} item.second.value().OutputToStream(ss, "${macro.mapLocationName}.", ${macro.varName}Count, ".${macro.valueLocationName}"); + ${spaces} } +#else ${spaces} item.second.OutputToStream(ss, "${macro.mapLocationName}.", ${macro.varName}Count, ".${macro.valueLocationName}"); +#end #else #set($macro.equals='=') #if($member.shape.mapValue.shape.list || $member.shape.mapValue.shape.map) #set($macro.equals='') #end +#if($member.shape.sparse) + ${spaces} if(item.second.has_value()) { + ${spaces} ss << "${macro.mapLocationName}." << ${macro.varName}Count << ".${macro.valueLocationName}${macro.equals}" + ${spaces} << #serializeQuerySingleElementToText($spaces, $member.shape.mapValue, "item.second.value()") << "&"; + ${spaces} } +#else ${spaces} ss << "${macro.mapLocationName}." << ${macro.varName}Count << ".${macro.valueLocationName}${macro.equals}" ${spaces} << #serializeQuerySingleElementToText($spaces, $member.shape.mapValue, "item.second") << "&"; +#end #end ${spaces} ${macro.varName}Count++; ${spaces}} diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeSubObjQueryMapElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeSubObjQueryMapElement.vm index 633eddb064d3..4db390fc41b7 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeSubObjQueryMapElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/queryxml/QuerySerializeTemplateMacros/serializeSubObjQueryMapElement.vm @@ -32,14 +32,26 @@ #if($member.shape.mapValue.shape.structure) ${spaces} Aws::StringStream ${macro.lowerCaseVarName}Ss; ${spaces} ${macro.lowerCaseVarName}Ss << location << ${macro.locationIndexValue}".${macro.mapLocationName}." << ${macro.lowerCaseVarName}Idx << ".${macro.mapValueLocationName}"; +#if($member.shape.sparse) + ${spaces} if(item.second.has_value()) { + ${spaces} item.second.value().OutputToStream(oStream, ${macro.lowerCaseVarName}Ss.str().c_str()); + ${spaces} } +#else ${spaces} item.second.OutputToStream(oStream, ${macro.lowerCaseVarName}Ss.str().c_str()); +#end #else #set($macro.equals='="') #if($member.shape.mapValue.shape.list || $member.shape.mapValue.shape.map) #set($macro.equals='"') #end #set($mapValueLocation = '".' + "${macro.mapLocationName}." + '"' + " << ${macro.lowerCaseVarName}Idx << " + '".' + ${macro.mapValueLocationName} + $macro.equals + $nl + " ${spaces} ") +#if($member.shape.sparse) + ${spaces} if(item.second.has_value()) { + ${spaces} oStream << location << ${macro.locationIndexValue}#serializeSubObjQuerySingleElement($member.shape.mapValue, $mapValueLocation, "item.second.value()") << "&"; + ${spaces} } +#else ${spaces} oStream << location << ${macro.locationIndexValue}#serializeSubObjQuerySingleElement($member.shape.mapValue, $mapValueLocation, "item.second") << "&"; +#end #end ${spaces} ${macro.lowerCaseVarName}Idx++; ${spaces}} diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlListPayloadElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlListPayloadElement.vm index 289c96de1220..be8e43a22dbf 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlListPayloadElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlListPayloadElement.vm @@ -54,7 +54,19 @@ ${macro.spaces}while(!${macro.listVarName}.IsNull()) ${macro.spaces}{ #set($macro.memberVarName = $CppViewHelper.computeMemberVariableName($memberName)) +#if($member.shape.sparse) + ${macro.spaces} if(${macro.listVarName}.GetText().empty() || ${macro.listVarName}.GetAttributeValue("xsi:nil") == "true") { + ${macro.spaces} ${macro.memberVarName}.emplace_back(); + ${macro.spaces} } else { +#if($member.shape.listMember.shape.structure) + ${macro.spaces} ${macro.memberVarName}.emplace_back(#deserializeXmlSingleElement($member.shape.listMember, $macro.listVarName)); +#else + ${macro.spaces} ${macro.memberVarName}.push_back(#deserializeXmlSingleElement($member.shape.listMember, $macro.listVarName)); +#end + ${macro.spaces} } +#else ${macro.spaces} ${macro.memberVarName}.push_back(#deserializeXmlSingleElement($member.shape.listMember, $macro.listVarName)); +#end #if($member.shape.listMember.locationName) #set($listMemberName = $member.shape.listMember.locationName) #elseif(!($member.shape.flattened || $member.flattened)) diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlMapPayloadElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlMapPayloadElement.vm index c117ed91570a..1c3ed3ccc637 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlMapPayloadElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlMapPayloadElement.vm @@ -38,8 +38,14 @@ ${macro.spaces} XmlNode valueNode = ${macro.mapVarName}.FirstChild("value"); #end #set($macro.memberVarName = $CppViewHelper.computeMemberVariableName($memberName)) +#if($member.shape.sparse) + ${macro.spaces} if(valueNode.IsNull() || valueNode.GetAttributeValue("xsi:nil") == "true") { ${macro.memberVarName}[#deserializeXmlSingleElement($member.shape.mapKey, "keyNode")]; } else { + ${macro.spaces} ${macro.memberVarName}[#deserializeXmlSingleElement($member.shape.mapKey, "keyNode")] = + ${macro.spaces} #deserializeXmlSingleElement($member.shape.mapValue, "valueNode", $macro.spaces, false); } +#else ${macro.spaces} ${macro.memberVarName}[#deserializeXmlSingleElement($member.shape.mapKey, "keyNode")] = ${macro.spaces} #deserializeXmlSingleElement($member.shape.mapValue, "valueNode", $macro.spaces, false); +#end #if($member.locationName) ${macro.spaces} ${macro.mapVarName} = ${macro.mapVarName}.NextNode("${member.locationName}"); #else diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedListElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedListElement.vm index f04e717dbbb3..015c9b215b24 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedListElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedListElement.vm @@ -8,7 +8,15 @@ ${macro.spaces} if(${memberVarName}.IsNull()) { return ${macro.resultVarName}; } ${macro.spaces} XmlNode ${macro.resultVarName}MemberNode = ${memberVarName}.FirstChild("${CppViewHelper.ifNotNullOrEmpty($member.locationName, 'member')}"); ${macro.spaces} while(!${macro.resultVarName}MemberNode.IsNull()) { +#if($member.shape.sparse) + ${macro.spaces} if(${macro.resultVarName}MemberNode.IsNull() || ${macro.resultVarName}MemberNode.GetText().empty()) { + ${macro.spaces} ${macro.resultVarName}.push_back(Aws::Crt::Optional<$CppViewHelper.computeCppType($member.shape.listMember.shape)>{}); + ${macro.spaces} } else { + ${macro.spaces} ${macro.resultVarName}.push_back(#deserializeXmlSingleElement($member.shape.listMember, "${macro.resultVarName}MemberNode")); + ${macro.spaces} } +#else ${macro.spaces} ${macro.resultVarName}.push_back(#deserializeXmlSingleElement($member.shape.listMember, "${macro.resultVarName}MemberNode")); +#end ${macro.spaces} ${macro.resultVarName}MemberNode = ${macro.resultVarName}MemberNode.NextNode("${CppViewHelper.ifNotNullOrEmpty($member.locationName, 'member')}"); ${macro.spaces} } ${macro.spaces} return ${macro.resultVarName}; diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedMapElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedMapElement.vm index 2eadbc20f8ec..52ee6eeb9c25 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedMapElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlDeserializeTemplateMacros/deserializeXmlNestedMapElement.vm @@ -23,8 +23,17 @@ ${macro.spaces} while(!${macro.resultVarName}EntryNode.IsNull()) { ${macro.spaces} XmlNode ${macro.resultVarName}KeyNode = ${macro.resultVarName}EntryNode.FirstChild("${CppViewHelper.ifNotNullOrEmpty($member.shape.mapKey.locationName, 'key')}"); ${macro.spaces} XmlNode ${macro.resultVarName}ValNode = ${macro.resultVarName}EntryNode.FirstChild("${CppViewHelper.ifNotNullOrEmpty($member.shape.mapValue.locationName, 'value')}"); +#if($member.shape.sparse) + ${macro.spaces} if(${macro.resultVarName}ValNode.IsNull() || ${macro.resultVarName}ValNode.GetText().empty()) { + ${macro.spaces} ${macro.resultVarName}[#deserializeXmlSingleElement($member.shape.mapKey, "${macro.resultVarName}KeyNode")] = Aws::Crt::Optional<$CppViewHelper.computeCppType($member.shape.mapValue.shape)>{}; + ${macro.spaces} } else { + ${macro.spaces} ${macro.resultVarName}[#deserializeXmlSingleElement($member.shape.mapKey, "${macro.resultVarName}KeyNode")] = + ${macro.spaces} #deserializeXmlSingleElement($member.shape.mapValue, "${macro.resultVarName}ValNode", $macro.spaces, false); + ${macro.spaces} } +#else ${macro.spaces} ${macro.resultVarName}[#deserializeXmlSingleElement($member.shape.mapKey, "${macro.resultVarName}KeyNode")] = ${macro.spaces} #deserializeXmlSingleElement($member.shape.mapValue, "${macro.resultVarName}ValNode", $macro.spaces, false); +#end ${macro.spaces} ${macro.resultVarName}EntryNode = ${macro.resultVarName}EntryNode.NextNode("${CppViewHelper.ifNotNullOrEmpty($member.locationName, 'entry')}"); ${macro.spaces} } ${macro.spaces} return ${macro.resultVarName}; diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlListPayloadElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlListPayloadElement.vm index cacc0d8899a9..a046ef956287 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlListPayloadElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlListPayloadElement.vm @@ -29,6 +29,15 @@ ## if list is flattened than the name of repeated XML element is ShapeMember name in parent name OR explicitly set by parent's locationName #set($macro.listMemberSerializationName = ${CppViewHelper.ifNotNullOrEmpty($member.locationName, $serializationName)}) #end +#if($member.shape.sparse) + ${spaces} if(!${macro.listItemVarName}.has_value()) { + ${spaces} XmlNode ${lowerCaseVarName}NilNode = ${macro.listMemberParentNode}.CreateChildElement("${macro.listMemberSerializationName}"); + ${spaces} ${lowerCaseVarName}NilNode.SetAttributeValue("xsi:nil", "true"); + ${spaces} } else { +#serializeXmlSinglePayloadElement($macro.listSpaces, $macro.listMemberSerializationName, $lowerCaseVarName, $member.shape.listMember, "(*${macro.listItemVarName})", $macro.listMemberParentNode) + ${spaces} } +#else #serializeXmlSinglePayloadElement($macro.listSpaces, $macro.listMemberSerializationName, $lowerCaseVarName, $member.shape.listMember, $macro.listItemVarName, $macro.listMemberParentNode) +#end ${spaces}} #end##macro serializeXmlListPayloadElement \ No newline at end of file diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlMapPayloadElement.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlMapPayloadElement.vm index abd754414e4a..23fa939fe361 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlMapPayloadElement.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlSerializeTemplateMacros/serializeXmlMapPayloadElement.vm @@ -25,6 +25,15 @@ #set($macro.mapKeySerializationName = "#if($member.shape.mapKey.locationName)$member.shape.mapKey.locationName#{else}key#end") #serializeXmlSinglePayloadElement($macro.mapSpaces, $macro.mapKeySerializationName, "${lowerCaseVarName}Key", $member.shape.mapKey, "${macro.mapItemVarName}.first", "${lowerCaseVarName}MapEntryNode") #set($macro.mapValueSerializationName = "#if($member.shape.mapValue.locationName)$member.shape.mapValue.locationName#{else}value#end") +#if($member.shape.sparse) + ${spaces} if(!${macro.mapItemVarName}.second.has_value()) { + ${spaces} XmlNode ${lowerCaseVarName}NilNode = ${lowerCaseVarName}MapEntryNode.CreateChildElement("${macro.mapValueSerializationName}"); + ${spaces} ${lowerCaseVarName}NilNode.SetAttributeValue("xsi:nil", "true"); + ${spaces} } else { +#serializeXmlSinglePayloadElement($macro.mapSpaces, $macro.mapValueSerializationName, "${lowerCaseVarName}Value", $member.shape.mapValue, "(*${macro.mapItemVarName}.second)", "${lowerCaseVarName}MapEntryNode") + ${spaces} } +#else #serializeXmlSinglePayloadElement($macro.mapSpaces, $macro.mapValueSerializationName, "${lowerCaseVarName}Value", $member.shape.mapValue, "${macro.mapItemVarName}.second", "${lowerCaseVarName}MapEntryNode") +#end ${spaces}} #end##macro serializeXmlMapPayloadElement \ No newline at end of file diff --git a/tools/scripts/run_code_generation.py b/tools/scripts/run_code_generation.py index 82a5a5acecee..787c66a94ae5 100644 --- a/tools/scripts/run_code_generation.py +++ b/tools/scripts/run_code_generation.py @@ -161,7 +161,10 @@ def main(): return -1 if args["generate_protocol_tests"]: - protocol_tests_generator = ProtocolTestsGen(args) + # Disable smithy generation for protocol tests + protocol_args = args.copy() + protocol_args["disable_smithy_generation"] = True + protocol_tests_generator = ProtocolTestsGen(protocol_args) if protocol_tests_generator.generate(executor, max_workers) != 0: print("ERROR: Failed to generate protocol test(s)!") return -1