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

ambee/giterated

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

More progress :)

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨92c3f32

⁨giterated-plugin/src/new_stack/operation_walker.rs⁩ - ⁨9520⁩ bytes
Raw
1 use crate::{callback::RuntimeState, AnyFailure, AnySuccess, FFIBox};
2 use giterated_models::{
3 error::OperationError, operation::GiteratedOperation, settings::GetSetting, value::GetValue,
4 };
5
6 use serde_json::Value;
7 use tracing::{debug_span, trace, trace_span};
8
9 use crate::new_stack::ObjectOperationPair;
10
11 use super::{ObjectSettingPair, ObjectValuePair, RuntimeHandlers};
12
13 /// A wrapper for operation handling that enforces handling rules.
14 ///
15 /// # Handler Resolution
16 /// In order, handler resolution will be attempted as follows:
17 ///
18 /// | Index | object_kind | operation_kind | Special Case? |
19 /// |-------|-------------|-----------------|---------------|
20 /// | 1 | `any` | `typed` | No |
21 /// | 2 | `typed` | `any` | No |
22 /// | 3 | `any` | `any` | No |
23 /// | 4 | `any` | `GetValue` | ⚠️ Yes ⚠️ |
24 /// | 5 | `any` | `GetSetting` | ⚠️ Yes ⚠️ |
25 /// | 6 | `any` | `SetSetting` | ⚠️ Yes ⚠️ |
26 /// | 7 | `any` | `ObjectRequest` | ⚠️ Yes ⚠️ |
27 /// | 8 | `typed` | `typed` | No |
28 pub struct OperationHandlerRules<'a> {
29 object_kind: &'a str,
30 operation_name: &'a str,
31 handlers: &'a RuntimeHandlers,
32 }
33
34 impl<'o> OperationHandlerRules<'o> {
35 pub fn new(
36 object_kind: &'o str,
37 operation_name: &'o str,
38 handlers: &'o RuntimeHandlers,
39 ) -> Self {
40 Self {
41 object_kind,
42 operation_name,
43 handlers,
44 }
45 }
46
47 pub async fn handle(
48 &self,
49 runtime_state: &RuntimeState,
50 object: &str,
51 operation_payload: &[u8],
52 ) -> Result<AnySuccess, OperationError<AnyFailure>> {
53 // object_kind: `any`
54 // operation_kind: `typed`
55 if let Some(_handler) = self
56 .handlers
57 .operation_handlers
58 .get(&ObjectOperationPair::new("any", self.operation_name))
59 {
60 todo!()
61 }
62
63 // object_kind: `typed`
64 // operation_kind: `any`
65 if let Some(_handler) = self
66 .handlers
67 .operation_handlers
68 .get(&ObjectOperationPair::new(self.object_kind, "any"))
69 {}
70
71 // object_kind: `any`
72 // operation_kind: `any`
73 if let Some(_handler) = self
74 .handlers
75 .operation_handlers
76 .get(&ObjectOperationPair::new("any", "any"))
77 {}
78
79 // ⚠️ Special Case ⚠️
80 // object_kind: `any`
81 // operation_kind: `GetValue`
82 if self.operation_name == "get_value" {
83 let operation: GetValue = serde_json::from_slice(operation_payload).unwrap();
84 let _guard = trace_span!(
85 "get_value handler resolving",
86 object = self.object_kind,
87 value = operation.value_name
88 )
89 .entered();
90
91 if let Some((domain, callback)) = self.handlers.value_getters.get(
92 &ObjectValuePair::new(self.object_kind, &operation.value_name),
93 ) {
94 trace_span!(
95 "get_value handler.",
96 object = self.object_kind,
97 value_name = operation.value_name
98 );
99
100 let object_vtable = domain
101 .object_vtable(self.object_kind)
102 .ok_or_else(|| OperationError::Unhandled)?;
103 trace!("Resolved object vtable for {}", self.object_kind);
104
105 let _value_vtable = domain
106 .value_vtable(self.object_kind, &operation.value_name)
107 .ok_or_else(|| OperationError::Unhandled)?;
108 trace!(
109 "Resolved value vtable for {}::{}",
110 self.object_kind,
111 operation.value_name
112 );
113
114 let object = unsafe { (object_vtable.from_str)(object) }
115 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
116
117 let _guard = debug_span!("get_value handler");
118
119 let result = unsafe {
120 (callback.func)(
121 callback.callback_ptr,
122 runtime_state,
123 &domain.plugin.state,
124 object,
125 )
126 }
127 .await;
128
129 match result {
130 Ok(value) => return Ok(value.into()),
131 Err(_err) => todo!(),
132 }
133 } else {
134 trace!("Failed to resolve handler.");
135 }
136 }
137
138 // ⚠️ Special Case ⚠️
139 // object_kind: `any`
140 // operation_kind: `GetSetting`
141 if self.operation_name == "get_setting" {
142 let operation: GetSetting = serde_json::from_slice(operation_payload).unwrap();
143 let _guard = trace_span!(
144 "get_setting handler resolving",
145 object = self.object_kind,
146 setting = operation.setting_name
147 )
148 .entered();
149
150 if let Some((domain, callback)) = self.handlers.setting_getters.get(
151 &ObjectSettingPair::new(self.object_kind, &operation.setting_name),
152 ) {
153 trace_span!(
154 "get_setting handler.",
155 object = self.object_kind,
156 setting_name = operation.setting_name
157 );
158
159 let object_vtable = domain
160 .object_vtable(self.object_kind)
161 .ok_or_else(|| OperationError::Unhandled)?;
162 trace!("Resolved object vtable for {}", self.object_kind);
163
164 let _setting_vtable = domain
165 .setting_vtable(self.object_kind, &operation.setting_name)
166 .ok_or_else(|| OperationError::Unhandled)?;
167 trace!("Resolved setting vtable for {}", operation.setting_name);
168
169 let object = unsafe { (object_vtable.from_str)(object) }
170 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
171
172 let _guard = debug_span!("get_value handler");
173
174 let result = unsafe {
175 (callback.func)(
176 callback.callback_ptr,
177 runtime_state,
178 &domain.plugin.state,
179 object,
180 )
181 }
182 .await;
183
184 match result {
185 Ok(value) => {
186 let vtable = unsafe { (value.vtable.get_setting_vtable)() };
187 let return_value: Value = serde_json::from_slice(unsafe {
188 (value.vtable.serialize)(value).unwrap().as_ref()
189 })
190 .unwrap();
191
192 return Ok(unsafe {
193 AnySuccess::from_raw(
194 FFIBox::from_box(Box::new(return_value)).untyped(),
195 vtable,
196 )
197 });
198 }
199 Err(_err) => todo!(),
200 }
201 } else {
202 trace!("Failed to resolve handler.");
203 }
204 }
205
206 // ⚠️ Special Case ⚠️
207 // object_kind: `any`
208 // operation_kind: `SetSetting`
209 self.operation_name == "set_setting";
210
211 // ⚠️ Special Case ⚠️
212 // object_kind: `any`
213 // operation_kind: `ObjectRequest`
214 self.operation_name == "object_request";
215
216 // object_kind: `typed`
217 // operation_kind: `typed`
218 if let Some((domain, handler)) =
219 self.handlers
220 .operation_handlers
221 .get(&ObjectOperationPair::new(
222 self.object_kind,
223 self.operation_name,
224 ))
225 {
226 let _guard = trace_span!("typed_typed handler resolved").entered();
227
228 let object_vtable = domain
229 .object_vtable(self.object_kind)
230 .ok_or_else(|| OperationError::Unhandled)?;
231 trace!("Resolved object vtable for {}", self.object_kind);
232
233 let operation_vtable = domain
234 .operation_vtable(self.object_kind, self.operation_name)
235 .ok_or_else(|| OperationError::Unhandled)?;
236 trace!(
237 "Resolved operation vtable for {}::{}",
238 self.object_kind,
239 self.operation_name
240 );
241
242 let object = unsafe { (object_vtable.from_str)(object) }
243 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
244 let operation = unsafe { (operation_vtable.deserialize)(operation_payload) }
245 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
246 trace!("Parsed operation data");
247
248 let _guard = debug_span!("calling handler").entered();
249 let result = unsafe {
250 (handler.func)(
251 handler.callback_ptr,
252 runtime_state,
253 &domain.plugin.state,
254 object,
255 operation,
256 )
257 };
258
259 return result.await;
260 }
261
262 Err(OperationError::Unhandled)
263 }
264 }
265