n_observer_cffi_impl/
ior_cffi_traits.rs1use 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
13#[repr(C)]
14#[derive(Debug, Clone)]
15pub struct CffiInnerObserverReceiver {
16 pub self_ptr: *const c_void,
17 pub update_fut: extern "C" fn(*const c_void, CffiPointerBuffer) -> *const c_void,
18 pub hold_strong_publisher_ref_fut: extern "C" fn(*const c_void, *const c_void) -> *const c_void,
19}
20
21impl InnerObserverReceiver for CffiInnerObserverReceiver {
22 fn update(&self, data: Vec<Option<AnyArc>>) -> BoxFuture<'_, ()> {
23 let data = CffiPointerBuffer::from_slice(
24 data.into_iter()
25 .map(|data| {
26 (if let Some(data) = data {
27 *data.downcast::<SafePtr>().expect("data must be SafePtr")
28 } else {
29 SafePtr(std::ptr::null())
30 })
31 .0
32 })
33 .collect::<Box<[_]>>(),
34 );
35
36 let update_fn = self.update_fut;
37
38 let self_ptr = SafePtr(self.self_ptr);
39
40 Box::pin(async move {
41 let self_ptr = self_ptr;
42
43 let data = data;
44
45 let fut = (update_fn)(self_ptr.0, data);
46
47 if fut.is_null() {
48 panic!("C function returned null pointer");
49 }
50
51 let fut = unsafe {
52 (fut as *mut CffiFuture)
55 .as_mut()
56 .expect("CffiFuture cannot be null")
57 };
58
59 fut.await;
60 })
61 }
62 fn hold_strong_publisher_ref(
63 &self,
64 publisher: Arc<dyn Publisher + Send + Sync>,
65 ) -> BoxFuture<'_, ()> {
66 let publisher = SafePtr(Arc::into_raw(publisher) as *const c_void);
67
68 let hold_strong_publisher_ref_fn = self.hold_strong_publisher_ref_fut;
69
70 let self_ptr = SafePtr(self.self_ptr);
71
72 Box::pin(async move {
73 let self_ptr = self_ptr;
74
75 let publisher = publisher;
76
77 let fut = (hold_strong_publisher_ref_fn)(self_ptr.0, publisher.0);
78
79 if fut.is_null() {
80 panic!("C function returned null pointer");
81 }
82
83 let fut = unsafe {
84 (fut as *mut CffiFuture)
87 .as_mut()
88 .expect("CffiFuture cannot be null")
89 };
90
91 fut.await;
92 })
93 }
94}
95
96unsafe impl Send for CffiInnerObserverReceiver {}
97
98unsafe impl Sync for CffiInnerObserverReceiver {}
99
100impl CffiInnerObserverReceiver {
101 extern "C" fn update_fut_impl(
102 self_ptr: *const c_void,
103 data: CffiPointerBuffer,
104 ) -> *const c_void {
105 let self_ref = unsafe {
106 (self_ptr as *const &(dyn InnerObserverReceiver + Send + Sync))
107 .as_ref()
108 .expect("Self pointer cannot be null")
109 };
110
111 let data = data
112 .as_slice()
113 .iter()
114 .copied()
115 .map(|value| {
116 if !value.is_null() {
117 let value = SafePtr(value);
118
119 Some(Arc::new(value) as AnyArc)
120 } else {
121 None
122 }
123 })
124 .collect();
125
126 let fut = self_ref.update(data);
127
128 CffiFuture::from_rust_future_boxed(fut).into_raw()
129 }
130 extern "C" fn hold_strong_publisher_ref_fut_impl(
131 self_ptr: *const c_void,
132 publisher: *const c_void,
133 ) -> *const c_void {
134 CffiFuture::from_rust_future_boxed(async move {}).into_raw()
137 }
138}
139
140impl From<&dyn InnerObserverReceiver> for CffiInnerObserverReceiver {
141 fn from(inner: &dyn InnerObserverReceiver) -> Self {
142 CffiInnerObserverReceiver {
143 self_ptr: Box::into_raw(Box::new(inner)) as *const c_void,
147
148 update_fut: CffiInnerObserverReceiver::update_fut_impl,
149
150 hold_strong_publisher_ref_fut:
151 CffiInnerObserverReceiver::hold_strong_publisher_ref_fut_impl,
152 }
153 }
154}