-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unknown enum variants removed from server #1398
Conversation
A new generated diff is ready to view. A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
CHANGELOG.next.toml
Outdated
[[smithy-rs]] | ||
message = "Remove Unknown variant from enums in server" | ||
references = ["smithy-rs#1187"] | ||
meta = { "breaking" = true, "tada" = false, "bug" = false } | ||
author = "82marbag" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not publish CHANGELOG entries for server only changes. If this PR does not change how the client SDK is generated, this should go away.
if (mode == CodegenMode.Client) { | ||
docs("$UnknownVariant contains new variants that have been added since this code was generated.") | ||
write("$UnknownVariant(String)") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this be abstracted completely inside the ServerEnumGenerator
rather than having an if guard here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I understand. They are here because the client generates the same code as the server, plus some more. The one where the server is generating actual different code is in the server only. But not to copy/paste code around, I generate the common code in the client and the additional code in the client. Moving to ServerEnumGenerator would mean to copy the same code there anyway. I am open for suggestions
...in/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/HttpBindingGenerator.kt
Show resolved
Hide resolved
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
@@ -184,7 +184,7 @@ class ServerCodegenVisitor(context: PluginContext, private val codegenDecorator: | |||
logger.info("[rust-server-codegen] Generating an enum $shape") | |||
shape.getTrait<EnumTrait>()?.also { enum -> | |||
rustCrate.useShapeWriter(shape) { writer -> | |||
EnumGenerator(model, symbolProvider, writer, shape, enum).render() | |||
ServerEnumGenerator(model, symbolProvider, writer, shape, enum, codegenContext.mode, codegenContext.runtimeConfig).render() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In these cases where the number of params grows, instead of plucking everything out of codegenContext
, just pass codegenContext
and have the generator pull out the things it needs: model
, symbolProvider
, runtimeConfig
etc...
...n/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt
Outdated
Show resolved
Hide resolved
...n/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt
Outdated
Show resolved
Hide resolved
...n/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt
Outdated
Show resolved
Hide resolved
writer.rustBlock("impl #T<$errorStruct> for #T", RuntimeType.From, ServerRuntimeType.RequestRejection(runtimeConfig)) { | ||
writer.rustBlock("fn from(e: $errorStruct) -> Self") { | ||
write("Self::EnumVariantNotFound(Box::new(e))") | ||
} | ||
} | ||
writer.rustBlock("impl From<$errorStruct> for #T", RuntimeType.jsonDeserialize(runtimeConfig)) { | ||
writer.rustBlock("fn from(e: $errorStruct) -> Self") { | ||
write("""Self::custom(format!("unknown variant {}", e))""") | ||
} | ||
} | ||
writer.rustBlock("impl std::error::Error for $errorStruct") {} | ||
writer.rustBlock("impl std::fmt::Display for $errorStruct") { | ||
writer.rustBlock("fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result") { | ||
write("self.0.fmt(f)") | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elaborating on the "strive to write as much uninterrupted Rust as possible", this code is fine, but notice it's exactly the same as:
writer.rustBlock("impl #T<$errorStruct> for #T", RuntimeType.From, ServerRuntimeType.RequestRejection(runtimeConfig)) { | |
writer.rustBlock("fn from(e: $errorStruct) -> Self") { | |
write("Self::EnumVariantNotFound(Box::new(e))") | |
} | |
} | |
writer.rustBlock("impl From<$errorStruct> for #T", RuntimeType.jsonDeserialize(runtimeConfig)) { | |
writer.rustBlock("fn from(e: $errorStruct) -> Self") { | |
write("""Self::custom(format!("unknown variant {}", e))""") | |
} | |
} | |
writer.rustBlock("impl std::error::Error for $errorStruct") {} | |
writer.rustBlock("impl std::fmt::Display for $errorStruct") { | |
writer.rustBlock("fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result") { | |
write("self.0.fmt(f)") | |
} | |
} | |
} | |
writer.rustTemplate( | |
""" | |
impl #{From}<$errorStruct> for #{RequestRejection} { | |
fn from(e: $errorStruct) -> Self { | |
Self::EnumVariantNotFound(Box::new(e)) | |
} | |
} | |
impl #{From}<$errorStruct> for #{JsonDeserialize} { | |
fn from(e: $errorStruct) -> Self { | |
Self::custom(format!("unknown variant {}", e)) | |
} | |
} | |
impl #{StdError} for $errorStruct { } | |
impl std::fmt::Display for $errorStruct { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
self.0.fmt(f) | |
} | |
} | |
""", | |
"From" to RuntimeType.From, | |
"StdError" to RuntimeType.StdError, | |
"RequestRejection" to ServerRuntimeType.RequestRejection(runtimeConfig), | |
"JsonDeserialize" to RuntimeType.jsonDeserialize(runtimeConfig), | |
) |
which reads much nicer.
(Bonus points: we should also have a RuntimeType.Display
and use it everywhere in the codebase where we've used RuntimeType.stdfmt.member("Display")
or written out Display
manually).
The writer.*block
methods are useful when you have to loop over a collection, when you want to insert blocks conditionally, or when you need to put conditionals based on Kotlin variables inside your Rust blocks. For example, above was a good use of rustBlock
, because you needed to iterate over sortedMembers
.
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/SymbolVisitor.kt
Outdated
Show resolved
Hide resolved
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/EnumGenerator.kt
Outdated
Show resolved
Hide resolved
...ain/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/JsonParserGenerator.kt
Outdated
Show resolved
Hide resolved
codegen/src/test/kotlin/software/amazon/smithy/rust/testutil/Annotations.kt
Outdated
Show resolved
Hide resolved
The server must have the most up to date variants and the unknown enum variant should not be used. Clients are generated with it because they might not have the most recent model and the server might return an unknown variant to them. Closes #1187 Signed-off-by: Daniele Ahmed <[email protected]>
Signed-off-by: Daniele Ahmed <[email protected]>
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
Signed-off-by: Daniele Ahmed <[email protected]>
Signed-off-by: Daniele Ahmed <[email protected]>
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An empty rust-runtime/.attach_pid18283
file crept into the patchset.
...tware/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt
Outdated
Show resolved
Hide resolved
...tlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGeneratorTest.kt
Outdated
Show resolved
Hide resolved
...tlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGeneratorTest.kt
Outdated
Show resolved
Hide resolved
...tlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGeneratorTest.kt
Outdated
Show resolved
Hide resolved
...ware/amazon/smithy/rust/codegen/smithy/protocols/parse/XmlBindingTraitParserGeneratorTest.kt
Outdated
Show resolved
Hide resolved
Co-authored-by: david-perez <[email protected]>
Signed-off-by: Daniele Ahmed <[email protected]>
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/Instantiator.kt
Show resolved
Hide resolved
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
A new generated diff is ready to view.
A new doc preview is ready to view. Rust Wrk benchmark report:Duration: 90 sec, Connections: 32, Threads: 2
|
XML deserialization of enums is currently broken. This commit should have been done as part of #1398, but we only tested that patch using the restJson1 protocol. The converter from the unknown enum variant error into `aws_smithy_json::deserialize::Error` has been removed from `ServerEnumGenerator`, since it's protocol-specific logic. We instead use `map_err` in the protocol-specific parsers before bubbling up using `?`. Fixes #1477.
…1485) XML deserialization of enums is currently broken. This commit should have been done as part of #1398, but we only tested that patch using the restJson1 protocol. The converter from the unknown enum variant error into `aws_smithy_json::deserialize::Error` has been removed from `ServerEnumGenerator`, since it's protocol-specific logic. We instead use `map_err` in the protocol-specific parsers before bubbling up using `?`. Fixes #1477.
The server must have the most up to date variants and the unknown enum
variant should not be used. Clients are generated with it because they
might not have the most recent model and the server might return
an unknown variant to them.
Closes #1187
Signed-off-by: Daniele Ahmed [email protected]
Motivation and Context
Closes #1187
Description
Testing
./gradlew :codegen-server-test:test
Checklist
CHANGELOG.next.toml
if I made changes to the smithy-rs codegen or runtime cratesCHANGELOG.next.toml
if I made changes to the AWS SDK, generated SDK code, or SDK runtime cratesBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.