use super::Layer;
use core::fmt;
pub fn layer_fn<T>(f: T) -> LayerFn<T> {
LayerFn { f }
}
#[derive(Clone)]
pub struct LayerFn<F> {
f: F,
}
impl<F, S, Out> Layer<S> for LayerFn<F>
where
F: Fn(S) -> Out,
{
type Service = Out;
fn layer(&self, inner: S) -> Self::Service {
(self.f)(inner)
}
fn into_layer(self, inner: S) -> Self::Service {
(self.f)(inner)
}
}
impl<F> fmt::Debug for LayerFn<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LayerFn")
.field("f", &format_args!("<{}>", core::any::type_name::<F>()))
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_layer_fn() {
use crate::{Service, service::service_fn};
use core::convert::Infallible;
#[derive(Debug, Clone)]
struct ToUpper<S>(S);
impl<S, Input> Service<Input> for ToUpper<S>
where
Input: Send + 'static,
S: Service<Input, Output = &'static str>,
{
type Output = String;
type Error = S::Error;
async fn serve(&self, input: Input) -> Result<Self::Output, Self::Error> {
let res = self.0.serve(input).await;
res.map(|msg| msg.to_uppercase())
}
}
let layer = layer_fn(ToUpper);
let f = async |req| Ok::<_, Infallible>(req);
let res = layer.layer(service_fn(f)).serve("hello").await;
assert_eq!(res, Ok("HELLO".to_owned()));
let svc = layer.layer(service_fn(f));
let res = svc.serve("hello").await;
assert_eq!(res, Ok("HELLO".to_owned()));
let res = svc.clone().serve("hello").await;
assert_eq!(res, Ok("HELLO".to_owned()));
}
#[expect(dead_code)]
#[test]
fn layer_fn_has_useful_debug_impl() {
struct WrappedService<S> {
inner: S,
}
let layer = layer_fn(|svc| WrappedService { inner: svc });
let _svc = layer.layer("foo");
assert_eq!(
"LayerFn { f: <rama_core::layer::layer_fn::tests::layer_fn_has_useful_debug_impl::{{closure}}> }".to_owned(),
format!("{layer:?}"),
);
}
}