A key-value map of query string parameters that specify properties of the export, depending on the requested exportType. For exportTypeoas30 and swagger, any combination of the following parameters are supported: extensions='integrations' or extensions='apigateway' will export the API with x-amazon-apigateway-integration extensions. extensions='authorizers' will export the API with x-amazon-apigateway-authorizer extensions. postman will export the API with Postman extensions, allowing for import to the Postman tool
"
+ "smithy.api#documentation": "
A key-value map of query string parameters that specify properties of the export, depending on the requested exportType. For exportTypeoas30 and swagger, any combination of the following parameters are supported: extensions='integrations' or extensions='apigateway' will export the API with x-amazon-apigateway-integration extensions. extensions='authorizers' will export the API with x-amazon-apigateway-authorizer extensions. postman will export the API with Postman extensions, allowing for import to the Postman tool
A string-to-string key-value map of query parameters sdkType-dependent properties of the SDK. For sdkType of objectivec or swift, a parameter named classPrefix is required. For sdkType of android, parameters named groupId, artifactId, artifactVersion, and invokerPackage are required. For sdkType of java, parameters named serviceName and javaPackageName are required.
"
+ "smithy.api#documentation": "
A string-to-string key-value map of query parameters sdkType-dependent properties of the SDK. For sdkType of objectivec or swift, a parameter named classPrefix is required. For sdkType of android, parameters named groupId, artifactId, artifactVersion, and invokerPackage are required. For sdkType of java, parameters named serviceName and javaPackageName are required.
A query parameter to specify whether to rollback the documentation importation (true) or not (false) when a warning is encountered. The default value is false.
A key-value map of context-specific query string parameters specifying the behavior of different API importing operations. The following shows operation-specific parameters and their supported values.
\n
To exclude DocumentationParts from the import, set parameters as ignore=documentation.
\n
To configure the endpoint type, set parameters as endpointConfigurationTypes=EDGE, endpointConfigurationTypes=REGIONAL, or endpointConfigurationTypes=PRIVATE. The default endpoint type is EDGE.
\n
To handle imported basepath, set parameters as basepath=ignore, basepath=prepend or basepath=split.
\n
For example, the AWS CLI command to exclude documentation from the imported API is:
A key-value map of context-specific query string parameters specifying the behavior of different API importing operations. The following shows operation-specific parameters and their supported values.
\n
To exclude DocumentationParts from the import, set parameters as ignore=documentation.
\n
To configure the endpoint type, set parameters as endpointConfigurationTypes=EDGE, endpointConfigurationTypes=REGIONAL, or endpointConfigurationTypes=PRIVATE. The default endpoint type is EDGE.
\n
To handle imported basepath, set parameters as basepath=ignore, basepath=prepend or basepath=split.
\n
For example, the AWS CLI command to exclude documentation from the imported API is:
[Required] The POST request body containing external API definitions. Currently, only OpenAPI definition JSON/YAML files are supported. The maximum size of the API definition file is 6MB.
Custom header parameters as part of the request. For example, to exclude DocumentationParts from an imported API, set ignore=documentation as a parameters value, as in the AWS CLI command of aws apigateway import-rest-api --parameters ignore=documentation --body 'file:///path/to/imported-api-body.json'.
"
+ "smithy.api#documentation": "
Custom header parameters as part of the request. For example, to exclude DocumentationParts from an imported API, set ignore=documentation as a parameters value, as in the AWS CLI command of aws apigateway import-rest-api --parameters ignore=documentation --body 'file:///path/to/imported-api-body.json'.
[Required] The PUT request body containing external API definitions. Currently, only OpenAPI definition JSON/YAML files are supported. The maximum size of the API definition file is 6MB.
",
+ "smithy.api#httpPayload": {},
+ "smithy.api#required": {}
}
}
},
diff --git a/codegen-test/model/naming-obstacle-course.smithy b/codegen-test/model/naming-obstacle-course.smithy
index 2425e50778..ae230993dc 100644
--- a/codegen-test/model/naming-obstacle-course.smithy
+++ b/codegen-test/model/naming-obstacle-course.smithy
@@ -48,11 +48,10 @@ structure ReservedWords {
protocol: awsJson1_1,
params: {
"regular_string": "hello!",
- "punned_string": { "ps_member": true },
},
method: "POST",
uri: "/",
- body: "{\"regular_string\": \"hello!\", \"punned_string\": { \"ps_member\": true }}",
+ body: "{\"regular_string\": \"hello!\"}",
bodyMediaType: "application/json"
}
])
@@ -62,7 +61,6 @@ operation StructureNamePunning {
structure StructureNamePunningInput {
regular_string: smithy.api#String,
- punned_string: crate#String,
punned_vec: Vec
}
@@ -70,9 +68,6 @@ structure Vec {
pv_member: Boolean
}
-structure String {
- ps_member: Boolean
-}
operation ErrCollisions {
errors: [
diff --git a/codegen-test/model/rest-json-extras.smithy b/codegen-test/model/rest-json-extras.smithy
index 565f557589..8c81d2dfe6 100644
--- a/codegen-test/model/rest-json-extras.smithy
+++ b/codegen-test/model/rest-json-extras.smithy
@@ -7,6 +7,46 @@ use aws.api#service
use smithy.test#httpRequestTests
use smithy.test#httpResponseTests
+apply QueryPrecedence @httpRequestTests([
+ {
+ id: "UrlParamsKeyEncoding",
+ documentation: "Keys and values must be url encoded",
+ protocol: restJson1,
+ method: "POST",
+ uri: "/Precedence",
+ body: "",
+ queryParams: ["bar=%26%F0%9F%90%B1", "hello%20there=how's%20your%20encoding?", "a%20%26%20b%20%26%20c=better%20encode%20%3D%20this"],
+ params: {
+ foo: "&🐱",
+ baz: {
+ "hello there": "how's your encoding?",
+ "a & b & c": "better encode = this"
+ }
+ },
+ appliesTo: "client",
+ },
+ {
+ id: "RestJsonQueryPrecedenceForbid",
+ documentation: "Prefer named query parameters when serializing",
+ protocol: restJson1,
+ method: "POST",
+ uri: "/Precedence",
+ body: "",
+ queryParams: [
+ "bar=named",
+ "qux=alsoFromMap"
+ ],
+ forbidQueryParams: ["bar=fromMap"],
+ params: {
+ foo: "named",
+ baz: {
+ bar: "fromMap",
+ qux: "alsoFromMap"
+ }
+ },
+ appliesTo: "client",
+ }]
+)
/// A REST JSON service that sends JSON requests and responses.
@service(sdkId: "Rest Json Protocol")
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt
index cff9a4ce36..8cf628e63d 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt
@@ -283,7 +283,7 @@ class RustWriter private constructor(
}
}
- fun ListForEach(
+ fun listForEach(
target: Shape,
outerField: String,
block: CodeWriter.(field: String, target: ShapeId) -> Unit
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenVisitor.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenVisitor.kt
index 321c42a0d3..5d5bf3b941 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenVisitor.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenVisitor.kt
@@ -59,7 +59,7 @@ class CodegenVisitor(context: PluginContext, private val codegenDecorator: RustC
).protocolFor(context.model, service)
protocolGenerator = generator
model = generator.transformModel(baseModel)
- val baseProvider = RustCodegenPlugin.BaseSymbolProvider(model, symbolVisitorConfig)
+ val baseProvider = RustCodegenPlugin.baseSymbolProvider(model, service, symbolVisitorConfig)
symbolProvider = codegenDecorator.symbolProvider(generator.symbolProvider(model, baseProvider))
protocolConfig =
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt
index a215cf0ea6..b1f9382ac1 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt
@@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.smithy
import software.amazon.smithy.build.PluginContext
import software.amazon.smithy.build.SmithyBuildPlugin
import software.amazon.smithy.model.Model
+import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.rust.codegen.rustlang.RustReservedWordSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.customize.CombinedCodegenDecorator
@@ -20,8 +21,8 @@ class RustCodegenPlugin : SmithyBuildPlugin {
}
companion object {
- fun BaseSymbolProvider(model: Model, symbolVisitorConfig: SymbolVisitorConfig = DefaultConfig) =
- SymbolVisitor(model, config = symbolVisitorConfig)
+ fun baseSymbolProvider(model: Model, serviceShape: ServiceShape, symbolVisitorConfig: SymbolVisitorConfig = DefaultConfig) =
+ SymbolVisitor(model, serviceShape = serviceShape, config = symbolVisitorConfig)
.let { BaseSymbolMetadataProvider(it) }
.let { RustReservedWordSymbolProvider(it) }
}
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/SymbolVisitor.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/SymbolVisitor.kt
index 11901d80af..7bad1b8696 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/SymbolVisitor.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/SymbolVisitor.kt
@@ -122,6 +122,7 @@ interface RustSymbolProvider : SymbolProvider {
class SymbolVisitor(
private val model: Model,
+ private val serviceShape: ServiceShape?,
private val config: SymbolVisitorConfig = DefaultConfig
) : RustSymbolProvider,
ShapeVisitor {
@@ -132,6 +133,14 @@ class SymbolVisitor(
return shape.accept(this)
}
+ private fun Shape.contextName(): String {
+ return if (serviceShape != null) {
+ id.getName(serviceShape)
+ } else {
+ id.name
+ }
+ }
+
override fun toMemberName(shape: MemberShape): String = shape.memberName.toSnakeCase()
override fun blobShape(shape: BlobShape?): Symbol {
@@ -173,7 +182,7 @@ class SymbolVisitor(
override fun doubleShape(shape: DoubleShape): Symbol = simpleShape(shape)
override fun stringShape(shape: StringShape): Symbol {
return if (shape.hasTrait(EnumTrait::class.java)) {
- symbolBuilder(shape, RustType.Opaque(shape.id.name)).locatedIn(Models).build()
+ symbolBuilder(shape, RustType.Opaque(shape.contextName())).locatedIn(Models).build()
} else {
simpleShape(shape)
}
@@ -218,7 +227,7 @@ class SymbolVisitor(
}
override fun operationShape(shape: OperationShape): Symbol {
- return symbolBuilder(shape, RustType.Opaque(shape.id.name.capitalize())).locatedIn(Operations).build()
+ return symbolBuilder(shape, RustType.Opaque(shape.contextName().capitalize())).locatedIn(Operations).build()
}
override fun resourceShape(shape: ResourceShape?): Symbol {
@@ -234,7 +243,7 @@ class SymbolVisitor(
val isInput = shape.hasTrait(SyntheticInputTrait::class.java)
val isOutput = shape.hasTrait(SyntheticOutputTrait::class.java)
val isBody = shape.hasTrait(InputBodyTrait::class.java) || shape.hasTrait(OutputBodyTrait::class.java)
- val name = StringUtils.capitalize(shape.id.name).letIf(isError && config.codegenConfig.renameExceptions) {
+ val name = StringUtils.capitalize(shape.contextName()).letIf(isError && config.codegenConfig.renameExceptions) {
// TODO: Do we want to do this?
// https://github.com/awslabs/smithy-rs/issues/77
it.replace("Exception", "Error")
@@ -250,7 +259,7 @@ class SymbolVisitor(
}
override fun unionShape(shape: UnionShape): Symbol {
- val name = StringUtils.capitalize(shape.id.name)
+ val name = StringUtils.capitalize(shape.contextName())
val builder = symbolBuilder(shape, RustType.Opaque(name)).locatedIn(Models)
return builder.build()
@@ -284,7 +293,6 @@ class SymbolVisitor(
// TODO(chore): Move this to a useful place
private const val RUST_TYPE_KEY = "rusttype"
private const val SHAPE_KEY = "shape"
-private const val CAN_USE_DEFAULT = "canusedefault"
private const val SYMBOL_DEFAULT = "symboldefault"
fun Symbol.Builder.rustType(rustType: RustType): Symbol.Builder {
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/HttpProtocolGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/HttpProtocolGenerator.kt
index 06bc3adf40..135c29869b 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/HttpProtocolGenerator.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/HttpProtocolGenerator.kt
@@ -71,7 +71,8 @@ abstract class HttpProtocolGenerator(
val inputShape = operationShape.inputShape(model)
val sdkId =
protocolConfig.serviceShape.getTrait(ServiceTrait::class.java)
- .map { it.sdkId.toLowerCase().replace(" ", "") }.orElse(protocolConfig.serviceShape.id.name)
+ .map { it.sdkId.toLowerCase().replace(" ", "") }
+ .orElse(protocolConfig.serviceShape.id.getName(protocolConfig.serviceShape))
val builderGenerator = BuilderGenerator(model, symbolProvider, operationShape.inputShape(model))
builderGenerator.render(inputWriter)
// impl OperationInputShape { ... }
@@ -158,7 +159,12 @@ abstract class HttpProtocolGenerator(
}
}
- private fun buildOperation(implBlockWriter: RustWriter, shape: OperationShape, features: List, sdkId: String) {
+ private fun buildOperation(
+ implBlockWriter: RustWriter,
+ shape: OperationShape,
+ features: List,
+ sdkId: String
+ ) {
val runtimeConfig = protocolConfig.runtimeConfig
val outputSymbol = symbolProvider.toSymbol(shape)
val operationT = RuntimeType.operation(runtimeConfig)
@@ -175,7 +181,10 @@ abstract class HttpProtocolGenerator(
val mut = features.any { it.mutSelf() }
val consumes = features.any { it.consumesSelf() }
val self = "self".letIf(mut) { "mut $it" }.letIf(!consumes) { "&$it" }
- implBlockWriter.rustBlock("pub fn make_operation($self, _config: T::Config) -> $returnType", RuntimeType.Config) {
+ implBlockWriter.rustBlock(
+ "pub fn make_operation($self, _config: T::Config) -> $returnType",
+ RuntimeType.Config
+ ) {
withBlock("Ok({", "})") {
features.forEach { it.section(OperationSection.MutateInput("self", "_config"))(this) }
rust("let request = Self::assemble(self.request_builder_base()?, self.build_body());")
@@ -192,7 +201,9 @@ abstract class HttpProtocolGenerator(
let op = #1T::Operation::new(
request,
#2T::new()
- ).with_metadata(#1T::Metadata::new(${shape.id.name.dq()}, ${sdkId.dq()}));
+ ).with_metadata(#1T::Metadata::new(${
+ shape.id.getName(protocolConfig.serviceShape).dq()
+ }, ${sdkId.dq()}));
""",
operationModule, symbolProvider.toSymbol(shape)
)
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/ErrorGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/ErrorGenerator.kt
index cc491a4686..05126dbc57 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/ErrorGenerator.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/ErrorGenerator.kt
@@ -91,6 +91,7 @@ class ErrorGenerator(
writer.rustBlock("impl #T for ${symbol.name}", stdfmt.member("Display")) {
rustBlock("fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result") {
// If the error id and the Rust name don't match, print the actual error id for easy debugging
+ // Note: Exceptions cannot be renamed so it is OK to not call `getName(service)` here
val errorDesc = symbol.name.letIf(symbol.name != shape.id.name) { symbolName ->
"$symbolName [${shape.id.name}]"
}
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/TopLevelErrorGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/TopLevelErrorGenerator.kt
index 054c834292..6798a43fce 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/TopLevelErrorGenerator.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/error/TopLevelErrorGenerator.kt
@@ -38,9 +38,9 @@ class TopLevelErrorGenerator(protocolConfig: ProtocolConfig, private val operati
private val symbolProvider = protocolConfig.symbolProvider
private val model = protocolConfig.model
- private val allErrors = operations.flatMap { it.errors }.distinctBy { it.name }
+ private val allErrors = operations.flatMap { it.errors }.distinctBy { it.getName(protocolConfig.serviceShape) }
.map { protocolConfig.model.expectShape(it, StructureShape::class.java) }
- .sortedBy { it.id.name }
+ .sortedBy { it.id.getName(protocolConfig.serviceShape) }
private val sdkError = CargoDependency.SmithyHttp(protocolConfig.runtimeConfig).asType().member("result::SdkError")
fun render(crate: RustCrate) {
@@ -91,7 +91,10 @@ class TopLevelErrorGenerator(protocolConfig: ProtocolConfig, private val operati
}
private fun RustWriter.renderDefinition() {
- RustMetadata(additionalAttributes = listOf(Attribute.NonExhaustive), public = true).withDerives(RuntimeType.Debug).render(this)
+ RustMetadata(
+ additionalAttributes = listOf(Attribute.NonExhaustive),
+ public = true
+ ).withDerives(RuntimeType.Debug).render(this)
rustBlock("enum Error") {
allErrors.forEach { error ->
val sym = symbolProvider.toSymbol(error)
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/RequestBindingGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/RequestBindingGenerator.kt
index 3fa0f12989..a65e803940 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/RequestBindingGenerator.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/RequestBindingGenerator.kt
@@ -28,7 +28,6 @@ import software.amazon.smithy.rust.codegen.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.generators.operationBuildError
import software.amazon.smithy.rust.codegen.smithy.generators.redactIfNecessary
-import software.amazon.smithy.rust.codegen.smithy.rustType
import software.amazon.smithy.rust.codegen.util.dq
import software.amazon.smithy.rust.codegen.util.expectMember
@@ -70,7 +69,6 @@ class RequestBindingGenerator(
private val defaultTimestampFormat = TimestampFormatTrait.Format.EPOCH_SECONDS
private val index = HttpBindingIndex.of(model)
private val buildError = runtimeConfig.operationBuildError()
- private val instant = RuntimeType.Instant(runtimeConfig).toSymbol().rustType()
/**
* Generates `update_http_builder` and all necessary dependency functions into the impl block provided by
@@ -152,7 +150,13 @@ class RequestBindingGenerator(
let header_value = http::header::HeaderValue::try_from(header_value).map_err(|err| {
#{build_error}::InvalidField {
field: ${memberName.dq()},
- details: format!("`{}` cannot be used as a header value: {}", ${redactIfNecessary(memberShape, model,"v")}, err)}
+ details: format!("`{}` cannot be used as a header value: {}", ${
+ redactIfNecessary(
+ memberShape,
+ model,
+ "v"
+ )
+ }, err)}
})?;
builder = builder.header(header_name, header_value);
}
@@ -169,7 +173,7 @@ class RequestBindingGenerator(
val memberSymbol = symbolProvider.toSymbol(memberShape)
val memberName = symbolProvider.toMemberName(memberShape)
ifSet(memberType, memberSymbol, "&self.$memberName") { field ->
- ListForEach(memberType, field) { innerField, targetId ->
+ listForEach(memberType, field) { innerField, targetId ->
val innerMemberType = model.expectShape(targetId)
val formatted = headerFmtFun(innerMemberType, memberShape, innerField)
val safeName = safeName("formatted")
@@ -263,10 +267,12 @@ class RequestBindingGenerator(
private fun uriQuery(writer: RustWriter): Boolean {
// Don't bother generating the function if we aren't going to make a query string
val dynamicParams = index.getRequestBindings(shape, HttpBinding.Location.QUERY)
+ val mapParams = index.getRequestBindings(shape, HttpBinding.Location.QUERY_PARAMS)
val literalParams = httpTrait.uri.queryLiterals
if (dynamicParams.isEmpty() && literalParams.isEmpty()) {
return false
}
+ val preloadedParams = literalParams.keys + dynamicParams.map { it.locationName }
writer.rustBlock("fn uri_query(&self, mut output: &mut String)") {
write("let mut query = #T::new(&mut output);", RuntimeType.QueryFormat(runtimeConfig, "Writer"))
literalParams.forEach { (k, v) ->
@@ -279,13 +285,35 @@ class RequestBindingGenerator(
}
}
+ if (mapParams.isNotEmpty()) {
+ rust("let protected_params = ${preloadedParams.joinToString(prefix = "[", postfix = "]") { it.dq() }};")
+ }
+ mapParams.forEach { param ->
+ val memberShape = param.member
+ val memberSymbol = symbolProvider.toSymbol(memberShape)
+ val memberName = symbolProvider.toMemberName(memberShape)
+ val targetShape = model.expectShape(memberShape.target, MapShape::class.java)
+ val stringFormatter = RuntimeType.QueryFormat(runtimeConfig, "fmt_string")
+ ifSet(model.expectShape(param.member.target), memberSymbol, "&self.$memberName") { field ->
+ rustBlock("for (k, v) in $field") {
+ // if v is a list, generate another level of iteration
+ listForEach(model.expectShape(targetShape.value.target), "v") { innerField, _ ->
+ rustBlock("if !protected_params.contains(&k.as_str())") {
+ rust("query.push_kv(T(k), T($innerField));", stringFormatter)
+ }
+ }
+ }
+ }
+ }
+
dynamicParams.forEach { param ->
val memberShape = param.member
val memberSymbol = symbolProvider.toSymbol(memberShape)
val memberName = symbolProvider.toMemberName(memberShape)
val outerTarget = model.expectShape(memberShape.target)
ifSet(outerTarget, memberSymbol, "&self.$memberName") { field ->
- ListForEach(outerTarget, field) { innerField, targetId ->
+ // if `param` is a list, generate another level of iteration
+ listForEach(outerTarget, field) { innerField, targetId ->
val target = model.expectShape(targetId)
rust(
"query.push_kv(${param.locationName.dq()}, &${
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/ResponseBindingGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/ResponseBindingGenerator.kt
index 9b55797ea8..e56f2ec3c6 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/ResponseBindingGenerator.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/http/ResponseBindingGenerator.kt
@@ -40,6 +40,7 @@ class ResponseBindingGenerator(protocolConfig: ProtocolConfig, private val opera
private val runtimeConfig = protocolConfig.runtimeConfig
private val symbolProvider = protocolConfig.symbolProvider
private val model = protocolConfig.model
+ private val service = protocolConfig.serviceShape
private val index = HttpBindingIndex.of(model)
private val headerUtil = CargoDependency.SmithyHttp(runtimeConfig).asType().member("header")
private val defaultTimestampFormat = TimestampFormatTrait.Format.EPOCH_SECONDS
@@ -60,7 +61,7 @@ class ResponseBindingGenerator(protocolConfig: ProtocolConfig, private val opera
fun generateDeserializeHeaderFn(binding: HttpBinding): RuntimeType {
check(binding.location == HttpBinding.Location.HEADER)
val outputT = symbolProvider.toSymbol(binding.member)
- val fnName = "deser_header_${operationShape.id.name.toSnakeCase()}_${binding.memberName.toSnakeCase()}"
+ val fnName = "deser_header_${fnName(operationShape, binding)}"
return RuntimeType.forInlineFun(fnName, "http_serde") { writer ->
writer.rustBlock(
"pub fn $fnName(header_map: T::HeaderMap) -> Result<#T, #T::ParseError>",
@@ -80,7 +81,7 @@ class ResponseBindingGenerator(protocolConfig: ProtocolConfig, private val opera
check(outputT.rustType().stripOuter() is RustType.HashMap) { outputT.rustType() }
val target = model.expectShape(binding.member.target)
check(target is MapShape)
- val fnName = "deser_prefix_header_${operationShape.id.name.toSnakeCase()}_${binding.memberName.toSnakeCase()}"
+ val fnName = "deser_prefix_header_${fnName(operationShape, binding)}"
val inner = RuntimeType.forInlineFun("${fnName}_inner", "http_serde_inner") {
it.rustBlock(
"pub fn ${fnName}_inner(headers: #T::header::ValueIter) -> Result