Skip to content
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

Smithy 1.9/1.10 Upgrade #618

Merged
merged 18 commits into from
Jul 30, 2021
Merged

Smithy 1.9/1.10 Upgrade #618

merged 18 commits into from
Jul 30, 2021

Conversation

rcoh
Copy link
Collaborator

@rcoh rcoh commented Jul 29, 2021

Issue #, if available: Fixes #603
Description of changes: This diff upgrades smithy-rs to Smithy 1.10. The most significant change is updates to the float parsing behavior. To handle this, I centralized all of our primitive parsing behavior into smithy_types::primitive and refactored the numerous protocols:

  • aws-query
  • restXml
  • header parsing / serde
  • label parsing / serde
  • query string parsing / serde

to use the implementation. This has the side benefit that we now serialize primitives without incurring an additional allocation to String in most cases because primitive::Encoder returns &str and uses a stack allocation to store the resulting value.

The second commit updates the S3 unwrapped response customization to use the new smithy-provided trait.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

rcoh added 2 commits July 29, 2021 10:54
This upgrades to Smithy 1.10, but the major change is a complete overhaul of how primitives are formatted and parsed. Primitive serialization was migrated and unified into Smithy Types with the end requirement of dealing with special float serialization semantics.
Smithy 1.9.1 brings S3UnwrappedXmlOutput as a vended trait. This commit pulls in the new model & uses that trait.
@rcoh rcoh requested a review from jdisanti July 29, 2021 14:58
Copy link
Collaborator

@jdisanti jdisanti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good! Just some minor comments to improve clarity. I think we should decide on how tied to the specifics of Smithy the JSON runtime crate should be. It has smithy- in the name, but I originally intended for it to be mostly usable outside of the context of Smithy. I guess it has the timestamp logic in it, so maybe I'm clinging to something that doesn't exist.

ModelTransformer.create().mapShapes(model) { shape ->
// Apply the S3UnwrappedXmlOutput customization to GetBucketLocation (more
// details on the S3UnwrappedXmlOutputTrait)
if (shape is StructureShape && shape.id == ShapeId.from("com.amazonaws.s3#GetBucketLocationOutput")) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay! 😄

Comment on lines 199 to 201
if (innerMemberType.isPrimitive()) {
rust("let mut encoder = #T::from(*$innerField);", Encoder)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to have this be in closer proximity to the encoder.encode() call?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sigh, not without a bunch of refactoring. The one downside of the encoder pattern is that it needs to be kept alive until the slice has made it to its final home

@@ -354,6 +361,8 @@ class RequestBindingGenerator(
return true
}

private val Encoder = CargoDependency.SmithyTypes(runtimeConfig).asType().member("primitive::Encoder")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go at the top of the class with the other private members so that it's discoverable.

@@ -6,7 +6,6 @@ edition = "2018"

[dependencies]
itoa = "0.4"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is itoa still needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, nope

Some(Token::ValueNull { .. }) => Ok(None),
Some(Token::ValueNumber { value, .. }) => Ok(Some(value)),
Some(Token::ValueString { value, offset }) => match value.to_unescaped() {
Err(_) => Err(Error::custom("expected a valid string, escape was invalid")),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're discarding some details about the underlying cause of the error here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, recovered them

Some(Token::ValueNumber { value, .. }) => Ok(Some(value)),
Some(Token::ValueString { value, offset }) => match value.to_unescaped() {
Err(_) => Err(Error::custom("expected a valid string, escape was invalid")),
Ok(v) => f64::parse(v.as_ref())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's easy to mistake this for the std library from_str operation, which accepts inf instead of Infinity. It works, but it may lead people astray. Maybe call the function parse_primitive so it's more apparent that smithy-types is adding it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed to parse_smithy_primitive

// JSON doesn't support NaN, Infinity, or -Infinity, so we're matching
// Smithy has specific behavior for infinity & NaN
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're conflating things here. smithy-json is intended to just do JSON, and this is a Smithy detail on top of JSON. Seems like it should be behavior that is added via inlineable. What are your thoughts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that these are smithy specific libraries I think it's pretty reasonable. The behavior only augments the expect_or helpers instead of the raw token stream. We could consider extracting those somewhere protocol specific

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I think for now, a JSON library that "does the right thing" is probably the best option

#[non_exhaustive]
Bool(bool),
#[non_exhaustive]
I8(i8, itoa::Buffer),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clever putting the buffers inside the encoder to avoid allocations! Nice.

@rcoh rcoh requested a review from jdisanti July 29, 2021 20:08
@rcoh rcoh enabled auto-merge (squash) July 30, 2021 15:15
@rcoh rcoh merged commit f1a726c into main Jul 30, 2021
@rcoh rcoh deleted the smithy-1.9.1 branch July 30, 2021 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Smithy 1.10 Upgrade
2 participants