use bindings::wasi::io;
use std::future::Future;
use std::mem;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Wake, Waker};
pub mod bindings {
wit_bindgen::generate!({
world: "imports",
path: "io.wit",
});
}
impl std::fmt::Display for io::streams::Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.to_debug_string())
}
}
impl std::error::Error for io::streams::Error {}
static WAKERS: Mutex<Vec<(io::poll::Pollable, Waker)>> = Mutex::new(Vec::new());
pub fn push_waker(pollable: io::poll::Pollable, waker: Waker) {
WAKERS.lock().unwrap().push((pollable, waker));
}
pub fn run<T>(future: impl Future<Output = T>) -> T {
futures::pin_mut!(future);
struct DummyWaker;
impl Wake for DummyWaker {
fn wake(self: Arc<Self>) {}
}
let waker = Arc::new(DummyWaker).into();
loop {
match future.as_mut().poll(&mut Context::from_waker(&waker)) {
Poll::Pending => {
let mut new_wakers = Vec::new();
let wakers = mem::take::<Vec<_>>(&mut WAKERS.lock().unwrap());
assert!(!wakers.is_empty());
let pollables = wakers
.iter()
.map(|(pollable, _)| pollable)
.collect::<Vec<_>>();
let mut ready = vec![false; wakers.len()];
for index in io::poll::poll(&pollables) {
ready[usize::try_from(index).unwrap()] = true;
}
for (ready, (pollable, waker)) in ready.into_iter().zip(wakers) {
if ready {
waker.wake()
} else {
new_wakers.push((pollable, waker));
}
}
*WAKERS.lock().unwrap() = new_wakers;
}
Poll::Ready(result) => break result,
}
}
}