Skip to main content

n_observer_cffi_impl/
ior_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
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                // Convert the raw pointer to a CffiFuture
53
54                (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                // Convert the raw pointer to a CffiFuture
85
86                (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        // no-op
135
136        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            // Wrap the fat pointer in a Box to get a stable address
144
145            // Leak it to keep [just the wrapper] alive
146            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}