Skip to main content

n_observer_cffi_impl/
lib.rs

1mod ior_cffi_traits;
2mod observable_cffi_traits;
3mod publisher_cffi_traits;
4
5use std::{ffi::c_void, sync::Arc};
6
7use async_cffi::{CffiFuture, SafePtr};
8
9use n_observer::{CachedPublisher, Observable, Observer, Publisher};
10
11pub use ior_cffi_traits::CffiInnerObserverReceiver;
12
13pub use publisher_cffi_traits::CffiPublisher;
14
15pub use observable_cffi_traits::CffiObservable;
16
17pub async fn observer_new_async<P>(publisher: P) -> CffiObservable
18where
19    P: Publisher + Send + Sync + 'static,
20{
21    let observer: Box<dyn Observable<SafePtr>> = Box::new(Observer::new(&publisher).await);
22    let cffi = (*observer).into();
23    Box::leak(observer); // Leak to keep alive
24    cffi
25}
26
27/// `observer_get_ptr(observer: CffiObservable) -> opt_ptr<T>`
28pub async fn observer_get_ptr(observer: CffiObservable) -> *const c_void {
29    let value = observer.get().await;
30    value.map_or(std::ptr::null(), |v| {
31        let ptr = (*v).0;
32        // TODO: Leaking this to ensure the underlying data lives long enough,
33        // need to free it later.
34        let _ = Arc::into_raw(v);
35        ptr
36    })
37}
38
39/// `int_publisher_new(initial_value: i32) -> CffiPublisher`
40pub fn int_publisher_new(initial_value: i32) -> CffiPublisher {
41    let initial_value = Box::new(initial_value);
42    let initial_value = Box::into_raw(initial_value);
43    let initial_value = initial_value as *const c_void;
44    let publisher: Box<dyn Publisher> =
45        Box::new(CachedPublisher::new(Some(Arc::new(SafePtr(initial_value)))));
46
47    let cffi_publisher = (*publisher).into();
48    Box::leak(publisher); // Leak to keep alive
49    cffi_publisher
50}
51
52/// `observer_new_fut(publisher: CffiPublisher) ->
53///   ptr<CffiFuture<ptr<CffiObservable>>>`
54pub fn observer_new_fut(publisher: CffiPublisher) -> *mut c_void {
55    let observer_fut = observer_new_async(publisher);
56    let observer_fut = CffiFuture::from_rust_future_boxed(observer_fut);
57    observer_fut.into_raw()
58}
59
60/// `observer_get_fut(observer: CffiObservable) -> ptr<CffiFuture<ptr<opt_ptr<T>>>>`
61pub fn observer_get_fut(observer: CffiObservable) -> *mut c_void {
62    let fut = observer_get_ptr(observer);
63    let fut = CffiFuture::from_rust_future_boxed(fut);
64    fut.into_raw()
65}