mirror of
https://github.com/ntex-rs/ntex.git
synced 2025-04-04 21:37:58 +03:00
114 lines
2.8 KiB
Rust
114 lines
2.8 KiB
Rust
use futures_util::future::{ok, Ready};
|
|
use std::{future::Future, marker::PhantomData};
|
|
|
|
use crate::{apply_fn, dev::Apply, Service, Transform};
|
|
|
|
/// Use function as transform service
|
|
pub fn fn_transform<S, F, R, Req, Res, Err>(
|
|
f: F,
|
|
) -> impl Transform<S, Request = Req, Response = Res, Error = Err, InitError = ()> + Clone
|
|
where
|
|
S: Service<Error = Err>,
|
|
F: Fn(Req, &S) -> R + Clone,
|
|
R: Future<Output = Result<Res, Err>>,
|
|
{
|
|
FnTransform::new(f)
|
|
}
|
|
|
|
pub struct FnTransform<S, F, R, Req, Res, Err>
|
|
where
|
|
S: Service<Error = Err>,
|
|
F: Fn(Req, &S) -> R + Clone,
|
|
R: Future<Output = Result<Res, Err>>,
|
|
{
|
|
f: F,
|
|
_t: PhantomData<(S, R, Req)>,
|
|
}
|
|
|
|
impl<S, F, R, Req, Res, Err> FnTransform<S, F, R, Req, Res, Err>
|
|
where
|
|
S: Service<Error = Err>,
|
|
F: Fn(Req, &S) -> R + Clone,
|
|
R: Future<Output = Result<Res, Err>>,
|
|
{
|
|
fn new(f: F) -> Self {
|
|
FnTransform { f, _t: PhantomData }
|
|
}
|
|
}
|
|
|
|
impl<S, F, R, Req, Res, Err> Transform<S> for FnTransform<S, F, R, Req, Res, Err>
|
|
where
|
|
S: Service<Error = Err>,
|
|
F: Fn(Req, &S) -> R + Clone,
|
|
R: Future<Output = Result<Res, Err>>,
|
|
{
|
|
type Request = Req;
|
|
type Response = Res;
|
|
type Error = Err;
|
|
type Transform = Apply<S, F, R, Req, Res, Err>;
|
|
type InitError = ();
|
|
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
|
|
|
fn new_transform(&self, service: S) -> Self::Future {
|
|
ok(apply_fn(service, self.f.clone()))
|
|
}
|
|
}
|
|
|
|
impl<S, F, R, Req, Res, Err> Clone for FnTransform<S, F, R, Req, Res, Err>
|
|
where
|
|
S: Service<Error = Err>,
|
|
F: Fn(Req, &S) -> R + Clone,
|
|
R: Future<Output = Result<Res, Err>>,
|
|
{
|
|
fn clone(&self) -> Self {
|
|
Self::new(self.f.clone())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[allow(clippy::redundant_clone)]
|
|
mod tests {
|
|
use futures_util::future::{lazy, ok};
|
|
use std::task::{Context, Poll};
|
|
|
|
use super::*;
|
|
use crate::Service;
|
|
|
|
#[derive(Clone)]
|
|
struct Srv;
|
|
|
|
impl Service for Srv {
|
|
type Request = usize;
|
|
type Response = usize;
|
|
type Error = ();
|
|
type Future = Ready<Result<usize, ()>>;
|
|
|
|
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
Poll::Ready(Ok(()))
|
|
}
|
|
|
|
fn call(&self, i: usize) -> Self::Future {
|
|
ok(i * 2)
|
|
}
|
|
}
|
|
|
|
#[ntex_rt::test]
|
|
async fn transform() {
|
|
let srv =
|
|
fn_transform::<Srv, _, _, _, _, _>(|i: usize, srv: &_| srv.call(i + 1))
|
|
.clone()
|
|
.new_transform(Srv)
|
|
.await
|
|
.unwrap();
|
|
|
|
let res = srv.call(10usize).await;
|
|
assert!(res.is_ok());
|
|
assert_eq!(res.unwrap(), 22);
|
|
|
|
let res = lazy(|cx| srv.poll_ready(cx)).await;
|
|
assert_eq!(res, Poll::Ready(Ok(())));
|
|
|
|
let res = lazy(|cx| srv.poll_shutdown(cx, true)).await;
|
|
assert_eq!(res, Poll::Ready(()));
|
|
}
|
|
}
|