polyhorn_ios_sys/polykit/
callback.rs1use objc::runtime::*;
2use objc::*;
3use std::marker::PhantomData;
4
5use crate::Raw;
6
7pub struct PLYCallback<T>
9where
10 T: Raw,
11{
12 object: *mut Object,
13 marker: PhantomData<T>,
14}
15
16struct PLYCallbackData<T, F>
17where
18 F: FnMut(T) + Send + Sync,
19 T: Raw,
20{
21 closure: F,
22 marker: PhantomData<T>,
23}
24
25impl<T, F> UITypeErasedCallbackData for PLYCallbackData<T, F>
26where
27 F: FnMut(T) + Send + Sync,
28 T: Raw,
29{
30 fn invoke(&mut self, object: *mut Object) {
31 (self.closure)(unsafe { T::from_raw_retain(object) })
32 }
33}
34
35trait UITypeErasedCallbackData {
36 fn invoke(&mut self, object: *mut Object);
37}
38
39struct UITypeErasedCallbackDataWrapper(Box<dyn UITypeErasedCallbackData>);
40
41impl<T> PLYCallback<T>
42where
43 T: Raw,
44{
45 pub fn new<F>(value: F) -> Self
47 where
48 F: FnMut(T) + Send + Sync + 'static,
49 T: Raw + 'static,
50 {
51 let data = UITypeErasedCallbackDataWrapper(Box::new(PLYCallbackData {
52 closure: value,
53 marker: PhantomData,
54 }));
55
56 unsafe {
57 unsafe fn hook(data: *mut UITypeErasedCallbackDataWrapper, argument: *mut Object) {
58 data.as_mut().unwrap().0.invoke(argument);
59 }
60
61 unsafe fn free(data: *mut UITypeErasedCallbackDataWrapper) {
62 Box::from_raw(data);
63 }
64
65 let data = Box::into_raw(Box::new(data));
66
67 let mut object: *mut Object = msg_send![class!(PLYCallback), alloc];
68
69 object = msg_send![object, initWithHook: hook as usize
70 free: free as usize
71 data: data as usize];
72
73 PLYCallback::from_raw(object)
74 }
75 }
76}
77
78impl<T> Raw for PLYCallback<T>
79where
80 T: Raw,
81{
82 unsafe fn from_raw(object: *mut Object) -> Self {
83 PLYCallback {
84 object,
85 marker: PhantomData,
86 }
87 }
88
89 unsafe fn as_raw(&self) -> *mut Object {
90 self.object
91 }
92}
93
94impl<T> Drop for PLYCallback<T>
95where
96 T: Raw,
97{
98 fn drop(&mut self) {
99 unsafe { objc_release(self.object) }
100 }
101}