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

ambee/giterated

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

Fix LatestCommit

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨3ff68ad

⁨giterated-stack/src/substack.rs⁩ - ⁨11106⁩ bytes
Raw
1 use std::{collections::HashMap, sync::Arc};
2
3 use futures_util::FutureExt;
4 use giterated_models::{
5 error::OperationError,
6 instance::Instance,
7 object::{GiteratedObject, ObjectRequest, ObjectResponse},
8 operation::GiteratedOperation,
9 settings::Setting,
10 value::GiteratedObjectValue,
11 };
12 use tracing::{info, trace};
13
14 use crate::{
15 handler::HandlerWrapper, provider::MetadataProvider, AnyFailure, AnyObject, AnyOperation,
16 AnySetting, AnySuccess, AnyValue, GiteratedStack, GiteratedStackState, IntoGiteratedHandler,
17 ObjectOperationPair, ObjectSettingPair, ObjectValuePair, OperationHandler, RuntimeMetadata,
18 SettingChange, SettingGetter, StackOperationState, ValueChange, ValueGetter,
19 };
20
21 pub struct SubstackBuilder<S: GiteratedStackState> {
22 pub(crate) operation_handlers: HashMap<ObjectOperationPair<'static>, OperationHandler>,
23 pub(crate) value_getters: HashMap<ObjectValuePair<'static>, ValueGetter>,
24 pub(crate) setting_getters: HashMap<&'static str, SettingGetter>,
25 pub(crate) metadata: RuntimeMetadata,
26 pub(crate) value_change: HashMap<ObjectValuePair<'static>, ValueChange>,
27 pub(crate) metadata_providers: Vec<Box<dyn MetadataProvider>>,
28 pub(crate) setting_change: HashMap<ObjectSettingPair<'static>, SettingChange>,
29
30 pub(crate) state: S,
31 }
32
33 impl<S: GiteratedStackState + 'static> SubstackBuilder<S> {
34 pub fn new(state: S) -> Self {
35 Self {
36 operation_handlers: Default::default(),
37 value_getters: Default::default(),
38 setting_getters: Default::default(),
39 metadata: Default::default(),
40 value_change: Default::default(),
41 metadata_providers: Default::default(),
42 setting_change: Default::default(),
43 state,
44 }
45 }
46 }
47
48 impl<S: Send + Sync + Clone + 'static> SubstackBuilder<S> {
49 /// Insert an operation handler into the runtime builder.
50 ///
51 /// # Type Registration
52 /// Inserting the handler will automatically, if required, register the operation type of the
53 /// handler. It will **not** register the object type automatically.
54 pub fn operation<O, D, A, H>(&mut self, handler: H) -> &mut Self
55 where
56 O: GiteratedObject + Clone,
57 D: GiteratedOperation<O> + Clone,
58 H: IntoGiteratedHandler<
59 (O, D),
60 A,
61 S,
62 StackOperationState,
63 Result<D::Success, OperationError<D::Failure>>,
64 > + Send
65 + Sync
66 + 'static,
67 O: 'static,
68 D: 'static,
69 D::Failure: std::fmt::Debug + 'static,
70 D::Success: 'static,
71 {
72 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
73
74 let wrapped = wrapped.map(
75 |(any_object, any_operation): &(AnyObject, AnyOperation),
76 _state: &StackOperationState| {
77 Ok((
78 any_object.0.downcast_ref::<O>().unwrap().clone(),
79 any_operation.0.downcast_ref::<D>().unwrap().clone(),
80 ))
81 },
82 );
83
84 let wrapped = wrapped.map_return(|ret_val, _state| match ret_val {
85 Ok(success) => Ok(AnySuccess(Arc::new(success))),
86 Err(err) => Err(match err {
87 OperationError::Operation(failure) => {
88 OperationError::Operation(AnyFailure(Arc::new(failure)))
89 }
90 OperationError::Internal(err) => OperationError::Internal(err),
91 OperationError::Unhandled => OperationError::Unhandled,
92 }),
93 });
94
95 let pair = ObjectOperationPair::from_types::<O, D>();
96
97 self.operation_handlers.insert(pair, wrapped);
98
99 self.metadata.register_operation::<O, D>();
100
101 self
102 }
103
104 /// Register a [`GiteratedObject`] type with the runtime.
105 ///
106 /// # Type Registration
107 /// This will register the provided object type.
108 pub fn object<O: GiteratedObject + 'static>(&mut self) -> &mut Self {
109 self.metadata.register_object::<O>();
110
111 // Insert handler so ObjectRequest is handled properly
112
113 self.operation(
114 move |_object: Instance,
115 operation: ObjectRequest,
116 _state: S,
117 _operation_state: StackOperationState,
118 stack: Arc<GiteratedStack>| {
119 let operation = operation.clone();
120 async move {
121 for (_object_name, object_meta) in stack.metadata.objects.iter() {
122 if (object_meta.from_str)(&operation.0).is_ok() {
123 return Ok(ObjectResponse(operation.0.clone()));
124 }
125 }
126
127 Err(OperationError::Unhandled)
128 }
129 .boxed_local()
130 },
131 );
132
133 self
134 }
135
136 /// Register a [`Setting`] type with the runtime.
137 ///
138 /// # Type Registration
139 /// This will register the provided setting type.
140 pub fn setting<O: GiteratedObject + 'static, T: Setting + 'static + Clone>(
141 &mut self,
142 ) -> &mut Self {
143 self.metadata.register_setting::<O, T>();
144
145 self
146 }
147
148 /// Register a [`GiteratedObjectValue`] that is also a [`Setting`], which
149 /// allows for automatic value updates.
150 pub fn value_setting<
151 O: GiteratedObject + 'static + Clone,
152 T: GiteratedObjectValue<Object = O> + Setting + 'static + Clone,
153 >(
154 &mut self,
155 ) -> &mut Self {
156 self.metadata.register_setting::<O, T>();
157 self.metadata.register_value::<O, T>();
158
159 self.setting_change.insert(
160 ObjectSettingPair::from_types::<O, T>(),
161 HandlerWrapper::new(
162 (),
163 move |object: AnyObject,
164 setting: AnySetting,
165 _state: (),
166 operation_state: StackOperationState,
167 stack: Arc<GiteratedStack>| {
168 trace!(
169 "value setting updated {}::{}",
170 O::object_name(),
171 T::value_name()
172 );
173 let object = object.clone();
174 async move {
175 let object = object.0.downcast_ref::<O>().unwrap();
176 let setting = setting.0.downcast_ref::<T>().unwrap();
177 stack
178 .value_update(object.clone(), setting.clone(), &operation_state)
179 .await;
180 Ok(())
181 }
182 .boxed_local()
183 },
184 ),
185 );
186
187 let wrapped = HandlerWrapper::new(
188 self.state.clone(),
189 |object: AnyObject,
190 _state: _,
191 _operation_state: StackOperationState,
192 stack: Arc<GiteratedStack>| {
193 info!("a setting handler called");
194 let object = object.clone();
195 async move {
196 match stack
197 .new_get_setting::<O, T>(object.0.downcast_ref().unwrap())
198 .await
199 {
200 Ok(setting) => Ok(AnyValue(Arc::new(setting))),
201 Err(err) => {
202 panic!("Error: {:?}", err);
203 }
204 }
205 }
206 .boxed_local()
207 },
208 );
209
210 self.value_getters
211 .insert(ObjectValuePair::from_types::<O, T>(), wrapped);
212
213 self
214 }
215
216 /// Register a [`GiteratedObjectValue<O>`] type with the runtime, providing
217 /// its associated handler for [`GetValue`].
218 ///
219 /// # Type Registration
220 /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified
221 /// object type. It will **not** register the object type automatically.
222 pub fn value<O, V, A, F, E>(&mut self, handler: F) -> &mut Self
223 where
224 O: GiteratedObject + 'static,
225 V: GiteratedObjectValue<Object = O> + 'static + Clone,
226 F: IntoGiteratedHandler<(O,), A, S, StackOperationState, Result<V, OperationError<E>>>
227 + Send
228 + Sync,
229 E: Into<anyhow::Error> + 'static + std::fmt::Debug + Clone,
230 F: 'static,
231 {
232 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
233
234 let wrapped = wrapped.map(
235 |(any_object,): &(AnyObject,), _state: &StackOperationState| {
236 Ok((any_object
237 .0
238 .downcast_ref::<O>()
239 .ok_or_else(|| OperationError::Internal(DowncastError.into()))?
240 .clone(),))
241 },
242 );
243
244 let wrapped = wrapped.map_return(|ret_val, _state| match ret_val {
245 Ok(success) => Ok(AnyValue(Arc::new(success))),
246 Err(err) => Err(match err {
247 OperationError::Operation(failure) => OperationError::Internal(failure.into()),
248 OperationError::Internal(err) => OperationError::Internal(err),
249 OperationError::Unhandled => OperationError::Unhandled,
250 }),
251 });
252
253 assert!(self
254 .value_getters
255 .insert(ObjectValuePair::from_types::<O, V>(), wrapped)
256 .is_none());
257
258 self.metadata.register_value::<O, V>();
259
260 self
261 }
262
263 pub fn value_change<O, A, F, V>(&mut self, handler: F) -> &mut Self
264 where
265 O: GiteratedObject + 'static,
266 F: IntoGiteratedHandler<
267 (O, V),
268 A,
269 S,
270 StackOperationState,
271 Result<(), OperationError<anyhow::Error>>,
272 > + Send
273 + Sync,
274 V: GiteratedObjectValue<Object = O> + Clone + 'static,
275 O: 'static,
276 V: 'static,
277 F: 'static,
278 {
279 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
280
281 let wrapped = wrapped.map(
282 |(any_object, any_value): &(AnyObject, AnyValue), _state: &StackOperationState| {
283 Ok((
284 any_object
285 .0
286 .downcast_ref::<O>()
287 .ok_or_else(|| OperationError::Internal(DowncastError.into()))?
288 .clone(),
289 any_value
290 .0
291 .downcast_ref::<V>()
292 .ok_or_else(|| OperationError::Internal(DowncastError.into()))?
293 .clone(),
294 ))
295 },
296 );
297
298 assert!(self
299 .value_change
300 .insert(ObjectValuePair::from_types::<O, V>(), wrapped)
301 .is_none());
302
303 self
304 }
305
306 pub fn object_metadata_provider(&mut self, provider: Box<dyn MetadataProvider>) -> &mut Self {
307 self.metadata_providers.push(provider);
308
309 self
310 }
311 }
312
313 #[derive(Debug, Clone, thiserror::Error)]
314 #[error("downcast error")]
315 pub struct DowncastError;
316