fp_bindgen_support/wasmer2_host/async/
future.rs

1use crate::common::{
2    mem::FatPtr,
3    r#async::{FUTURE_STATUS_PENDING, FUTURE_STATUS_READY},
4};
5use crate::wasmer2_host::{
6    io::{to_fat_ptr, to_wasm_ptr},
7    mem::import_from_guest_raw,
8    runtime::RuntimeInstanceData,
9};
10use std::{future::Future, task::Poll};
11
12// The ModuleRawFuture implements the Future Trait to handle async Futures as
13// returned from the module.
14pub struct ModuleRawFuture {
15    ptr: FatPtr,
16    env: RuntimeInstanceData,
17}
18
19impl ModuleRawFuture {
20    pub fn new(env: RuntimeInstanceData, ptr: FatPtr) -> Self {
21        Self { ptr, env }
22    }
23}
24
25impl Future for ModuleRawFuture {
26    type Output = Vec<u8>;
27
28    fn poll(
29        self: std::pin::Pin<&mut Self>,
30        cx: &mut std::task::Context<'_>,
31    ) -> std::task::Poll<Self::Output> {
32        let memory = unsafe { self.env.memory.get_unchecked() };
33
34        let ptr = self.ptr;
35
36        let (async_ptr, async_len) = to_wasm_ptr(ptr);
37        let values = async_ptr.deref(memory, 0, async_len).unwrap();
38
39        match values[0].get() {
40            FUTURE_STATUS_PENDING => {
41                let mut wakers = self.env.wakers.lock().unwrap();
42                wakers.insert(ptr, cx.waker().clone());
43                Poll::Pending
44            }
45            FUTURE_STATUS_READY => {
46                let result_ptr = values[1].get();
47                let result_len = values[2].get();
48                let result = import_from_guest_raw(&self.env, to_fat_ptr(result_ptr, result_len));
49                Poll::Ready(result)
50            }
51            value => panic!(
52                "expected async value FUTURE_STATUS_PENDING ({}) or FUTURE_STATUS_READY ({}) but got: {}",
53                FUTURE_STATUS_PENDING, FUTURE_STATUS_READY, value
54            ),
55        }
56    }
57}