Loading .changelog/unknown-variants.md 0 → 100644 +10 −0 Original line number Diff line number Diff line --- applies_to: ["client", "server"] authors: ["rcoh"] references: ["smithy-rs#4132"] breaking: false new_feature: false bug_fix: true --- Smithy unions that contain members named "unknown" will now codegen correctly codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGenerator.kt +6 −2 Original line number Diff line number Diff line Loading @@ -110,7 +110,8 @@ open class UnionGenerator( private fun renderImplBlock(unionSymbol: Symbol) { writer.rustBlock("impl ${unionSymbol.name}") { sortedMembers.forEach { member -> val funcNamePart = member.memberName.toSnakeCase() // We need to get the symbol first because the member can be renamed val funcNamePart = symbolProvider.toSymbol(member).name.toSnakeCase() val variantName = symbolProvider.toMemberName(member) if (sortedMembers.size == 1) { Loading Loading @@ -219,7 +220,10 @@ private fun RustWriter.renderAsVariant( targetSymbol, ) rust("/// Returns `Err(&Self)` if it can't be converted.") rustBlockTemplate("pub fn as_$funcNamePart(&self) -> #{Result}<&${memberSymbol.rustType().render()}, &Self>", *preludeScope) { rustBlockTemplate( "pub fn as_$funcNamePart(&self) -> #{Result}<&${memberSymbol.rustType().render()}, &Self>", *preludeScope, ) { rustTemplate( "if let ${unionSymbol.name}::$variantName(val) = &self { #{Ok}(val) } else { #{Err}(self) }", *preludeScope, Loading codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGeneratorTest.kt +49 −3 Original line number Diff line number Diff line Loading @@ -7,9 +7,11 @@ package software.amazon.smithy.rust.codegen.core.smithy.generators import io.kotest.matchers.string.shouldContain import org.junit.jupiter.api.Test import software.amazon.smithy.codegen.core.SymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWordConfig import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWordSymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest Loading Loading @@ -42,6 +44,28 @@ class UnionGeneratorTest { writer.toString() shouldContain "#[non_exhaustive]" } @Test fun `generate basic union with member names Unknown`() { val writer = generateUnion( """ union MyUnion { unknown: String } """, ) writer.compileAndTest( """ let var_a = MyUnion::UnknownValue("abc".to_string()); let var_b = MyUnion::Unknown; assert_ne!(var_a, var_b); assert_eq!(var_a, var_a); """, ) writer.toString() shouldContain "#[non_exhaustive]" } @Test fun `generate conversion helper methods`() { val writer = Loading Loading @@ -232,9 +256,31 @@ class UnionGeneratorTest { unknownVariant: Boolean = true, ): RustWriter { val model = "namespace test\n$modelSmithy".asSmithyModel() val provider: SymbolProvider = testSymbolProvider(model) // Reserved words to test generation of renamed members val reservedWords = RustReservedWordConfig( structureMemberMap = StructureGenerator.structureMemberNameMap, unionMemberMap = mapOf( // Unions contain an `Unknown` variant. This exists to support parsing data returned from the server // that represent union variants that have been added since this SDK was generated. UnionGenerator.UNKNOWN_VARIANT_NAME to "${UnionGenerator.UNKNOWN_VARIANT_NAME}Value", "${UnionGenerator.UNKNOWN_VARIANT_NAME}Value" to "${UnionGenerator.UNKNOWN_VARIANT_NAME}Value_", ), enumMemberMap = mapOf(), ) val provider: RustSymbolProvider = testSymbolProvider(model) val reservedWordsProvider = RustReservedWordSymbolProvider(provider, reservedWords) val writer = RustWriter.forModule("model") UnionGenerator(model, provider, writer, model.lookup("test#$unionName"), renderUnknownVariant = unknownVariant).render() UnionGenerator( model, reservedWordsProvider, writer, model.lookup("test#$unionName"), renderUnknownVariant = unknownVariant, ).render() return writer } } Loading
.changelog/unknown-variants.md 0 → 100644 +10 −0 Original line number Diff line number Diff line --- applies_to: ["client", "server"] authors: ["rcoh"] references: ["smithy-rs#4132"] breaking: false new_feature: false bug_fix: true --- Smithy unions that contain members named "unknown" will now codegen correctly
codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGenerator.kt +6 −2 Original line number Diff line number Diff line Loading @@ -110,7 +110,8 @@ open class UnionGenerator( private fun renderImplBlock(unionSymbol: Symbol) { writer.rustBlock("impl ${unionSymbol.name}") { sortedMembers.forEach { member -> val funcNamePart = member.memberName.toSnakeCase() // We need to get the symbol first because the member can be renamed val funcNamePart = symbolProvider.toSymbol(member).name.toSnakeCase() val variantName = symbolProvider.toMemberName(member) if (sortedMembers.size == 1) { Loading Loading @@ -219,7 +220,10 @@ private fun RustWriter.renderAsVariant( targetSymbol, ) rust("/// Returns `Err(&Self)` if it can't be converted.") rustBlockTemplate("pub fn as_$funcNamePart(&self) -> #{Result}<&${memberSymbol.rustType().render()}, &Self>", *preludeScope) { rustBlockTemplate( "pub fn as_$funcNamePart(&self) -> #{Result}<&${memberSymbol.rustType().render()}, &Self>", *preludeScope, ) { rustTemplate( "if let ${unionSymbol.name}::$variantName(val) = &self { #{Ok}(val) } else { #{Err}(self) }", *preludeScope, Loading
codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGeneratorTest.kt +49 −3 Original line number Diff line number Diff line Loading @@ -7,9 +7,11 @@ package software.amazon.smithy.rust.codegen.core.smithy.generators import io.kotest.matchers.string.shouldContain import org.junit.jupiter.api.Test import software.amazon.smithy.codegen.core.SymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWordConfig import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWordSymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest Loading Loading @@ -42,6 +44,28 @@ class UnionGeneratorTest { writer.toString() shouldContain "#[non_exhaustive]" } @Test fun `generate basic union with member names Unknown`() { val writer = generateUnion( """ union MyUnion { unknown: String } """, ) writer.compileAndTest( """ let var_a = MyUnion::UnknownValue("abc".to_string()); let var_b = MyUnion::Unknown; assert_ne!(var_a, var_b); assert_eq!(var_a, var_a); """, ) writer.toString() shouldContain "#[non_exhaustive]" } @Test fun `generate conversion helper methods`() { val writer = Loading Loading @@ -232,9 +256,31 @@ class UnionGeneratorTest { unknownVariant: Boolean = true, ): RustWriter { val model = "namespace test\n$modelSmithy".asSmithyModel() val provider: SymbolProvider = testSymbolProvider(model) // Reserved words to test generation of renamed members val reservedWords = RustReservedWordConfig( structureMemberMap = StructureGenerator.structureMemberNameMap, unionMemberMap = mapOf( // Unions contain an `Unknown` variant. This exists to support parsing data returned from the server // that represent union variants that have been added since this SDK was generated. UnionGenerator.UNKNOWN_VARIANT_NAME to "${UnionGenerator.UNKNOWN_VARIANT_NAME}Value", "${UnionGenerator.UNKNOWN_VARIANT_NAME}Value" to "${UnionGenerator.UNKNOWN_VARIANT_NAME}Value_", ), enumMemberMap = mapOf(), ) val provider: RustSymbolProvider = testSymbolProvider(model) val reservedWordsProvider = RustReservedWordSymbolProvider(provider, reservedWords) val writer = RustWriter.forModule("model") UnionGenerator(model, provider, writer, model.lookup("test#$unionName"), renderUnknownVariant = unknownVariant).render() UnionGenerator( model, reservedWordsProvider, writer, model.lookup("test#$unionName"), renderUnknownVariant = unknownVariant, ).render() return writer } }