use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
use crate::Error;
#[derive(Default)]
pub struct FrameFuture {
done: bool,
}
impl Future for FrameFuture {
type Output = ();
fn poll(mut self: Pin<&mut Self>, _context: &mut Context) -> Poll<Self::Output> {
if self.done {
Poll::Ready(())
} else {
self.done = true;
Poll::Pending
}
}
}
pub struct FileLoadingFuture {
pub contents: Arc<Mutex<Option<Result<Vec<u8>, Error>>>>,
}
impl Future for FileLoadingFuture {
type Output = Result<Vec<u8>, Error>;
fn poll(self: Pin<&mut Self>, _context: &mut Context) -> Poll<Self::Output> {
let mut contents = self.contents.lock().unwrap();
if let Some(contents) = contents.take() {
Poll::Ready(contents)
} else {
Poll::Pending
}
}
}
fn waker() -> Waker {
unsafe fn clone(data: *const ()) -> RawWaker {
RawWaker::new(data, &VTABLE)
}
unsafe fn wake(_data: *const ()) {
panic!(
"macroquad does not support waking futures, please use coroutines, \
otherwise your pending future will block until the next frame"
)
}
unsafe fn wake_by_ref(data: *const ()) {
wake(data);
}
unsafe fn drop(_data: *const ()) {
}
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
let raw_waker = RawWaker::new(std::ptr::null(), &VTABLE);
unsafe { Waker::from_raw(raw_waker) }
}
pub(crate) fn resume<T>(future: &mut Pin<Box<dyn Future<Output = T>>>) -> Option<T> {
let waker = waker();
let mut futures_context = std::task::Context::from_waker(&waker);
match future.as_mut().poll(&mut futures_context) {
Poll::Ready(v) => Some(v),
Poll::Pending => None,
}
}