diff --git a/build.gradle.kts b/build.gradle.kts index e66c520c77..20f2d9e400 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,8 +15,11 @@ buildscript { } allprojects { + val allowLocalDeps: String by project repositories { - // mavenLocal() + if (allowLocalDeps.toBoolean()) { + mavenLocal() + } mavenCentral() google() } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 0171fabac5..c032bfc8f8 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,7 +12,6 @@ plugins { repositories { mavenCentral() google() - /* mavenLocal() */ } // Load properties manually to avoid hard coding smithy version diff --git a/codegen-client-test/build.gradle.kts b/codegen-client-test/build.gradle.kts index 7b39dd1e38..de4b54d5b3 100644 --- a/codegen-client-test/build.gradle.kts +++ b/codegen-client-test/build.gradle.kts @@ -114,8 +114,6 @@ val allCodegenTests = listOf( ), ClientTest("aws.protocoltests.misc#QueryCompatService", "query-compat-test", dependsOn = listOf("aws-json-query-compat.smithy")), ).map(ClientTest::toCodegenTest) -// use this line to run just one test -// .filter { it.module == "query-compat-test" } project.registerGenerateSmithyBuildTask(rootProject, pluginName, allCodegenTests) project.registerGenerateCargoWorkspaceTask(rootProject, pluginName, allCodegenTests, workingDirUnderBuildDir) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt index 31a1b0c7b5..4a8b8a1054 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt @@ -36,6 +36,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.canUseDefault import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.Section @@ -121,6 +122,7 @@ class JsonParserGenerator( "skip_to_end" to smithyJson.resolve("deserialize::token::skip_to_end"), "Token" to smithyJson.resolve("deserialize::Token"), "or_empty" to orEmptyJson(), + *preludeScope, ) /** @@ -560,6 +562,15 @@ class JsonParserGenerator( *codegenScope, ) { objectKeyLoop(hasMembers = shape.members().isNotEmpty()) { + rustTemplate( + """ + if let #{Some}(#{Ok}(#{Token}::ValueNull { .. })) = tokens.peek() { + let _ = tokens.next().expect("peek returned a token")?; + continue; + } + """, + *codegenScope, + ) rustTemplate( """ let key = key.to_unescaped()?; @@ -622,6 +633,16 @@ class JsonParserGenerator( *codegenScope, ) } + // If we've gotten to the point where the union had a `{ ... }` section, we can't return None + // anymore. If we didn't parse a union at this point, this is an error. + rustTemplate( + """ + if variant.is_none() { + return Err(#{Error}::custom("Union did not contain a valid variant.")) + } + """, + *codegenScope, + ) rust("Ok(variant)") } } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt index ed416545b1..8e7985a27a 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt @@ -183,6 +183,26 @@ class JsonParserGeneratorTest { """, ) + unitTest( + "allow_null_for_variants", + """ + // __type field should be ignored during deserialization + let input = br#"{ "top": { "choice": { "blob": null, "boolean": null, "int": 5, "long": null, "__type": "value-should-be-ignored-anyway" } } }"#; + let output = ${format(operationGenerator)}(input, test_output::OpOutput::builder()).unwrap().build(); + use test_model::Choice; + assert_eq!(Choice::Int(5), output.top.unwrap().choice); + """, + ) + + unitTest( + "all_variants_null", + """ + // __type field should be ignored during deserialization + let input = br#"{ "top": { "choice": { "blob": null, "boolean": null, "int": null, "long": null, "__type": "value-should-be-ignored-anyway" } } }"#; + let _err = ${format(operationGenerator)}(input, test_output::OpOutput::builder()).expect_err("invalid union"); + """, + ) + unitTest( "empty_error", """ diff --git a/gradle.properties b/gradle.properties index d5e5184bdb..e198984afd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,6 +22,7 @@ kotlin.code.style=official # codegen smithyGradlePluginVersion=0.9.0 smithyVersion=1.45.0 +allowLocalDeps=false # kotlin kotlinVersion=1.9.20