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
#[cfg(any(feature="rt_tokio",feature="rt_async-std",feature="rt_worker"))]
mod handler;
#[cfg(any(feature="rt_tokio",feature="rt_async-std",feature="rt_worker"))]
pub(crate) use handler::{Handler, IntoHandler};

mod middleware;
pub use middleware::{Fangs, util};

use crate::{Request, Response};
use std::{future::Future, pin::Pin, ops::Deref};


pub trait Fang<Inner: FangProc> {
    type Proc: FangProc;
    fn chain(&self, inner: Inner) -> Self::Proc;
}

pub trait FangProc: Send + Sync + 'static {
    fn bite<'b>(&'b self, req: &'b mut Request) -> impl std::future::Future<Output = Response> + Send;

    /// Default: `Box::pin(self.bite(req))`.
    /// 
    /// Override when `bite` itself returns `Pin<Box<dyn Future>>`.
    fn bite_boxed<'b>(&'b self, req: &'b mut Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'b>> {
        Box::pin(self.bite(req))
    }
}

/// `FangProc` but object-safe, returning `Pin<Box<dyn Future>>`.
pub trait FangProcCaller {
    fn call_bite<'b>(&'b self, req: &'b mut Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'b>>;
}
impl<Proc: FangProc> FangProcCaller for Proc {
    #[inline(always)]
    fn call_bite<'b>(&'b self, req: &'b mut Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'b>> {
        self.bite_boxed(req)
    }
}

pub struct BoxedFPC(Box<dyn
    FangProcCaller + Send + Sync + 'static
>);
impl BoxedFPC {
    pub(crate) fn from_proc(proc: impl FangProcCaller + Send + Sync + 'static) -> Self {
        Self(Box::new(proc))
    }
}
const _: () = {
    impl Deref for BoxedFPC {
        type Target = dyn FangProcCaller + Send + Sync + 'static;
        
        #[inline(always)]
        fn deref(&self) -> &Self::Target {
            &*self.0
        }
    }

    impl std::fmt::Debug for BoxedFPC {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            f.write_str("{Fang proc}")
        }
    }

    impl FangProc for BoxedFPC {
        #[inline(always)]
        fn bite<'b>(&'b self, req: &'b mut Request) -> impl std::future::Future<Output = Response> + Send {
            (&*self.0).call_bite(req)
        }

        #[inline]
        fn bite_boxed<'b>(&'b self, req: &'b mut Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'b>> {
            (&*self.0).call_bite(req)
        }
    }
};