forked from smithy-lang/smithy-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SdkConfigDecorator.kt
163 lines (147 loc) · 6.6 KB
/
SdkConfigDecorator.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package software.amazon.smithy.rustsdk
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule
import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfig
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
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.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RustCrate
import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocCustomization
import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocSection
import software.amazon.smithy.rust.codegen.core.smithy.customize.adhocCustomization
import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations
sealed class SdkConfigSection(name: String) : AdHocSection(name) {
/**
* [sdkConfig]: A reference to the SDK config struct
* [serviceConfigBuilder]: A reference (owned) to the `<service>::config::Builder` struct.
*
* Each invocation of this section MUST be a complete statement (ending with a semicolon), e.g:
* ```
* rust("${section.serviceConfigBuilder}.set_foo(${section.sdkConfig}.foo());")
* ```
*/
data class CopySdkConfigToClientConfig(val sdkConfig: String, val serviceConfigBuilder: String) :
SdkConfigSection("CopySdkConfigToClientConfig")
}
/**
* Section enabling linkage between `SdkConfig` and <service>::Config
*/
object SdkConfigCustomization {
/**
* Copy a field from SDK config to service config with an optional map block.
*
* This handles the common case where the field name is identical in both cases and an accessor is used.
*
* # Examples
* ```kotlin
* SdkConfigCustomization.copyField("some_string_field") { rust("|s|s.to_to_string()") }
* ```
*/
fun copyField(fieldName: String, map: Writable?) =
adhocCustomization<SdkConfigSection.CopySdkConfigToClientConfig> { section ->
val mapBlock = map?.let { writable { rust(".map(#W)", it) } } ?: writable { }
rustTemplate(
"${section.serviceConfigBuilder}.set_$fieldName(${section.sdkConfig}.$fieldName()#{map});",
"map" to mapBlock,
)
}
}
/**
* SdkConfig -> <service>::Config for settings that come from generic smithy
*/
class GenericSmithySdkConfigSettings : ClientCodegenDecorator {
override val name: String = "GenericSmithySdkConfigSettings"
override val order: Byte = 0
override fun extraSections(codegenContext: ClientCodegenContext): List<AdHocCustomization> =
listOf(
adhocCustomization<SdkConfigSection.CopySdkConfigToClientConfig> { section ->
rust(
"""
// resiliency
${section.serviceConfigBuilder}.set_retry_config(${section.sdkConfig}.retry_config().cloned());
${section.serviceConfigBuilder}.set_timeout_config(${section.sdkConfig}.timeout_config().cloned());
${section.serviceConfigBuilder}.set_sleep_impl(${section.sdkConfig}.sleep_impl());
${section.serviceConfigBuilder}.set_http_connector(${section.sdkConfig}.http_connector().cloned());
""",
)
},
)
}
/**
* Adds functionality for constructing `<service>::Config` objects from `aws_types::SdkConfig`s
*
* - `From<&aws_types::SdkConfig> for <service>::config::Builder`: Enabling customization
* - `pub fn new(&aws_types::SdkConfig) -> <service>::Config`: Direct construction without customization
*/
class SdkConfigDecorator : ClientCodegenDecorator {
override val name: String = "SdkConfig"
override val order: Byte = 0
override fun configCustomizations(
codegenContext: ClientCodegenContext,
baseCustomizations: List<ConfigCustomization>,
): List<ConfigCustomization> {
return baseCustomizations + NewFromShared(codegenContext.runtimeConfig)
}
override fun extras(codegenContext: ClientCodegenContext, rustCrate: RustCrate) {
val codegenScope = arrayOf(
"SdkConfig" to AwsRuntimeType.awsTypes(codegenContext.runtimeConfig).resolve("sdk_config::SdkConfig"),
)
rustCrate.withModule(ClientRustModule.Config) {
rustTemplate(
"""
impl From<&#{SdkConfig}> for Builder {
fn from(input: &#{SdkConfig}) -> Self {
let mut builder = Builder::default();
#{augmentBuilder:W}
builder
}
}
impl From<&#{SdkConfig}> for Config {
fn from(sdk_config: &#{SdkConfig}) -> Self {
Builder::from(sdk_config).build()
}
}
""",
"augmentBuilder" to writable {
writeCustomizations(
codegenContext.rootDecorator.extraSections(codegenContext),
SdkConfigSection.CopySdkConfigToClientConfig(
sdkConfig = "input",
serviceConfigBuilder = "builder",
),
)
},
*codegenScope,
)
}
}
}
class NewFromShared(runtimeConfig: RuntimeConfig) : ConfigCustomization() {
private val codegenScope = arrayOf(
"SdkConfig" to AwsRuntimeType.awsTypes(runtimeConfig).resolve("sdk_config::SdkConfig"),
)
override fun section(section: ServiceConfig): Writable {
return when (section) {
ServiceConfig.ConfigImpl -> writable {
rustTemplate(
"""
/// Creates a new [service config](crate::Config) from a [shared `config`](#{SdkConfig}).
pub fn new(config: &#{SdkConfig}) -> Self {
Builder::from(config).build()
}
""",
*codegenScope,
)
}
else -> emptySection
}
}
}