Skip to content

Commit

Permalink
Add send_with method to fluent builders (#2652)
Browse files Browse the repository at this point in the history
## Motivation and Context
This is a child PR of #2615.

## Description
- Adds `send_with` method to Fluent Builder.

## Prerequisite PRs
You can merge this first too reduce diffs.

- #2651

## Testing
NA

## Checklist
NA

----

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

---------

Co-authored-by: John DiSanti <[email protected]>
Co-authored-by: John DiSanti <[email protected]>
  • Loading branch information
3 people authored Jun 14, 2023
1 parent 45f2711 commit 1e2c03c
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 10 deletions.
40 changes: 37 additions & 3 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
message = "Fix bug in AWS JSON 1.x routers where, if a service had more than 14 operations, the router was created without the route for the 15th operation."
author = "thor-bjorgvinsson"
references = ["smithy-rs#2733"]
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" ="server" }
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "server" }

[[aws-sdk-rust]]
message = "Remove native-tls and add a migration guide."
Expand Down Expand Up @@ -66,7 +66,7 @@ author = "jdisanti"
[[smithy-rs]]
message = "For event stream operations, the `EventStreamSender` in inputs/outputs now requires the passed in `Stream` impl to implement `Sync`."
references = ["smithy-rs#2673"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"}
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" }
author = "jdisanti"

[[aws-sdk-rust]]
Expand Down Expand Up @@ -143,7 +143,7 @@ author = "jdisanti"
[[smithy-rs]]
message = "Update MSRV to Rust 1.68.2"
references = ["smithy-rs#2745"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"}
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" }
author = "jdisanti"

[[smithy-rs]]
Expand Down Expand Up @@ -408,3 +408,37 @@ let scoped_plugin = Scoped::new::<SomeScope>(plugin);
references = ["smithy-rs#2740", "smithy-rs#2759"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "hlbarber"

[[smithy-rs]]
message = "Implement unstable serde support for the `Number`, `Blob`, `Document`, `DateTime` primitives"
author = "thomas-k-cameron"
meta = { "breaking" = false, "tada" = true, "bug" = false, target = "all" }
references = [
"smithy-rs#2647",
"smithy-rs#2645",
"smithy-rs#2646",
"smithy-rs#2616",
]

[[aws-sdk-rust]]
message = "Implement unstable serde support for the `Number`, `Blob`, `Document`, `DateTime` primitives"
author = "thomas-k-cameron"
meta = { "breaking" = false, "tada" = true, "bug" = false }
references = [
"smithy-rs#2647",
"smithy-rs#2645",
"smithy-rs#2646",
"smithy-rs#2616",
]

[[smithy-rs]]
message = "Add a `send_with` function on `-Input` types for sending requests without fluent builders"
author = "thomas-k-cameron"
references = ["smithy-rs#2652"]
meta = { "breaking" = false, "tada" = true, "bug" = false, target = "client" }

[[aws-sdk-rust]]
message = "Add a `send_with` function on `-Input` types for sending requests without fluent builders"
author = "thomas-k-cameron"
references = ["smithy-rs#2652"]
meta = { "breaking" = false, "tada" = true, "bug" = false }
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.docLink
import software.amazon.smithy.rust.codegen.core.rustlang.docs
import software.amazon.smithy.rust.codegen.core.rustlang.documentShape
import software.amazon.smithy.rust.codegen.core.rustlang.escape
import software.amazon.smithy.rust.codegen.core.rustlang.implBlock
import software.amazon.smithy.rust.codegen.core.rustlang.normalizeHtml
import software.amazon.smithy.rust.codegen.core.rustlang.qualifiedName
import software.amazon.smithy.rust.codegen.core.rustlang.render
Expand Down Expand Up @@ -315,10 +316,44 @@ class FluentClientGenerator(
}

private fun RustWriter.renderFluentBuilder(operation: OperationShape) {
val outputType = symbolProvider.toSymbol(operation.outputShape(model))
val errorType = symbolProvider.symbolForOperationError(operation)
val operationSymbol = symbolProvider.toSymbol(operation)

val input = operation.inputShape(model)
val baseDerives = symbolProvider.toSymbol(input).expectRustMetadata().derives
// Filter out any derive that isn't Clone. Then add a Debug derive
// input name
val fnName = clientOperationFnName(operation, symbolProvider)
implBlock(symbolProvider.symbolForBuilder(input)) {
rustTemplate(
"""
/// Sends a request with this input using the given client.
pub async fn send_with${generics.inst}(self, client: &crate::Client${generics.inst}) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{RawResponseType}>>
#{send_bounds:W}
#{boundsWithoutWhereClause:W}
{
let mut fluent_builder = client.$fnName();
fluent_builder.inner = self;
fluent_builder.send().await
}
""",
*preludeScope,
"RawResponseType" to if (codegenContext.smithyRuntimeMode.defaultToMiddleware) {
RuntimeType.smithyHttp(runtimeConfig).resolve("operation::Response")
} else {
RuntimeType.smithyRuntimeApi(runtimeConfig).resolve("client::orchestrator::HttpResponse")
},
"Operation" to operationSymbol,
"OperationError" to errorType,
"OperationOutput" to outputType,
"SdkError" to RuntimeType.sdkError(runtimeConfig),
"SdkSuccess" to RuntimeType.sdkSuccess(runtimeConfig),
"boundsWithoutWhereClause" to generics.boundsWithoutWhereClause,
"send_bounds" to generics.sendBounds(operationSymbol, outputType, errorType, retryClassifier),
)
}

val derives = baseDerives.filter { it == RuntimeType.Clone } + RuntimeType.Debug
docs("Fluent builder constructing a request to `${operationSymbol.name}`.\n")

Expand Down Expand Up @@ -350,9 +385,6 @@ class FluentClientGenerator(
"client" to RuntimeType.smithyClient(runtimeConfig),
"bounds" to generics.bounds,
) {
val outputType = symbolProvider.toSymbol(operation.outputShape(model))
val errorType = symbolProvider.symbolForOperationError(operation)

rust("/// Creates a new `${operationSymbol.name}`.")
withBlockTemplate(
"pub(crate) fn new(handle: #{Arc}<crate::client::Handle${generics.inst}>) -> Self {",
Expand All @@ -370,6 +402,7 @@ class FluentClientGenerator(
}
}
}

if (smithyRuntimeMode.generateMiddleware) {
val middlewareScope = arrayOf(
*preludeScope,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ interface FluentClientGenerics {

/** Convert this `FluentClientGenerics` into the more general `RustGenerics` */
fun toRustGenerics(): RustGenerics

/** bounds without where clause. If bounds does is not prefixed with `where\n`, then it gets the same value. **/
val boundsWithoutWhereClause: Writable
}

class NoClientGenerics(private val runtimeConfig: RuntimeConfig) : FluentClientGenerics {
Expand All @@ -55,6 +58,8 @@ class NoClientGenerics(private val runtimeConfig: RuntimeConfig) : FluentClientG
/** Trait bounds */
override val bounds = writable { }

override val boundsWithoutWhereClause = writable {}

/** Bounds for generated `send()` functions */
override fun sendBounds(
operation: Symbol,
Expand Down Expand Up @@ -94,9 +99,18 @@ data class FlexibleClientGenerics(
rustTemplate(
"""
where
C: #{client}::bounds::SmithyConnector,
M: #{client}::bounds::SmithyMiddleware<C>,
R: #{client}::retry::NewRequestPolicy,
#{bounds}
""",
"bounds" to boundsWithoutWhereClause,
)
}

override val boundsWithoutWhereClause = writable {
rustTemplate(
"""
C: #{client}::bounds::SmithyConnector,
M: #{client}::bounds::SmithyMiddleware<C>,
R: #{client}::retry::NewRequestPolicy,
""",
"client" to client,
)
Expand All @@ -112,7 +126,7 @@ data class FlexibleClientGenerics(
#{OperationOutput},
#{OperationError},
#{RetryClassifier}
>
>,
""",
"client" to client,
"Operation" to operation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import java.nio.file.Path
sealed class DependencyScope {
object Dev : DependencyScope()
object Compile : DependencyScope()
object CfgUnstable : DependencyScope()
object Build : DependencyScope()
}

Expand Down Expand Up @@ -283,5 +284,8 @@ data class CargoDependency(
fun smithyRuntimeApi(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-runtime-api")
fun smithyTypes(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-types")
fun smithyXml(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-xml")

// behind feature-gate
val Serde = CargoDependency("serde", CratesIo("1.0"), features = setOf("derive"), scope = DependencyScope.CfgUnstable)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,23 @@ class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) {
}
}

// These were supposed to be a part of companion object but we decided to move it out to here to avoid NPE
// You can find the discussion here.
// https://github.com/awslabs/smithy-rs/discussions/2248
public fun SerdeSerialize(): Attribute {
return Attribute(cfgAttr(all(writable("aws_sdk_unstable"), feature("serde-serialize")), derive(RuntimeType.SerdeSerialize)))
}
public fun SerdeDeserialize(): Attribute {
return Attribute(cfgAttr(all(writable("aws_sdk_unstable"), feature("serde-deserialize")), derive(RuntimeType.SerdeDeserialize)))
}
public fun SerdeSkip(): Attribute {
return Attribute(cfgAttr(all(writable("aws_sdk_unstable"), any(feature("serde-serialize"), feature("serde-deserialize"))), serde("skip")))
}

public fun SerdeSerializeOrDeserialize(): Attribute {
return Attribute(cfg(all(writable("aws_sdk_unstable"), any(feature("serde-serialize"), feature("serde-deserialize")))))
}

companion object {
val AllowClippyBoxedLocal = Attribute(allow("clippy::boxed_local"))
val AllowClippyLetAndReturn = Attribute(allow("clippy::let_and_return"))
Expand Down Expand Up @@ -504,6 +521,7 @@ class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) {

val Test = Attribute("test")
val TokioTest = Attribute(RuntimeType.Tokio.resolve("test").writable)
val AwsSdkUnstableAttribute = Attribute(cfg("aws_sdk_unstable"))

/**
* [non_exhaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute)
Expand Down Expand Up @@ -532,10 +550,12 @@ class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) {
}

fun all(vararg attrMacros: Writable): Writable = macroWithArgs("all", *attrMacros)
fun cfgAttr(vararg attrMacros: Writable): Writable = macroWithArgs("cfg_attr", *attrMacros)

fun allow(lints: Collection<String>): Writable = macroWithArgs("allow", *lints.toTypedArray())
fun allow(vararg lints: String): Writable = macroWithArgs("allow", *lints)
fun deny(vararg lints: String): Writable = macroWithArgs("deny", *lints)
fun serde(vararg lints: String): Writable = macroWithArgs("serde", *lints)
fun any(vararg attrMacros: Writable): Writable = macroWithArgs("any", *attrMacros)
fun cfg(vararg attrMacros: Writable): Writable = macroWithArgs("cfg", *attrMacros)
fun cfg(vararg attrMacros: String): Writable = macroWithArgs("cfg", *attrMacros)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null)
val ConstrainedTrait = RuntimeType("crate::constrained::Constrained", InlineDependency.constrained())
val MaybeConstrained = RuntimeType("crate::constrained::MaybeConstrained", InlineDependency.constrained())

// serde types. Gated behind `CfgUnstable`.
val Serde = CargoDependency.Serde.toType()
val SerdeSerialize = Serde.resolve("Serialize")
val SerdeDeserialize = Serde.resolve("Deserialize")

// smithy runtime types
fun smithyAsync(runtimeConfig: RuntimeConfig) = CargoDependency.smithyAsync(runtimeConfig).toType()
fun smithyChecksums(runtimeConfig: RuntimeConfig) = CargoDependency.smithyChecksums(runtimeConfig).toType()
Expand Down

0 comments on commit 1e2c03c

Please sign in to comment.