1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
//! This module holds convenient short-hands for the otherwise fairly extensive trait bounds
//! required for `call` and friends.
//!
//! The short-hands will one day be true [trait aliases], but for now they are traits with blanket
//! implementations. Also, due to [compiler limitations], the bounds repeat a number of associated
//! types with bounds so that those bounds [do not need to be repeated] at the call site. It's a
//! bit of a mess to define, but _should_ be invisible to callers.
//!
//! [trait aliases]: https://rust-lang.github.io/rfcs/1733-trait-alias.html
//! [compiler limitations]: https://github.com/rust-lang/rust/issues/20671
//! [do not need to be repeated]: https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828
use crate::erase::DynConnector;
use crate::http_connector::HttpConnector;
use aws_smithy_http::body::SdkBody;
use aws_smithy_http::operation::{self, Operation};
use aws_smithy_http::response::ParseHttpResponse;
use aws_smithy_http::result::{ConnectorError, SdkError, SdkSuccess};
use aws_smithy_http::retry::ClassifyRetry;
use tower::{Layer, Service};
/// A service that has parsed a raw Smithy response.
pub type Parsed<S, O, Retry> =
aws_smithy_http_tower::parse_response::ParseResponseService<S, O, Retry>;
/// A low-level Smithy connector that maps from [`http::Request`] to [`http::Response`].
///
/// This trait has a blanket implementation for all compatible types, and should never be
/// implemented.
pub trait SmithyConnector:
Service<
http::Request<SdkBody>,
Response = http::Response<SdkBody>,
Error = <Self as SmithyConnector>::Error,
Future = <Self as SmithyConnector>::Future,
> + Send
+ Sync
+ Clone
+ 'static
{
/// Forwarding type to `<Self as Service>::Error` for bound inference.
///
/// See module-level docs for details.
type Error: Into<ConnectorError> + Send + Sync + 'static;
/// Forwarding type to `<Self as Service>::Future` for bound inference.
///
/// See module-level docs for details.
type Future: Send + 'static;
}
impl<T> SmithyConnector for T
where
T: Service<http::Request<SdkBody>, Response = http::Response<SdkBody>>
+ Send
+ Sync
+ Clone
+ 'static,
T::Error: Into<ConnectorError> + Send + Sync + 'static,
T::Future: Send + 'static,
{
type Error = T::Error;
type Future = T::Future;
}
impl<T, E, F> From<T> for HttpConnector
where
E: Into<ConnectorError> + Send + Sync + 'static,
F: Send + 'static,
T: SmithyConnector<Error = E, Future = F, Response = http::Response<SdkBody>>,
{
fn from(smithy_connector: T) -> Self {
HttpConnector::Prebuilt(Some(DynConnector::new(smithy_connector)))
}
}
/// A Smithy middleware service that adjusts [`aws_smithy_http::operation::Request`](operation::Request)s.
///
/// This trait has a blanket implementation for all compatible types, and should never be
/// implemented.
pub trait SmithyMiddlewareService:
Service<
operation::Request,
Response = operation::Response,
Error = aws_smithy_http_tower::SendOperationError,
Future = <Self as SmithyMiddlewareService>::Future,
>
{
/// Forwarding type to `<Self as Service>::Future` for bound inference.
///
/// See module-level docs for details.
type Future: Send + 'static;
}
impl<T> SmithyMiddlewareService for T
where
T: Service<
operation::Request,
Response = operation::Response,
Error = aws_smithy_http_tower::SendOperationError,
>,
T::Future: Send + 'static,
{
type Future = T::Future;
}
/// A Smithy middleware layer (i.e., factory).
///
/// This trait has a blanket implementation for all compatible types, and should never be
/// implemented.
pub trait SmithyMiddleware<C>:
Layer<
aws_smithy_http_tower::dispatch::DispatchService<C>,
Service = <Self as SmithyMiddleware<C>>::Service,
>
{
/// Forwarding type to `<Self as Layer>::Service` for bound inference.
///
/// See module-level docs for details.
type Service: SmithyMiddlewareService + Send + Sync + Clone + 'static;
}
impl<T, C> SmithyMiddleware<C> for T
where
T: Layer<aws_smithy_http_tower::dispatch::DispatchService<C>>,
T::Service: SmithyMiddlewareService + Send + Sync + Clone + 'static,
{
type Service = T::Service;
}
/// A Smithy retry policy.
///
/// This trait has a blanket implementation for all compatible types, and should never be
/// implemented.
pub trait SmithyRetryPolicy<O, T, E, Retry>:
tower::retry::Policy<Operation<O, Retry>, SdkSuccess<T>, SdkError<E>> + Clone
{
/// Forwarding type to `O` for bound inference.
///
/// See module-level docs for details.
type O: ParseHttpResponse<Output = Result<T, Self::E>> + Send + Sync + Clone + 'static;
/// Forwarding type to `E` for bound inference.
///
/// See module-level docs for details.
type E: std::error::Error;
/// Forwarding type to `Retry` for bound inference.
///
/// See module-level docs for details.
type Retry: ClassifyRetry<SdkSuccess<T>, SdkError<Self::E>>;
}
impl<R, O, T, E, Retry> SmithyRetryPolicy<O, T, E, Retry> for R
where
R: tower::retry::Policy<Operation<O, Retry>, SdkSuccess<T>, SdkError<E>> + Clone,
O: ParseHttpResponse<Output = Result<T, E>> + Send + Sync + Clone + 'static,
E: std::error::Error,
Retry: ClassifyRetry<SdkSuccess<T>, SdkError<E>>,
{
type O = O;
type E = E;
type Retry = Retry;
}