intrepid_core/action/
handler.rs1use futures::Stream;
2
3use crate::{Action, ActionContext, BoxedAction, Context, Extractor, Frame, FrameOutbox, Ready};
4
5use super::{ActiveAction, CandidateAction, ReadyAction};
6
7pub trait Handler<Args, State>: Clone {
9 type Future: std::future::Future<Output = crate::Result<Frame>> + Send + 'static;
11
12 fn invoke(&self, frame: impl Into<Frame>, state: State) -> Self::Future;
15
16 fn context(&self) -> ActionContext<State>
19 where
20 State: Send + Sync + 'static,
21 {
22 ActionContext::<State>::Unit
23 }
24
25 fn as_into_actionable(&self) -> BoxedAction<State>
27 where
28 Self: Clone + Send + Sync + 'static,
29 Args: Clone + Send + Sync + 'static,
30 State: Clone + Send + Sync + 'static,
31 {
32 Box::new(self.clone().candidate())
33 }
34
35 fn into_stream(self, state: State) -> (impl Stream<Item = crate::Result<Frame>>, FrameOutbox)
39 where
40 Self: Clone + Send + Sync + 'static,
41 Args: Clone + Send + Sync + 'static,
42 State: Clone + Send + Sync + 'static,
43 {
44 self.active(state).into_stream()
45 }
46
47 fn ready(self, state: State) -> ReadyAction<Self, Args, State>
50 where
51 Self: Clone + Send + 'static,
52 Args: Clone + Send + 'static,
53 State: Clone + Send + 'static,
54 {
55 Ready::new(self, state).into()
56 }
57
58 fn candidate(self) -> CandidateAction<Self, Args, State>
61 where
62 Self: Clone + Send + 'static,
63 Args: Clone + Send + 'static,
64 State: Clone + Send + 'static,
65 {
66 Action::new(self.clone())
67 }
68
69 fn active(self, state: State) -> ActiveAction
71 where
72 Self: Clone + Send + Sync + 'static,
73 Args: Clone + Send + Sync + 'static,
74 State: Clone + Send + Sync + 'static,
75 {
76 self.clone().as_into_actionable().into_actionable(state)
77 }
78}
79
80macro_rules! define_handler_for_tuple ({ $($param:ident)* } => {
81 #[allow(non_snake_case, unused_mut, unused_variables)]
82 impl<Func, Future, State, Output, $($param,)*>
83 Handler<($($param,)*), State> for Func
84 where
85 Func: FnOnce($($param,)*) -> Future + Clone + Send + 'static,
86 State: Send + Sync + 'static,
87 Output: Into<Frame>,
88 Future: std::future::Future<Output = Output> + Send + 'static,
89 $(
90 $param: Extractor<State> + Send,
91 )*
92 {
93 type Future = crate::FrameFuture;
94
95 fn invoke(&self, input: impl Into<Frame>, state: State) -> Self::Future {
96 let handler = self.clone();
97 let input = input.into();
98 let action: ActionContext<State> = handler.context();
99 let context = Context::with_action(action, state);
100
101 crate::FrameFuture::from_async_block(async move {
102 let input = &input;
103 let handler = handler;
104 let context = &context;
105
106 $(
107 let $param = match $param::extract_from_frame_and_state(input.clone(), context) {
108 Ok(value) => value,
109 Err(rejection) => return Err(rejection.into()),
110 };
111 )*
112
113 let response = handler($($param,)*).await;
114
115 Ok(response.into())
116 })
117 }
118 }
119});
120
121define_handler_for_tuple! {}
122define_handler_for_tuple! { A }
123define_handler_for_tuple! { A B }
124define_handler_for_tuple! { A B C }
125define_handler_for_tuple! { A B C D }
126define_handler_for_tuple! { A B C D E }
127define_handler_for_tuple! { A B C D E F }
128define_handler_for_tuple! { A B C D E F G }
129define_handler_for_tuple! { A B C D E F G H }
130define_handler_for_tuple! { A B C D E F G H I }
131define_handler_for_tuple! { A B C D E F G H I J }
132define_handler_for_tuple! { A B C D E F G H I J K }
133define_handler_for_tuple! { A B C D E F G H I J K L }