use crate::config::{FallbackConfig, FallbackConfigBuilder};
use crate::Fallback;
use std::sync::Arc;
use tower::layer::Layer;
pub struct FallbackLayer<Req, Res, E> {
config: Arc<FallbackConfig<Req, Res, E>>,
}
impl<Req, Res, E> FallbackLayer<Req, Res, E> {
pub(crate) fn new(config: FallbackConfig<Req, Res, E>) -> Self {
Self {
config: Arc::new(config),
}
}
pub fn builder() -> FallbackConfigBuilder<Req, Res, E> {
FallbackConfigBuilder::new()
}
pub fn value_fn<F>(f: F) -> Self
where
F: Fn() -> Res + Send + Sync + 'static,
{
FallbackConfigBuilder::new().value_fn(f).build()
}
}
impl<Req, Res, E> FallbackLayer<Req, Res, E>
where
Res: Clone,
{
pub fn value(value: Res) -> Self {
FallbackConfigBuilder::new().value(value).build()
}
pub fn from_error<F>(f: F) -> Self
where
F: Fn(&E) -> Res + Send + Sync + 'static,
{
FallbackConfigBuilder::new().from_error(f).build()
}
pub fn from_request_error<F>(f: F) -> Self
where
F: Fn(&Req, &E) -> Res + Send + Sync + 'static,
{
FallbackConfigBuilder::new().from_request_error(f).build()
}
pub fn service<S, Fut>(service: S) -> Self
where
S: Fn(Req) -> Fut + Send + Sync + 'static,
Fut: std::future::Future<Output = Result<Res, E>> + Send + 'static,
{
FallbackConfigBuilder::new().service(service).build()
}
pub fn exception<F>(f: F) -> Self
where
F: Fn(E) -> E + Send + Sync + 'static,
{
FallbackConfigBuilder::new().exception(f).build()
}
}
impl<Req, Res, E> Clone for FallbackLayer<Req, Res, E>
where
Res: Clone,
{
fn clone(&self) -> Self {
Self {
config: Arc::clone(&self.config),
}
}
}
impl<S, Req, Res, E> Layer<S> for FallbackLayer<Req, Res, E>
where
Res: Clone,
{
type Service = Fallback<S, Req, Res, E>;
fn layer(&self, service: S) -> Self::Service {
Fallback::new(service, Arc::clone(&self.config))
}
}