use std::{future::Future, sync::Arc};
mod future;
mod scheduler;
#[cfg(test)]
mod tests;
use crate::{FfiDefault, Handle, LiftArgsError, LowerReturn, RustCallStatus};
pub(crate) use future::RustFuture;
pub use scheduler::{RustFutureCallback, Scheduler};
#[repr(i8)]
#[derive(Debug, PartialEq, Eq)]
pub enum RustFuturePoll {
Ready = 0,
Wake = 1,
}
pub type RustFutureContinuationCallback = extern "C" fn(callback_data: u64, RustFuturePoll);
pub struct RustFutureContinuationBoundCallback {
callback: RustFutureContinuationCallback,
data: u64,
}
#[doc(hidden)]
#[cfg(not(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded")))]
pub trait UniffiCompatibleFuture<T>: Future<Output = T> + Send {}
#[doc(hidden)]
pub trait FutureLowerReturn<UT>: LowerReturn<UT> {}
#[cfg(not(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded")))]
impl<T, F> UniffiCompatibleFuture<T> for F where F: Future<Output = T> + Send {}
#[cfg(not(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded")))]
impl<UT, LR> FutureLowerReturn<UT> for LR where LR: LowerReturn<UT> + Send {}
#[cfg(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded"))]
pub trait UniffiCompatibleFuture<T>: Future<Output = T> {}
#[cfg(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded"))]
impl<T, F> UniffiCompatibleFuture<T> for F where F: Future<Output = T> {}
#[cfg(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded"))]
impl<UT, LR> FutureLowerReturn<UT> for LR where LR: LowerReturn<UT> {}
pub fn rust_future_new<F, T, UT>(future: F, tag: UT) -> Handle
where
F: UniffiCompatibleFuture<Result<T, LiftArgsError>> + 'static,
T: FutureLowerReturn<UT> + 'static,
{
let rust_future = Arc::new(RustFuture::<_, RustFutureContinuationBoundCallback>::new(
future, tag,
));
let handle = Handle::from_arc(rust_future);
trace_and_return!(handle, "rust_future_new: {handle:?}")
}
pub unsafe fn rust_future_poll<FfiType>(
handle: Handle,
callback: extern "C" fn(callback_data: u64, RustFuturePoll),
data: u64,
) {
#[cfg(feature = "ffi-trace")]
let raw_handle = handle.as_raw();
trace!("rust_future_poll: {raw_handle:x}");
Handle::into_arc_borrowed::<RustFuture<FfiType>>(handle)
.poll(RustFutureContinuationBoundCallback { callback, data });
trace!("rust_future_poll returning: {raw_handle:x}");
}
pub unsafe fn rust_future_cancel<FfiType>(handle: Handle) {
trace!("rust_future_cancel: {handle:?}");
Handle::into_arc_borrowed::<RustFuture<FfiType>>(handle).cancel()
}
pub unsafe fn rust_future_complete<FfiType>(
handle: Handle,
out_status: &mut RustCallStatus,
) -> FfiType
where
FfiType: FfiDefault,
{
trace!("rust_future_complete: {handle:?}");
Handle::into_arc_borrowed::<RustFuture<FfiType>>(handle).complete(out_status)
}
pub unsafe fn rust_future_free<FfiType>(handle: Handle) {
trace!("rust_future_free: {handle:?}");
Handle::into_arc::<RustFuture<FfiType>>(handle).free()
}