1use std::future::Future;
8
9use ion::conversions::{BoxedIntoValue, IntoValue};
10use ion::{Context, Promise};
11use tokio::task::spawn_local;
12
13use crate::ContextExt as _;
14
15pub fn future_to_promise<'cx, F, Fut, O, E>(cx: &'cx Context, func: F) -> Option<Promise<'cx>>
17where
18 F: FnOnce(Context) -> Fut + 'static,
19 Fut: Future<Output = Result<O, E>> + 'static,
20 O: for<'cx2> IntoValue<'cx2> + 'static,
21 E: for<'cx2> IntoValue<'cx2> + 'static,
22{
23 let promise = Promise::new(cx);
24 let object = promise.handle().get();
25
26 let cx2 = unsafe { Context::new_unchecked(cx.as_ptr()) };
27
28 let handle = spawn_local(async move {
29 let future = func(cx2);
30 let result: Result<BoxedIntoValue, BoxedIntoValue> = match future.await {
31 Ok(o) => Ok(Box::new(o)),
32 Err(e) => Err(Box::new(e)),
33 };
34 (result, object)
35 });
36
37 let event_loop = unsafe { &cx.get_private().event_loop };
38 event_loop.futures.as_ref().map(|futures| {
39 futures.enqueue(handle);
40 promise
41 })
42}