-
Notifications
You must be signed in to change notification settings - Fork 190
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
Enforce constraints for unnamed enums #3884
base: main
Are you sure you want to change the base?
Conversation
A new generated diff is ready to view.
A new doc preview is ready to view. |
f2aa580
to
651538a
Compare
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
17ca030
to
bfdf606
Compare
A new generated diff is ready to view.
A new doc preview is ready to view. |
...n/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGenerator.kt
Show resolved
Hide resolved
@@ -10,6 +10,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust | |||
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate | |||
import software.amazon.smithy.rust.codegen.core.rustlang.writable | |||
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.util.dq | |||
|
|||
object TestEnumType : EnumType() { |
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.
Huh, I wonder why we have this class at all i.e. why we don't test directly against InfallibleEnumType
. It feels wrong to copy over the implementations from the "real" classes to this class.
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.
I agree with you on this. I'll see if it can be easily fixed in this PR, otherwise will raise another one for this.
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.
InfallibleEnumType
allows UnknownVariants
, whereas TestEnumType
panics when an unknown variant is encountered. I tried composing TestEnumType
to use InfallibleEnumType
internally, but InfallibleEnumType
is defined in codegen-client
, while TestEnumType
is in codegen-core
.
impl #{TryFrom}<&str> for ${context.enumName} { | ||
type Error = #{ConstraintViolation}; | ||
fn try_from(s: &str) -> #{Result}<Self, <Self as #{TryFrom}<&str>>::Error> { | ||
s.to_owned().try_into() |
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.
This is first converting to a heap-allocated String
and only then matching on the enum values. So invalid enum values would unnecessarily be heap-allocated. We should make TryFrom<String>
and TryFrom<&str>
instead delegate to FromStr
, which should only heap-allocate when the enum value is valid.
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.
Unlike named enums, which can use &str
for comparison and directly return an enum variant, unnamed enums need to store an owned, heap-allocated String
. The TryFrom<String>
implementation already receives an owned String
as a parameter, so delegating to FromStr
would result in an unnecessary heap allocation. Additionally, ConstraintViolation
takes ownership of a heap-allocated String
. Therefore, both code paths (valid and invalid enum values) require a heap-allocated String
. Calling to_owned
within TryFrom<&str>
only shifts the allocation slightly earlier without adding any additional allocation.
...n/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGenerator.kt
Show resolved
Hide resolved
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
fbcefa0
to
042fe5c
Compare
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
Enforces Constraints for Unnamed Enums
This PR addresses the issue where, on the server side, unnamed enums were incorrectly treated as infallible during deserialization, allowing any string value to be converted without validation. The solution introduces a
ConstraintViolation
andTryFrom
implementation for unnamed enums, ensuring that deserialized values conform to the enum variants defined in the Smithy model.The following is an example of an unnamed enum:
On the server side the following type is generated for the Smithy shape:
This change prevents invalid values from being deserialized into unnamed enums and raises appropriate constraint violations when necessary.
There is one difference between the Rust code generated for
TryFrom<String>
for named enums versus unnamed enums. The implementation for unnamed enums passes the ownership of theString
parameter to the generated structure, and the implementation forTryFrom<&str>
delegates toTryFrom<String>
.On the client side, the behaviour is unchanged, and the client does not validate for backward compatibility reasons. An existing test has been modified to ensure this.
Fixes issue #3880