Skip to main content

polyhorn_ios_sys/polykit/
callback.rs

1use objc::runtime::*;
2use objc::*;
3use std::marker::PhantomData;
4
5use crate::Raw;
6
7/// Callback that can be invoked from within Objective-C.
8pub 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    /// Initializes a newly allocated callback with the given closure.
46    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}