diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt index 5e2ce595af..ff7496b973 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt @@ -136,6 +136,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( "RuntimeError" to ServerRuntimeType.runtimeError(runtimeConfig), "RequestRejection" to ServerRuntimeType.requestRejection(runtimeConfig), "ResponseRejection" to ServerRuntimeType.responseRejection(runtimeConfig), + "PinProjectLite" to ServerCargoDependency.PinProjectLite.toType(), "http" to RuntimeType.Http, ) @@ -196,8 +197,27 @@ private class ServerHttpBoundProtocolTraitImplGenerator( } // Implement `from_request` trait for input types. + val inputFuture = "${inputSymbol.name}Future" rustTemplate( """ + // TODO(https://github.com/awslabs/smithy-rs/issues/2238): Remove the `Pin>` and replace with thin wrapper around `Collect`. + #{PinProjectLite}::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`${inputSymbol.name}`](#{I}) using modelled bindings. + pub struct $inputFuture { + inner: std::pin::Pin> + Send>> + } + } + + impl std::future::Future for $inputFuture { + type Output = Result<#{I}, #{RuntimeError}>; + + fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } + } + impl #{SmithyHttpServer}::request::FromRequest<#{Marker}, B> for #{I} where B: #{SmithyHttpServer}::body::HttpBody + Send, @@ -207,7 +227,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( #{RequestRejection} : From<::Error> { type Rejection = #{RuntimeError}; - type Future = std::pin::Pin> + Send>>; + type Future = $inputFuture; fn from_request(request: #{http}::Request) -> Self::Future { let fut = async move { @@ -217,7 +237,9 @@ private class ServerHttpBoundProtocolTraitImplGenerator( .await .map_err(Into::into) }; - Box::pin(fut) + $inputFuture { + inner: Box::pin(fut) + } } }