Skip to content

Commit 7ef728f

Browse files
committed
Event streams with initial-request bodies now support schema serde
1 parent 699a8ce commit 7ef728f

1 file changed

Lines changed: 42 additions & 5 deletions

File tree

codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ClientHttpBoundProtocolPayloadGenerator(
3535
.expect("a SharedClientProtocol is required")
3636
.clone();
3737
let error_marshaller = #{errorMarshallerConstructorFn}(protocol.clone());
38-
let marshaller = #{marshallerConstructorFn}(protocol);
38+
let marshaller = #{marshallerConstructorFn}(protocol.clone());
3939
"""
4040
} else {
4141
"""
@@ -78,22 +78,59 @@ private fun eventStreamWithInitialRequest(
7878
protocol: Protocol,
7979
params: EventStreamBodyParams,
8080
): Writable? {
81-
val parser = protocol.structuredDataSerializer().operationInputSerializer(params.operationShape) ?: return null
82-
8381
if (codegenContext.protocolImpl?.httpBindingResolver?.handlesEventStreamInitialRequest(params.operationShape) != true) {
8482
return null
8583
}
8684

85+
val useSchemaSerde = SchemaSerdeAllowlist.usesSchemaSerdeExclusively(codegenContext)
86+
val parser = protocol.structuredDataSerializer().operationInputSerializer(params.operationShape)
87+
// Legacy path requires the structured serializer to be available.
88+
if (!useSchemaSerde && parser == null) return null
89+
8790
val smithyHttp = RuntimeType.smithyHttp(codegenContext.runtimeConfig)
8891
val eventOrInitial = smithyHttp.resolve("event_stream::EventOrInitial")
8992
val eventOrInitialMarshaller = smithyHttp.resolve("event_stream::EventOrInitialMarshaller")
9093

94+
val operationSymbol = codegenContext.symbolProvider.toSymbol(params.operationShape)
95+
val smithySchema = RuntimeType.smithySchema(codegenContext.runtimeConfig)
96+
97+
val bodyExpr: Writable =
98+
if (useSchemaSerde) {
99+
writable {
100+
rustTemplate(
101+
"""
102+
{
103+
let codec = protocol.payload_codec()
104+
.ok_or_else(|| "protocol has no payload codec")?;
105+
let mut ser = codec.create_serializer();
106+
#{ShapeSerializer}::write_struct(
107+
&mut *ser,
108+
#{Operation}::INPUT_SCHEMA,
109+
&input,
110+
)?;
111+
#{SdkBody}::from(#{PayloadSerializer}::finish_boxed(ser))
112+
}
113+
""",
114+
"Operation" to operationSymbol,
115+
"ShapeSerializer" to smithySchema.resolve("serde::ShapeSerializer"),
116+
"PayloadSerializer" to smithySchema.resolve("codec::PayloadSerializer"),
117+
"SdkBody" to
118+
CargoDependency.smithyTypes(codegenContext.runtimeConfig).withFeature("http-body-1-x")
119+
.toType().resolve("body::SdkBody"),
120+
)
121+
}
122+
} else {
123+
writable {
124+
rustTemplate("#{parser}(&input)?", "parser" to parser!!)
125+
}
126+
}
127+
91128
return writable {
92129
rustTemplate(
93130
"""
94131
{
95132
use #{futures_util}::StreamExt;
96-
let body = #{parser}(&input)?;
133+
let body = #{body:W};
97134
let initial_message = #{initial_message}(body);
98135
99136
// Wrap the marshaller to handle both initial and regular messages
@@ -117,7 +154,7 @@ private fun eventStreamWithInitialRequest(
117154
*preludeScope,
118155
"futures_util" to CargoDependency.FuturesUtil.toType(),
119156
"initial_message" to params.eventStreamMarshallerGenerator.renderInitialRequestGenerator(params.payloadContentType),
120-
"parser" to parser,
157+
"body" to bodyExpr,
121158
"EventOrInitial" to eventOrInitial,
122159
"EventOrInitialMarshaller" to eventOrInitialMarshaller,
123160
"EventStreamSender" to smithyHttp.resolve("event_stream::EventStreamSender"),

0 commit comments

Comments
 (0)