Skip to main content

n_observer_cffi_impl/
publisher_cffi_traits.rs

1// This file is autogenerated. Do not edit directly.
2use std::{
3    ffi::{c_ulong, c_void},
4    sync::Arc,
5};
6
7use async_cffi::{CffiFuture, CffiPointerBuffer, SafePtr};
8
9use futures::future::BoxFuture;
10
11use n_observer::{AnyArc, InnerObserverReceiver, Observable, Publisher};
12
13use crate::CffiInnerObserverReceiver;
14
15#[repr(C)]
16#[derive(Debug, Clone)]
17pub struct CffiPublisher {
18    pub self_ptr: *const c_void,
19    pub add_observer_fut:
20        extern "C" fn(*const c_void, CffiInnerObserverReceiver, c_ulong) -> *const c_void,
21    pub notify_fut: extern "C" fn(*const c_void, *const c_void) -> *const c_void,
22}
23
24impl Publisher for CffiPublisher {
25    fn add_observer(
26        &self,
27        observer: Box<dyn InnerObserverReceiver>,
28        input_index: usize,
29    ) -> BoxFuture<'_, Option<AnyArc>> {
30        let observer = {
31            let cffi_observer = (*observer).into();
32
33            Box::leak(observer); // Leak to keep alive
34
35            cffi_observer
36        };
37
38        let input_index = input_index as c_ulong;
39
40        let add_observer_fn = self.add_observer_fut;
41
42        let self_ptr = SafePtr(self.self_ptr);
43
44        Box::pin(async move {
45            let self_ptr = self_ptr;
46
47            let observer = observer;
48
49            let input_index = input_index;
50
51            let fut = (add_observer_fn)(self_ptr.0, observer, input_index);
52
53            if fut.is_null() {
54                panic!("C function returned null pointer");
55            }
56
57            let fut = unsafe {
58                // Convert the raw pointer to a CffiFuture
59
60                (fut as *mut CffiFuture)
61                    .as_mut()
62                    .expect("CffiFuture cannot be null")
63            };
64
65            let ret = fut.await;
66
67            assert!(!ret.is_null());
68
69            let ret = ret as *const *const c_void;
70
71            let ret = *unsafe { ret.as_ref().unwrap() };
72
73            let ret = if ret.is_null() {
74                None
75            } else {
76                Some(Arc::new(SafePtr(ret)) as AnyArc)
77            };
78
79            ret
80        })
81    }
82    fn notify(&self, data: AnyArc) -> BoxFuture<'_, ()> {
83        let data = *data.downcast::<SafePtr>().expect("data must be SafePtr");
84
85        let notify_fn = self.notify_fut;
86
87        let self_ptr = SafePtr(self.self_ptr);
88
89        Box::pin(async move {
90            let self_ptr = self_ptr;
91
92            let data = data;
93
94            let fut = (notify_fn)(self_ptr.0, data.0);
95
96            if fut.is_null() {
97                panic!("C function returned null pointer");
98            }
99
100            let fut = unsafe {
101                // Convert the raw pointer to a CffiFuture
102
103                (fut as *mut CffiFuture)
104                    .as_mut()
105                    .expect("CffiFuture cannot be null")
106            };
107
108            fut.await;
109        })
110    }
111}
112
113unsafe impl Send for CffiPublisher {}
114
115unsafe impl Sync for CffiPublisher {}
116
117impl CffiPublisher {
118    extern "C" fn add_observer_fut_impl(
119        self_ptr: *const c_void,
120        observer: CffiInnerObserverReceiver,
121        input_index: c_ulong,
122    ) -> *const c_void {
123        let self_ref = unsafe {
124            (self_ptr as *const &(dyn Publisher + Send + Sync))
125                .as_ref()
126                .expect("Self pointer cannot be null")
127        };
128
129        let observer = Box::new(observer);
130
131        let input_index = input_index as usize;
132
133        let fut = Box::pin(async move {
134            let ret = self_ref.add_observer(observer, input_index).await;
135
136            let ret = ret
137                .map(|ret| ret.downcast::<SafePtr>().unwrap().0)
138                .unwrap_or(std::ptr::null());
139
140            SafePtr(ret)
141        });
142
143        CffiFuture::from_rust_future_boxed(fut).into_raw()
144    }
145    extern "C" fn notify_fut_impl(self_ptr: *const c_void, data: *const c_void) -> *const c_void {
146        let self_ref = unsafe {
147            (self_ptr as *const &(dyn Publisher + Send + Sync))
148                .as_ref()
149                .expect("Self pointer cannot be null")
150        };
151
152        let data = Arc::new(SafePtr(data));
153
154        let fut = self_ref.notify(data);
155
156        CffiFuture::from_rust_future_boxed(fut).into_raw()
157    }
158}
159
160impl From<&dyn Publisher> for CffiPublisher {
161    fn from(inner: &dyn Publisher) -> Self {
162        CffiPublisher {
163            // Wrap the fat pointer in a Box to get a stable address
164
165            // Leak it to keep [just the wrapper] alive
166            self_ptr: Box::into_raw(Box::new(inner)) as *const c_void,
167
168            add_observer_fut: CffiPublisher::add_observer_fut_impl,
169
170            notify_fut: CffiPublisher::notify_fut_impl,
171        }
172    }
173}