diff --git a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs index 4f0c8255e9..fc3191f8a0 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs @@ -62,35 +62,36 @@ where } } -// fn(Input, Ext0) -> Output -impl Handler for F -where - Op: OperationShape, - F: Fn(Op::Input, Ext0) -> Fut, - Fut: Future, - Fut::Output: IntoResult, -{ - type Future = Map Result>; - - fn call(&mut self, input: Op::Input, exts: (Ext0,)) -> Self::Future { - (self)(input, exts.0).map(IntoResult::into_result) - } +// fn(Input, Ext_i) -> Output +macro_rules! impl_handler { + ($($var:ident),+) => ( + impl Handler for F + where + Op: OperationShape, + F: Fn(Op::Input, $($var,)*) -> Fut, + Fut: Future, + Fut::Output: IntoResult, + { + type Future = Map Result>; + + fn call(&mut self, input: Op::Input, exts: ($($var,)*)) -> Self::Future { + #[allow(non_snake_case)] + let ($($var,)*) = exts; + (self)(input, $($var,)*).map(IntoResult::into_result) + } + } + ) } -// fn(Input, Ext0, Ext1) -> Output -impl Handler for F -where - Op: OperationShape, - F: Fn(Op::Input, Ext0, Ext1) -> Fut, - Fut: Future, - Fut::Output: IntoResult, -{ - type Future = Map Result>; - - fn call(&mut self, input: Op::Input, exts: (Ext0, Ext1)) -> Self::Future { - (self)(input, exts.0, exts.1).map(IntoResult::into_result) - } -} +impl_handler!(Exts0); +impl_handler!(Exts0, Exts1); +impl_handler!(Exts0, Exts1, Exts2); +impl_handler!(Exts0, Exts1, Exts2, Exts3); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6, Exts7); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6, Exts7, Exts8); /// An extension trait for [`Handler`]. pub trait HandlerExt: Handler diff --git a/rust-runtime/aws-smithy-http-server/src/rejection.rs b/rust-runtime/aws-smithy-http-server/src/rejection.rs index c75b3e466c..4ad682e6b8 100644 --- a/rust-runtime/aws-smithy-http-server/src/rejection.rs +++ b/rust-runtime/aws-smithy-http-server/src/rejection.rs @@ -264,21 +264,38 @@ convert_to_request_rejection!(hyper::Error, HttpBody); // Required in order to accept Lambda HTTP requests using `Router`. convert_to_request_rejection!(lambda_http::Error, HttpBody); -/// A sum type rejection, implementing [`IntoResponse`] when both variants do. -pub enum EitherRejection { - Left(Left), - Right(Right), -} - -impl IntoResponse

for EitherRejection -where - L: IntoResponse

, - R: IntoResponse

, -{ - fn into_response(self) -> http::Response { - match self { - EitherRejection::Left(left) => left.into_response(), - EitherRejection::Right(right) => right.into_response(), - } +pub mod any_rejections { + //! This module hosts enums, up to size 8, which implement [`IntoResponse`] when their variants implement + //! [`IntoResponse`]. + + use super::IntoResponse; + + macro_rules! any_rejection { + ($name:ident, $($var:ident),+) => ( + pub enum $name<$($var),*> { + $($var ($var),)* + } + + impl IntoResponse

for $name<$($var),*> + where + $($var: IntoResponse

,)* + { + #[allow(non_snake_case)] + fn into_response(self) -> http::Response { + match self { + $($name::$var ($var) => $var.into_response(),)* + } + } + } + ) } + + // any_rejection!(One, A); + any_rejection!(Two, A, B); + any_rejection!(Three, A, B, C); + any_rejection!(Four, A, B, C, D); + any_rejection!(Five, A, B, C, D, E); + any_rejection!(Six, A, B, C, D, E, F); + any_rejection!(Seven, A, B, C, D, E, F, G); + any_rejection!(Eight, A, B, C, D, E, F, G, H); } diff --git a/rust-runtime/aws-smithy-http-server/src/request.rs b/rust-runtime/aws-smithy-http-server/src/request.rs index 36b880e228..9faf1ea58d 100644 --- a/rust-runtime/aws-smithy-http-server/src/request.rs +++ b/rust-runtime/aws-smithy-http-server/src/request.rs @@ -43,7 +43,7 @@ use futures_util::{ }; use http::{request::Parts, Extensions, HeaderMap, Request, Uri}; -use crate::{rejection::EitherRejection, response::IntoResponse}; +use crate::{rejection::any_rejections, response::IntoResponse}; #[doc(hidden)] #[derive(Debug)] @@ -139,20 +139,32 @@ where } } -impl FromParts

for (T1, T2) -where - T1: FromParts

, - T2: FromParts

, -{ - type Rejection = EitherRejection; - - fn from_parts(parts: &mut Parts) -> Result { - let t1 = T1::from_parts(parts).map_err(EitherRejection::Left)?; - let t2 = T2::from_parts(parts).map_err(EitherRejection::Right)?; - Ok((t1, t2)) - } +macro_rules! impl_from_parts { + ($error_name:ident, $($var:ident),+) => ( + impl FromParts

for ($($var),*) + where + $($var: FromParts

,)* + { + type Rejection = any_rejections::$error_name<$($var::Rejection),*>; + + fn from_parts(parts: &mut Parts) -> Result { + let tuple = ( + $($var::from_parts(parts).map_err(any_rejections::$error_name::$var)?,)* + ); + Ok(tuple) + } + } + ) } +impl_from_parts!(Two, A, B); +impl_from_parts!(Three, A, B, C); +impl_from_parts!(Four, A, B, C, D); +impl_from_parts!(Five, A, B, C, D, E); +impl_from_parts!(Six, A, B, C, D, E, F); +impl_from_parts!(Seven, A, B, C, D, E, F, G); +impl_from_parts!(Eight, A, B, C, D, E, F, G, H); + /// Provides a protocol aware extraction from a [`Request`]. This consumes the /// [`Request`], in contrast to [`FromParts`]. pub trait FromRequest: Sized { @@ -180,14 +192,14 @@ where T1: FromRequest, T2: FromParts

, { - type Rejection = EitherRejection; + type Rejection = any_rejections::Two; type Future = TryJoin Self::Rejection>, Ready>>; fn from_request(request: Request) -> Self::Future { let (mut parts, body) = request.into_parts(); - let t2_result = T2::from_parts(&mut parts).map_err(EitherRejection::Right); + let t2_result = T2::from_parts(&mut parts).map_err(any_rejections::Two::B); try_join( - T1::from_request(Request::from_parts(parts, body)).map_err(EitherRejection::Left), + T1::from_request(Request::from_parts(parts, body)).map_err(any_rejections::Two::A), ready(t2_result), ) }