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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use crate::TryFromConn;
use std::{future::Future, marker::PhantomData, sync::Arc};
use trillium::{async_trait, Conn, Handler, Info, Status, Upgrade};

// A trait for `async fn(conn: &mut Conn, additional: Additional) -> ReturnType`
pub trait MutBorrowConn<'conn, ReturnType, Additional>: Send + Sync + 'conn {
    /// the returned future
    type Fut: Future<Output = ReturnType> + Send + 'conn;
    /// executes this function
    fn call(&self, conn: &'conn mut Conn, additional: Additional) -> Self::Fut;
}

impl<'conn, Fun, Fut, ReturnType, Additional> MutBorrowConn<'conn, ReturnType, Additional> for Fun
where
    Fun: Fn(&'conn mut Conn, Additional) -> Fut + Send + Sync + 'conn,
    Fut: Future<Output = ReturnType> + Send + 'conn,
{
    type Fut = Fut;
    fn call(&self, conn: &'conn mut Conn, additional: Additional) -> Fut {
        self(conn, additional)
    }
}

/// An interface layer built on trillium
///
/// This handler provides the capacity to extract various components of a conn such as deserializing
/// a body, and supports returning handlers that will be called on the returned conn.
///
/// If [`ApiHandler`] encounters an error of any sort before the user-provided logic is executed, it
/// will put an [`Error`] into the conn's state. A default error handler is provided.
///
/// More documentation for this type is needed, hence the -rc semver on this crate
#[derive(Debug)]
pub struct ApiHandler<F, OutputHandler, TryFromConn>(
    F,
    PhantomData<OutputHandler>,
    PhantomData<TryFromConn>,
);

impl<TryFromConnHandler, OutputHandler, Extracted>
    ApiHandler<TryFromConnHandler, OutputHandler, Extracted>
where
    TryFromConnHandler: for<'a> MutBorrowConn<'a, OutputHandler, Extracted>,
    OutputHandler: Handler,
    Extracted: TryFromConn,
{
    /// constructs a new [`ApiTryFromConnHandler`] from the provided
    /// `async fn(&mut conn, TryFromConn) -> impl Handler`
    pub fn new(api_handler: TryFromConnHandler) -> Self {
        Self::from(api_handler)
    }
}

impl<TryFromConnHandler, OutputHandler, Extracted> From<TryFromConnHandler>
    for ApiHandler<TryFromConnHandler, OutputHandler, Extracted>
where
    TryFromConnHandler: for<'a> MutBorrowConn<'a, OutputHandler, Extracted>,
    OutputHandler: Handler,
    Extracted: TryFromConn,
{
    fn from(value: TryFromConnHandler) -> Self {
        Self(value, PhantomData, PhantomData)
    }
}

/// constructs a new [`ApiTryFromConnHandler`] from the provided
/// `async fn(&mut conn, TryFromConn) -> impl Handler`
///
/// convenience function for [`ApiTryFromConnHandler::new`]
pub fn api<TryFromConnHandler, OutputHandler, Extracted>(
    api_handler: TryFromConnHandler,
) -> ApiHandler<TryFromConnHandler, OutputHandler, Extracted>
where
    TryFromConnHandler: for<'a> MutBorrowConn<'a, OutputHandler, Extracted>,
    Extracted: TryFromConn,
    OutputHandler: Handler,
{
    ApiHandler::from(api_handler)
}

#[async_trait]
impl<TryFromConnHandler, OutputHandler, Extracted> Handler
    for ApiHandler<TryFromConnHandler, OutputHandler, Extracted>
where
    TryFromConnHandler: for<'a> MutBorrowConn<'a, OutputHandler, Extracted>,
    Extracted: TryFromConn,
    Extracted::Error: Handler,
    OutputHandler: Handler,
{
    async fn run(&self, mut conn: Conn) -> Conn {
        let mut output_handler: Result<OutputHandler, <Extracted as TryFromConn>::Error> =
            match Extracted::try_from_conn(&mut conn).await {
                Ok(extracted) => Ok(self.0.call(&mut conn, extracted).await),
                Err(error_handler) => Err(error_handler),
            };

        if let Some(info) = conn.state_mut::<Info>() {
            output_handler.init(info).await;
        } else {
            output_handler.init(&mut Info::default()).await;
        }
        let mut conn = output_handler.run(conn).await;
        if conn.status().is_none() && conn.inner().response_body().is_some() {
            conn.set_status(Status::Ok);
        }
        conn.with_state(OutputHandlerWrapper(
            Arc::new(output_handler),
            PhantomData::<Self>,
        ))
    }

    async fn before_send(&self, conn: Conn) -> Conn {
        if let Some(OutputHandlerWrapper(handler, _)) = conn
            .state::<OutputHandlerWrapper<Self, OutputHandler, <Extracted as TryFromConn>::Error>>()
            .cloned()
        {
            handler.before_send(conn).await
        } else {
            conn
        }
    }

    fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
        upgrade
            .state()
            .get::<OutputHandlerWrapper<Self, OutputHandler, <Extracted as TryFromConn>::Error>>()
            .cloned()
            .map_or(false, |OutputHandlerWrapper(handler, _)| {
                handler.has_upgrade(upgrade)
            })
    }

    async fn upgrade(&self, upgrade: Upgrade) {
        if let Some(OutputHandlerWrapper(handler, _)) = upgrade
            .state()
            .get::<OutputHandlerWrapper<Self, OutputHandler, <Extracted as TryFromConn>::Error>>()
            .cloned()
        {
            handler.upgrade(upgrade).await
        }
    }
}

struct OutputHandlerWrapper<TFC, OH, EH>(Arc<Result<OH, EH>>, PhantomData<TFC>);

impl<TFC, OH, EH> Clone for OutputHandlerWrapper<TFC, OH, EH> {
    fn clone(&self) -> Self {
        Self(Arc::clone(&self.0), self.1)
    }
}