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/callback/operation.rs⁩ - ⁨5932⁩ bytes
Raw
1 use giterated_models::{
2 error::OperationError,
3 object::GiteratedObject,
4 operation::{GiteratedOperation, OperationState},
5 };
6
7 use crate::{
8 future::{RuntimeFuture, RuntimeFuturesExt},
9 new_stack::{handle::RuntimeHandle, PluginState},
10 vtable::OperationVTable,
11 AnyFailure, AnyObject, AnyOperation, AnySuccess, FFIBox,
12 };
13
14 use std::{any::type_name, fmt::Debug, future::Future};
15
16 use super::{CallbackPtr, RuntimeState};
17
18 #[derive(Clone, Copy)]
19 pub struct OperationHandlerCallback {
20 pub callback_ptr: CallbackPtr,
21 pub func: unsafe extern "C" fn(
22 CallbackPtr,
23 &RuntimeState,
24 &PluginState,
25 object: AnyObject,
26 operation: AnyOperation,
27 )
28 -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>>,
29 }
30
31 impl OperationHandlerCallback {
32 pub fn new<
33 S,
34 O: GiteratedObject,
35 D: GiteratedOperation<O>,
36 A,
37 T: IntoPluginOperationHandler<S, O, D, A>,
38 >(
39 handler: T,
40 ) -> Self {
41 OperationHandlerCallback {
42 func: T::handle,
43 callback_ptr: T::callback_ptr(&handler),
44 }
45 }
46 }
47
48 pub trait IntoPluginOperationHandler<S, O: GiteratedObject, D: GiteratedOperation<O>, A> {
49 unsafe extern "C" fn handle(
50 callback_ptr: CallbackPtr,
51 runtime_state: &RuntimeState,
52 state: &PluginState,
53 object: AnyObject,
54 operation: AnyOperation,
55 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>>;
56 fn callback_ptr(&self) -> CallbackPtr;
57 }
58
59 impl<F, S, O, D, Fut> IntoPluginOperationHandler<S, O, D, ()> for F
60 where
61 Fut: Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send + Sync,
62 F: Fn(S, O, D) -> Fut + Send + Sync + 'static,
63 S: Clone + Debug + Send + Sync + 'static,
64 O: Debug + GiteratedObject + 'static,
65 D: Debug + GiteratedOperation<O> + 'static,
66 {
67 unsafe extern "C" fn handle(
68 callback: CallbackPtr,
69 runtime_state: &RuntimeState,
70 state: &PluginState,
71 mut object: AnyObject,
72 mut operation: AnyOperation,
73 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
74 let _guard = trace_span!(
75 "operation handler",
76 object = type_name::<O>(),
77 operation = type_name::<D>()
78 )
79 .entered();
80 let state = unsafe { state.transmute_ref::<S>() };
81
82 // Since this is Rust code, we know that the AnyObject and AnyOperation are just boxes
83 let object = unsafe { object.transmute_owned::<O>() };
84 let operation = unsafe { operation.transmute_owned::<D>() };
85
86 // Cast the callback ptr to ourselves
87 let callback: *const F = std::mem::transmute(callback.0);
88 let callback = callback.as_ref().unwrap();
89
90 let state = state.clone();
91 runtime_state.spawn_future(async move {
92 let result = callback(state, *object, *operation).await;
93
94 match result {
95 Ok(success) => unsafe {
96 Ok(AnySuccess::from_raw(
97 FFIBox::from_box(Box::new(success)).untyped(),
98 OperationVTable::new::<O, D>(),
99 ))
100 },
101 Err(err) => match err {
102 OperationError::Operation(_) => todo!(),
103 OperationError::Internal(_) => todo!(),
104 OperationError::Unhandled => todo!(),
105 },
106 }
107 })
108 }
109
110 fn callback_ptr(&self) -> CallbackPtr {
111 unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) }
112 }
113 }
114
115 impl<F, S, O, D, Fut, A1> IntoPluginOperationHandler<S, O, D, (A1,)> for F
116 where
117 Fut: Future<Output = Result<D::Success, OperationError<D::Failure>>>,
118 F: Fn(S, O, D, A1) -> Fut,
119 S: Clone + Debug,
120 O: Debug + GiteratedObject,
121 D: Debug + GiteratedOperation<O>,
122 {
123 unsafe extern "C" fn handle(
124 _callback_ptr: CallbackPtr,
125 _runtime_state: &RuntimeState,
126 _state: &PluginState,
127 _object: AnyObject,
128 _operation: AnyOperation,
129 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
130 todo!()
131 }
132
133 fn callback_ptr(&self) -> CallbackPtr {
134 todo!()
135 }
136 }
137
138 impl<F, S, O, D, Fut, A1, A2> IntoPluginOperationHandler<S, O, D, (A1, A2)> for F
139 where
140 Fut: Future<Output = Result<D::Success, OperationError<D::Failure>>>,
141 F: Fn(S, O, D, A1, A2) -> Fut,
142 S: Clone + Debug,
143 O: Debug + GiteratedObject,
144 D: Debug + GiteratedOperation<O>,
145 {
146 unsafe extern "C" fn handle(
147 _callback_ptr: CallbackPtr,
148 _runtime_state: &RuntimeState,
149 _state: &PluginState,
150 _object: AnyObject,
151 _operation: AnyOperation,
152 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
153 todo!()
154 }
155
156 fn callback_ptr(&self) -> CallbackPtr {
157 todo!()
158 }
159 }
160
161 pub trait FromOperationState<O, D>: Sized {
162 fn from_operation_state(
163 operation_state: &OperationState,
164 runtime_state: &RuntimeState,
165 object: &O,
166 operation: &D,
167 ) -> Result<Self, OperationError<anyhow::Error>>;
168 }
169
170 impl<O, D> FromOperationState<O, D> for RuntimeHandle {
171 fn from_operation_state(
172 _operation_state: &OperationState,
173 runtime_state: &RuntimeState,
174 _object: &O,
175 _operation: &D,
176 ) -> Result<Self, OperationError<anyhow::Error>> {
177 Ok(unsafe { RuntimeHandle::from_vtable(runtime_state.vtable) })
178 }
179 }
180
181 impl<O, D, T> FromOperationState<O, D> for Option<T>
182 where
183 T: FromOperationState<O, D>,
184 {
185 fn from_operation_state(
186 operation_state: &OperationState,
187 runtime_state: &RuntimeState,
188 object: &O,
189 operation: &D,
190 ) -> Result<Self, OperationError<anyhow::Error>> {
191 Ok(T::from_operation_state(operation_state, runtime_state, object, operation).ok())
192 }
193 }
194