Skip to content

Commit 1e2c03c

Browse files
Add send_with method to fluent builders (#2652)
## 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 <johndisanti@gmail.com> Co-authored-by: John DiSanti <jdisanti@amazon.com>
1 parent 45f2711 commit 1e2c03c

File tree

6 files changed

+120
-10
lines changed

6 files changed

+120
-10
lines changed

CHANGELOG.next.toml

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
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."
1616
author = "thor-bjorgvinsson"
1717
references = ["smithy-rs#2733"]
18-
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" ="server" }
18+
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "server" }
1919

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

7272
[[aws-sdk-rust]]
@@ -143,7 +143,7 @@ author = "jdisanti"
143143
[[smithy-rs]]
144144
message = "Update MSRV to Rust 1.68.2"
145145
references = ["smithy-rs#2745"]
146-
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"}
146+
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" }
147147
author = "jdisanti"
148148

149149
[[smithy-rs]]
@@ -408,3 +408,37 @@ let scoped_plugin = Scoped::new::<SomeScope>(plugin);
408408
references = ["smithy-rs#2740", "smithy-rs#2759"]
409409
meta = { "breaking" = true, "tada" = false, "bug" = false }
410410
author = "hlbarber"
411+
412+
[[smithy-rs]]
413+
message = "Implement unstable serde support for the `Number`, `Blob`, `Document`, `DateTime` primitives"
414+
author = "thomas-k-cameron"
415+
meta = { "breaking" = false, "tada" = true, "bug" = false, target = "all" }
416+
references = [
417+
"smithy-rs#2647",
418+
"smithy-rs#2645",
419+
"smithy-rs#2646",
420+
"smithy-rs#2616",
421+
]
422+
423+
[[aws-sdk-rust]]
424+
message = "Implement unstable serde support for the `Number`, `Blob`, `Document`, `DateTime` primitives"
425+
author = "thomas-k-cameron"
426+
meta = { "breaking" = false, "tada" = true, "bug" = false }
427+
references = [
428+
"smithy-rs#2647",
429+
"smithy-rs#2645",
430+
"smithy-rs#2646",
431+
"smithy-rs#2616",
432+
]
433+
434+
[[smithy-rs]]
435+
message = "Add a `send_with` function on `-Input` types for sending requests without fluent builders"
436+
author = "thomas-k-cameron"
437+
references = ["smithy-rs#2652"]
438+
meta = { "breaking" = false, "tada" = true, "bug" = false, target = "client" }
439+
440+
[[aws-sdk-rust]]
441+
message = "Add a `send_with` function on `-Input` types for sending requests without fluent builders"
442+
author = "thomas-k-cameron"
443+
references = ["smithy-rs#2652"]
444+
meta = { "breaking" = false, "tada" = true, "bug" = false }

codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.docLink
3030
import software.amazon.smithy.rust.codegen.core.rustlang.docs
3131
import software.amazon.smithy.rust.codegen.core.rustlang.documentShape
3232
import software.amazon.smithy.rust.codegen.core.rustlang.escape
33+
import software.amazon.smithy.rust.codegen.core.rustlang.implBlock
3334
import software.amazon.smithy.rust.codegen.core.rustlang.normalizeHtml
3435
import software.amazon.smithy.rust.codegen.core.rustlang.qualifiedName
3536
import software.amazon.smithy.rust.codegen.core.rustlang.render
@@ -315,10 +316,44 @@ class FluentClientGenerator(
315316
}
316317

