Skip to content

Commit

Permalink
Merge branch 'main' into davidpz/unique-items-validator
Browse files Browse the repository at this point in the history
  • Loading branch information
david-perez committed Nov 18, 2022
2 parents 71537ad + b2d280f commit ec01c93
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 59 deletions.
55 changes: 28 additions & 27 deletions rust-runtime/aws-smithy-http-server/src/operation/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,35 +62,36 @@ where
}
}

// fn(Input, Ext0) -> Output
impl<Op, F, Fut, Ext0> Handler<Op, (Ext0,)> for F
where
Op: OperationShape,
F: Fn(Op::Input, Ext0) -> Fut,
Fut: Future,
Fut::Output: IntoResult<Op::Output, Op::Error>,
{
type Future = Map<Fut, fn(Fut::Output) -> Result<Op::Output, Op::Error>>;

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<Op, F, Fut, $($var,)*> Handler<Op, ($($var,)*)> for F
where
Op: OperationShape,
F: Fn(Op::Input, $($var,)*) -> Fut,
Fut: Future,
Fut::Output: IntoResult<Op::Output, Op::Error>,
{
type Future = Map<Fut, fn(Fut::Output) -> Result<Op::Output, Op::Error>>;

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<Op, F, Fut, Ext0, Ext1> Handler<Op, (Ext0, Ext1)> for F
where
Op: OperationShape,
F: Fn(Op::Input, Ext0, Ext1) -> Fut,
Fut: Future,
Fut::Output: IntoResult<Op::Output, Op::Error>,
{
type Future = Map<Fut, fn(Fut::Output) -> Result<Op::Output, Op::Error>>;

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<Op, Exts>: Handler<Op, Exts>
Expand Down
49 changes: 33 additions & 16 deletions rust-runtime/aws-smithy-http-server/src/rejection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,21 +264,38 @@ convert_to_request_rejection!(hyper::Error, HttpBody);
// Required in order to accept Lambda HTTP requests using `Router<lambda_http::Body>`.
convert_to_request_rejection!(lambda_http::Error, HttpBody);

/// A sum type rejection, implementing [`IntoResponse`] when both variants do.
pub enum EitherRejection<Left, Right> {
Left(Left),
Right(Right),
}

impl<P, L, R> IntoResponse<P> for EitherRejection<L, R>
where
L: IntoResponse<P>,
R: IntoResponse<P>,
{
fn into_response(self) -> http::Response<crate::body::BoxBody> {
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<P, $($var,)*> IntoResponse<P> for $name<$($var),*>
where
$($var: IntoResponse<P>,)*
{
#[allow(non_snake_case)]
fn into_response(self) -> http::Response<crate::body::BoxBody> {
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);
}
44 changes: 28 additions & 16 deletions rust-runtime/aws-smithy-http-server/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -139,20 +139,32 @@ where
}
}

impl<P, T1, T2> FromParts<P> for (T1, T2)
where
T1: FromParts<P>,
T2: FromParts<P>,
{
type Rejection = EitherRejection<T1::Rejection, T2::Rejection>;

fn from_parts(parts: &mut Parts) -> Result<Self, Self::Rejection> {
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<P, $($var,)*> FromParts<P> for ($($var),*)
where
$($var: FromParts<P>,)*
{
type Rejection = any_rejections::$error_name<$($var::Rejection),*>;

fn from_parts(parts: &mut Parts) -> Result<Self, Self::Rejection> {
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<Protocol, B>: Sized {
Expand Down Expand Up @@ -180,14 +192,14 @@ where
T1: FromRequest<P, B>,
T2: FromParts<P>,
{
type Rejection = EitherRejection<T1::Rejection, T2::Rejection>;
type Rejection = any_rejections::Two<T1::Rejection, T2::Rejection>;
type Future = TryJoin<MapErr<T1::Future, fn(T1::Rejection) -> Self::Rejection>, Ready<Result<T2, Self::Rejection>>>;

fn from_request(request: Request<B>) -> 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),
)
}
Expand Down

0 comments on commit ec01c93

Please sign in to comment.