intrepid_core/action/
handler.rsuse futures::Stream;
use crate::{Action, ActionContext, BoxedAction, Context, Extractor, Frame, FrameOutbox, Ready};
use super::{ActiveAction, CandidateAction, ReadyAction};
pub trait Handler<Args, State>: Clone {
type Future: std::future::Future<Output = crate::Result<Frame>> + Send + 'static;
fn invoke(&self, frame: impl Into<Frame>, state: State) -> Self::Future;
fn context(&self) -> ActionContext<State>
where
State: Send + Sync + 'static,
{
ActionContext::<State>::Unit
}
fn http_handler(&self) -> crate::RequestHandler<Self, Args, State>
where
Self: Handler<Args, State> + Clone + Send + Sync + 'static,
Args: Clone + Send + Sync + 'static,
State: Clone + Send + Sync + 'static,
{
crate::RequestHandler::new(self.clone())
}
fn as_into_actionable(&self) -> BoxedAction<State>
where
Self: Clone + Send + Sync + 'static,
Args: Clone + Send + Sync + 'static,
State: Clone + Send + Sync + 'static,
{
Box::new(self.clone().candidate())
}
fn into_stream(self, state: State) -> (impl Stream<Item = crate::Result<Frame>>, FrameOutbox)
where
Self: Clone + Send + Sync + 'static,
Args: Clone + Send + Sync + 'static,
State: Clone + Send + Sync + 'static,
{
self.active(state).into_stream()
}
fn ready(self, state: State) -> ReadyAction<Self, Args, State>
where
Self: Clone + Send + 'static,
Args: Clone + Send + 'static,
State: Clone + Send + 'static,
{
Ready::new(self, state).into()
}
fn candidate(self) -> CandidateAction<Self, Args, State>
where
Self: Clone + Send + 'static,
Args: Clone + Send + 'static,
State: Clone + Send + 'static,
{
Action::new(self.clone())
}
fn active(self, state: State) -> ActiveAction
where
Self: Clone + Send + Sync + 'static,
Args: Clone + Send + Sync + 'static,
State: Clone + Send + Sync + 'static,
{
self.clone().as_into_actionable().into_actionable(state)
}
}
macro_rules! define_handler_for_tuple ({ $($param:ident)* } => {
#[allow(non_snake_case, unused_mut, unused_variables)]
impl<Func, Future, State, Output, $($param,)*>
Handler<($($param,)*), State> for Func
where
Func: FnOnce($($param,)*) -> Future + Clone + Send + 'static,
State: Send + Sync + 'static,
Output: Into<Frame>,
Future: std::future::Future<Output = Output> + Send + 'static,
$(
$param: Extractor<State> + Send,
)*
{
type Future = crate::FrameFuture;
fn invoke(&self, input: impl Into<Frame>, state: State) -> Self::Future {
let handler = self.clone();
let input = input.into();
let action: ActionContext<State> = handler.context();
let context = Context::with_action(action, state);
crate::FrameFuture::from_async_block(async move {
let input = &input;
let handler = handler;
let context = &context;
$(
let $param = match $param::extract_from_frame_and_state(input.clone(), context) {
Ok(value) => value,
Err(rejection) => return Err(rejection.into()),
};
)*
let response = handler($($param,)*).await;
Ok(response.into())
})
}
}
});
define_handler_for_tuple! {}
define_handler_for_tuple! { A }
define_handler_for_tuple! { A B }
define_handler_for_tuple! { A B C }
define_handler_for_tuple! { A B C D }
define_handler_for_tuple! { A B C D E }
define_handler_for_tuple! { A B C D E F }
define_handler_for_tuple! { A B C D E F G }
define_handler_for_tuple! { A B C D E F G H }
define_handler_for_tuple! { A B C D E F G H I }
define_handler_for_tuple! { A B C D E F G H I J }
define_handler_for_tuple! { A B C D E F G H I J K }
define_handler_for_tuple! { A B C D E F G H I J K L }