317318
private fun RustWriter.renderFluentBuilder(operation: OperationShape) {
319+
val outputType = symbolProvider.toSymbol(operation.outputShape(model))
320+
val errorType = symbolProvider.symbolForOperationError(operation)
318321
val operationSymbol = symbolProvider.toSymbol(operation)
322+
319323
val input = operation.inputShape(model)
320324
val baseDerives = symbolProvider.toSymbol(input).expectRustMetadata().derives
321325
// Filter out any derive that isn't Clone. Then add a Debug derive
326+
// input name
327+
val fnName = clientOperationFnName(operation, symbolProvider)
328+
implBlock(symbolProvider.symbolForBuilder(input)) {
329+
rustTemplate(
330+
"""
331+
/// Sends a request with this input using the given client.
332+
pub async fn send_with${generics.inst}(self, client: &crate::Client${generics.inst}) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{RawResponseType}>>
333+
#{send_bounds:W}
334+
#{boundsWithoutWhereClause:W}
335+
{
336+
let mut fluent_builder = client.$fnName();
337+
fluent_builder.inner = self;
338+
fluent_builder.send().await
339+
}
340+
""",
341+
*preludeScope,
342+
"RawResponseType" to if (codegenContext.smithyRuntimeMode.defaultToMiddleware) {
343+
RuntimeType.smithyHttp(runtimeConfig).resolve("operation::Response")
344+
} else {
345+
RuntimeType.smithyRuntimeApi(runtimeConfig).resolve("client::orchestrator::HttpResponse")
346+
},
347+
"Operation" to operationSymbol,
348+
"OperationError" to errorType,
349+
"OperationOutput" to outputType,
350+
"SdkError" to RuntimeType.sdkError(runtimeConfig),
351+
"SdkSuccess" to RuntimeType.sdkSuccess(runtimeConfig),
352+
"boundsWithoutWhereClause" to generics.boundsWithoutWhereClause,
353+
"send_bounds" to generics.sendBounds(operationSymbol, outputType, errorType, retryClassifier),
354+
)
355+
}
356+
322357
val derives = baseDerives.filter { it == RuntimeType.Clone } + RuntimeType.Debug
323358
docs("Fluent builder constructing a request to `${operationSymbol.name}`.\n")
324359

@@ -350,9 +385,6 @@ class FluentClientGenerator(
350385
"client" to RuntimeType.smithyClient(runtimeConfig),
351386
"bounds" to generics.bounds,
352387
) {
353-
val outputType = symbolProvider.toSymbol(operation.outputShape(model))
354-
val errorType = symbolProvider.symbolForOperationError(operation)
355-
356388
rust("/// Creates a new `${operationSymbol.name}`.")
357389
withBlockTemplate(
358390
"pub(crate) fn new(handle: #{Arc}<crate::client::Handle${generics.inst}>) -> Self {",
@@ -370,6 +402,7 @@ class FluentClientGenerator(
370402
}
371403
}
372404
}
405+
373406
if (smithyRuntimeMode.generateMiddleware) {
374407
val middlewareScope = arrayOf(
375408
*preludeScope,

codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerics.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ interface FluentClientGenerics {
3434

3535
/** Convert this `FluentClientGenerics` into the more general `RustGenerics` */
3636
fun toRustGenerics(): RustGenerics
37+
38+
/** bounds without where clause. If bounds does is not prefixed with `where\n`, then it gets the same value. **/
39+
val boundsWithoutWhereClause: Writable
3740
}
3841

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

61+
override val boundsWithoutWhereClause = writable {}
62+
5863
/** Bounds for generated `send()` functions */
5964
override fun sendBounds(
6065
operation: Symbol,
@@ -94,9 +99,18 @@ data class FlexibleClientGenerics(
9499
rustTemplate(
95100
"""
96101
where
97-
C: #{client}::bounds::SmithyConnector,
98-
M: #{client}::bounds::SmithyMiddleware<C>,
99-
R: #{client}::retry::NewRequestPolicy,
102+
#{bounds}
103+
""",
104+
"bounds" to boundsWithoutWhereClause,
105+
)
106+
}
107+
108+
override val boundsWithoutWhereClause = writable {
109+
rustTemplate(
110+
"""
111+
C: #{client}::bounds::SmithyConnector,
112+
M: #{client}::bounds::SmithyMiddleware<C>,
113+
R: #{client}::retry::NewRequestPolicy,
100114
""",
101115
"client" to client,
102116
)
@@ -112,7 +126,7 @@ data class FlexibleClientGenerics(
112126
#{OperationOutput},
113127
#{OperationError},
114128
#{RetryClassifier}
115-
>
129+
>,
116130
""",
117131
"client" to client,
118132
"Operation" to operation,

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import java.nio.file.Path
1616
sealed class DependencyScope {
1717
object Dev : DependencyScope()
1818
object Compile : DependencyScope()
19+
object CfgUnstable : DependencyScope()
1920
object Build : DependencyScope()
2021
}
2122

@@ -283,5 +284,8 @@ data class CargoDependency(
283284
fun smithyRuntimeApi(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-runtime-api")
284285
fun smithyTypes(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-types")
285286
fun smithyXml(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-xml")
287+
288+
// behind feature-gate
289+
val Serde = CargoDependency("serde", CratesIo("1.0"), features = setOf("derive"), scope = DependencyScope.CfgUnstable)
286290
}
287291
}

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,23 @@ class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) {
475475
}
476476
}
477477

478+
// These were supposed to be a part of companion object but we decided to move it out to here to avoid NPE
479+
// You can find the discussion here.
480+
// https://github.com/awslabs/smithy-rs/discussions/2248
481+
public fun SerdeSerialize(): Attribute {
482+
return Attribute(cfgAttr(all(writable("aws_sdk_unstable"), feature("serde-serialize")), derive(RuntimeType.SerdeSerialize)))
483+
}
484+
public fun SerdeDeserialize(): Attribute {
485+
return Attribute(cfgAttr(all(writable("aws_sdk_unstable"), feature("serde-deserialize")), derive(RuntimeType.SerdeDeserialize)))
486+
}
487+
public fun SerdeSkip(): Attribute {
488+
return Attribute(cfgAttr(all(writable("aws_sdk_unstable"), any(feature("serde-serialize"), feature("serde-deserialize"))), serde("skip")))
489+
}
490+
491+
public fun SerdeSerializeOrDeserialize(): Attribute {
492+
return Attribute(cfg(all(writable("aws_sdk_unstable"), any(feature("serde-serialize"), feature("serde-deserialize")))))
493+
}
494+
478495
companion object {
479496
val AllowClippyBoxedLocal = Attribute(allow("clippy::boxed_local"))
480497
val AllowClippyLetAndReturn = Attribute(allow("clippy::let_and_return"))
@@ -504,6 +521,7 @@ class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) {
504521

505522
val Test = Attribute("test")
506523
val TokioTest = Attribute(RuntimeType.Tokio.resolve("test").writable)
524+
val AwsSdkUnstableAttribute = Attribute(cfg("aws_sdk_unstable"))
507525

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

534552
fun all(vararg attrMacros: Writable): Writable = macroWithArgs("all", *attrMacros)
553+
fun cfgAttr(vararg attrMacros: Writable): Writable = macroWithArgs("cfg_attr", *attrMacros)
535554

536555
fun allow(lints: Collection<String>): Writable = macroWithArgs("allow", *lints.toTypedArray())
537556
fun allow(vararg lints: String): Writable = macroWithArgs("allow", *lints)
538557
fun deny(vararg lints: String): Writable = macroWithArgs("deny", *lints)
558+
fun serde(vararg lints: String): Writable = macroWithArgs("serde", *lints)
539559
fun any(vararg attrMacros: Writable): Writable = macroWithArgs("any", *attrMacros)
540560
fun cfg(vararg attrMacros: Writable): Writable = macroWithArgs("cfg", *attrMacros)
541561
fun cfg(vararg attrMacros: String): Writable = macroWithArgs("cfg", *attrMacros)

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,11 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null)
301301
val ConstrainedTrait = RuntimeType("crate::constrained::Constrained", InlineDependency.constrained())
302302
val MaybeConstrained = RuntimeType("crate::constrained::MaybeConstrained", InlineDependency.constrained())
303303

304+
// serde types. Gated behind `CfgUnstable`.
305+
val Serde = CargoDependency.Serde.toType()
306+
val SerdeSerialize = Serde.resolve("Serialize")
307+
val SerdeDeserialize = Serde.resolve("Deserialize")
308+
304309
// smithy runtime types
305310
fun smithyAsync(runtimeConfig: RuntimeConfig) = CargoDependency.smithyAsync(runtimeConfig).toType()
306311
fun smithyChecksums(runtimeConfig: RuntimeConfig) = CargoDependency.smithyChecksums(runtimeConfig).toType()

0 commit comments

Comments
 (0)