JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Remove unwrap statements and return OperationError's

erremilia - ⁨2⁩ years ago

parent: tbd commit: ⁨cf491a4

⁨giterated-stack/src/handler/mod.rs⁩ - ⁨7742⁩ bytes
Raw
1 use std::{any::Any, sync::Arc};
2 pub mod handler_impl;
3 use futures_util::{future::LocalBoxFuture, Future, FutureExt};
4 use giterated_models::error::OperationError;
5
6 use crate::{
7 AuthenticatedInstance, AuthenticatedUser, GiteratedStack, MissingValue, StackOperationState,
8 };
9
10 #[async_trait::async_trait(?Send)]
11 pub trait IntoGiteratedHandler<Params, AdditionalParams, State, OState, Output>
12 where
13 // Output cannot have non-static references
14 Output: 'static,
15 {
16 type Future: Future<Output = Output>;
17
18 async fn handle(&self, parameters: Params, state: State, operation_state: OState) -> Output;
19 }
20
21 pub struct HandlerTree<Kind> {
22 elements: Vec<Kind>,
23 }
24
25 impl<Kind> Default for HandlerTree<Kind> {
26 fn default() -> Self {
27 Self {
28 elements: Default::default(),
29 }
30 }
31 }
32
33 impl<'fut: 'o + 'p, 'p, 'o, P, O, E> HandlerTree<HandlerWrapper<P, O, E>>
34 where
35 P: Clone,
36 {
37 pub fn push(&mut self, handler: HandlerWrapper<P, O, E>) {
38 self.elements.push(handler);
39 }
40 pub async fn handle(
41 &self,
42 parameters: P,
43 operation_state: StackOperationState,
44 ) -> Result<O, OperationError<E>> {
45 for handler in self.elements.iter() {
46 match handler
47 .handle(parameters.clone(), operation_state.clone())
48 .await
49 {
50 Ok(handled) => return Ok(handled),
51 Err(err) => match err {
52 OperationError::Internal(err) => return Err(OperationError::Internal(err)),
53 OperationError::Operation(err) => return Err(OperationError::Operation(err)),
54 OperationError::Unhandled => continue,
55 },
56 }
57 }
58
59 Err(OperationError::Unhandled)
60 }
61 }
62
63 pub struct HandlerWrapper<P, O, E> {
64 func: Arc<
65 dyn Fn(
66 P,
67 Arc<dyn Any + Send + Sync>,
68 StackOperationState,
69 ) -> LocalBoxFuture<'static, Result<O, OperationError<E>>>
70 + Send
71 + Sync,
72 >,
73 state: Arc<dyn Any + Send + Sync>,
74 }
75
76 impl<P, O, E> HandlerWrapper<P, O, E> {
77 pub fn new<S, F, A>(state: S, handler: F) -> Self
78 where
79 F: IntoGiteratedHandler<P, A, S, StackOperationState, Result<O, OperationError<E>>>
80 + Send
81 + Sync,
82 S: Send + Sync + Clone + 'static,
83 E: 'static,
84 P: 'static + Clone,
85 F: 'static,
86 O: 'static,
87 {
88 let state = Arc::new(state);
89
90 let handler_func = Arc::new(handler);
91 let state_two = state.clone();
92 HandlerWrapper {
93 func: Arc::new(
94 move |args: P,
95 state: Arc<dyn Any + Send + Sync>,
96 operation_state: StackOperationState| {
97 let handler = handler_func.clone();
98 let operation_state = operation_state.clone();
99 let state = state.downcast_ref::<S>().unwrap();
100 let state = state.clone();
101 async move {
102 let handler = handler.clone();
103 let operation_state = operation_state;
104 handler.handle(args, state, operation_state).await
105 }
106 .boxed_local()
107 },
108 ),
109 state: state_two,
110 }
111 }
112
113 pub async fn handle(
114 &self,
115 required: P,
116 operation_state: StackOperationState,
117 ) -> Result<O, OperationError<E>> {
118 (self.func)(required, self.state.clone(), operation_state).await
119 }
120
121 pub fn map<F, N, R>(self, predicate: F) -> HandlerWrapper<N, O, R>
122 where
123 F: Fn(&N, &StackOperationState) -> Result<P, OperationError<R>> + Clone + Send + Sync,
124 R: std::fmt::Debug + 'static,
125 E: Into<OperationError<R>> + 'static,
126 OperationError<R>: From<OperationError<E>> + 'static,
127 F: 'static,
128 N: 'static,
129 P: 'static,
130 O: 'static,
131 {
132 let func = Arc::new(self.func);
133 let predicate = Arc::new(predicate);
134 HandlerWrapper {
135 func: Arc::new(
136 move |args: N,
137 state: Arc<dyn Any + Send + Sync>,
138 operation_state: StackOperationState| {
139 let predicate_output = predicate(&args, &operation_state);
140 let func = func.clone();
141 let operation_state: StackOperationState = operation_state.clone();
142 async move {
143 let predicate_output = predicate_output?;
144 let operation_state = operation_state;
145 match (func)(predicate_output, state, operation_state).await {
146 Ok(success) => Ok(success),
147 Err(err) => Err(err.into()),
148 }
149 }
150 .boxed_local()
151 },
152 ),
153 state: self.state,
154 }
155 }
156
157 pub fn map_return<F, NR, NE>(self, predicate: F) -> HandlerWrapper<P, NR, NE>
158 where
159 F: Fn(Result<O, OperationError<E>>, &StackOperationState) -> Result<NR, OperationError<NE>>
160 + Clone
161 + Send
162 + Sync,
163 O: 'static,
164 F: 'static,
165 E: 'static,
166 P: 'static,
167 {
168 let predicate = Arc::new(predicate);
169 let func = self.func;
170 HandlerWrapper {
171 func: Arc::new(
172 move |args: P,
173 state: Arc<dyn Any + Send + Sync>,
174 operation_state: StackOperationState| {
175 let clone = predicate.clone();
176 let func = func.clone();
177 let _statoperation_statee = operation_state.clone();
178
179 async move {
180 let func = func.clone();
181 let clone = clone;
182 let operation_state = operation_state;
183 clone(
184 (func)(args, state, operation_state.clone()).await,
185 &operation_state,
186 )
187 }
188 .boxed_local()
189 },
190 ),
191 state: self.state,
192 }
193 }
194 }
195
196 #[async_trait::async_trait(?Send)]
197 pub trait HandlerResolvable<RequiredParameters, OperationState>: Sized {
198 type Error;
199
200 async fn from_handler_state(
201 required_parameters: &RequiredParameters,
202 operation_state: &OperationState,
203 ) -> Result<Self, Self::Error>;
204 }
205
206 #[async_trait::async_trait(?Send)]
207 impl<R> HandlerResolvable<R, StackOperationState> for Arc<GiteratedStack> {
208 type Error = MissingValue;
209
210 async fn from_handler_state(
211 _required_parameters: &R,
212 operation_state: &StackOperationState,
213 ) -> Result<Self, Self::Error> {
214 Ok(operation_state.runtime.clone())
215 }
216 }
217
218 #[async_trait::async_trait(?Send)]
219 impl<R> HandlerResolvable<R, StackOperationState> for AuthenticatedUser {
220 type Error = MissingValue;
221
222 async fn from_handler_state(
223 _required_parameters: &R,
224 operation_state: &StackOperationState,
225 ) -> Result<Self, Self::Error> {
226 operation_state.user.clone().ok_or_else(|| MissingValue)
227 }
228 }
229
230 #[async_trait::async_trait(?Send)]
231 impl<R> HandlerResolvable<R, StackOperationState> for AuthenticatedInstance {
232 type Error = MissingValue;
233
234 async fn from_handler_state(
235 _required_parameters: &R,
236 operation_state: &StackOperationState,
237 ) -> Result<Self, Self::Error> {
238 operation_state.instance.clone().ok_or_else(|| MissingValue)
239 }
240 }
241