use tower_async_layer::{Identity, Layer, Stack};
use tower_async_service::Service;
use std::fmt;
#[derive(Clone)]
pub struct ServiceBuilder<L> {
layer: L,
}
impl Default for ServiceBuilder<Identity> {
fn default() -> Self {
Self::new()
}
}
impl ServiceBuilder<Identity> {
pub fn new() -> Self {
ServiceBuilder {
layer: Identity::new(),
}
}
}
impl<L> ServiceBuilder<L> {
pub fn layer<T>(self, layer: T) -> ServiceBuilder<Stack<T, L>> {
ServiceBuilder {
layer: Stack::new(layer, self.layer),
}
}
#[cfg(feature = "util")]
pub fn option_layer<T>(
self,
layer: Option<T>,
) -> ServiceBuilder<Stack<crate::util::Either<T, Identity>, L>> {
self.layer(crate::util::option_layer(layer))
}
pub fn layer_fn<F>(self, f: F) -> ServiceBuilder<Stack<crate::layer::LayerFn<F>, L>> {
self.layer(crate::layer::layer_fn(f))
}
#[cfg(feature = "retry")]
pub fn retry<P>(self, policy: P) -> ServiceBuilder<Stack<crate::retry::RetryLayer<P>, L>> {
self.layer(crate::retry::RetryLayer::new(policy))
}
#[cfg(feature = "timeout")]
pub fn timeout(
self,
timeout: std::time::Duration,
) -> ServiceBuilder<Stack<crate::timeout::TimeoutLayer, L>> {
self.layer(crate::timeout::TimeoutLayer::new(timeout))
}
#[cfg(feature = "filter")]
pub fn filter<P>(
self,
predicate: P,
) -> ServiceBuilder<Stack<crate::filter::FilterLayer<P>, L>> {
self.layer(crate::filter::FilterLayer::new(predicate))
}
#[cfg(feature = "filter")]
pub fn filter_async<P>(
self,
predicate: P,
) -> ServiceBuilder<Stack<crate::filter::AsyncFilterLayer<P>, L>> {
self.layer(crate::filter::AsyncFilterLayer::new(predicate))
}
#[cfg(feature = "limit")]
pub fn limit<P>(self, policy: P) -> ServiceBuilder<Stack<crate::limit::LimitLayer<P>, L>> {
self.layer(crate::limit::LimitLayer::new(policy))
}
#[cfg(feature = "util")]
pub fn map_request<F, R1, R2>(
self,
f: F,
) -> ServiceBuilder<Stack<crate::util::MapRequestLayer<F>, L>>
where
F: Fn(R1) -> R2 + Clone,
{
self.layer(crate::util::MapRequestLayer::new(f))
}
#[cfg(feature = "util")]
pub fn map_response<F>(
self,
f: F,
) -> ServiceBuilder<Stack<crate::util::MapResponseLayer<F>, L>> {
self.layer(crate::util::MapResponseLayer::new(f))
}
#[cfg(feature = "util")]
pub fn map_err<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapErrLayer<F>, L>> {
self.layer(crate::util::MapErrLayer::new(f))
}
#[cfg(feature = "util")]
pub fn then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::ThenLayer<F>, L>> {
self.layer(crate::util::ThenLayer::new(f))
}
#[cfg(feature = "util")]
pub fn and_then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::AndThenLayer<F>, L>> {
self.layer(crate::util::AndThenLayer::new(f))
}
#[cfg(feature = "util")]
pub fn map_result<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapResultLayer<F>, L>> {
self.layer(crate::util::MapResultLayer::new(f))
}
pub fn into_inner(self) -> L {
self.layer
}
pub fn service<S>(&self, service: S) -> L::Service
where
L: Layer<S>,
{
self.layer.layer(service)
}
#[cfg(feature = "util")]
pub fn service_fn<F>(self, f: F) -> L::Service
where
L: Layer<crate::util::ServiceFn<F>>,
{
self.service(crate::util::service_fn(f))
}
#[inline]
pub fn check_clone(self) -> Self
where
Self: Clone,
{
self
}
#[inline]
pub fn check_service_clone<S>(self) -> Self
where
L: Layer<S>,
L::Service: Clone,
{
self
}
#[inline]
pub fn check_service<S, T, U, E>(self) -> Self
where
L: Layer<S>,
L::Service: Service<T, Response = U, Error = E>,
{
self
}
}
impl<L: fmt::Debug> fmt::Debug for ServiceBuilder<L> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ServiceBuilder").field(&self.layer).finish()
}
}
impl<S, L> Layer<S> for ServiceBuilder<L>
where
L: Layer<S>,
{
type Service = L::Service;
fn layer(&self, inner: S) -> Self::Service {
self.layer.layer(inner)
}
}