hakuban 0.8.5

Data-object sharing library
Documentation
#![allow(clippy::not_unsafe_ptr_arg_deref)]

use std::{
	future::Future,
	pin::Pin,
	sync::{Arc, Mutex},
	task::Context,
};

use futures::task::ArcWake;
use wasm_bindgen::prelude::wasm_bindgen;

use super::{wasm_result::WasmResult, WasmExchange};

pub struct WasmWaker {
	wakers_triggered: Arc<Mutex<Vec<u64>>>,
	waker_id: u64,
}

impl ArcWake for WasmWaker {
	fn wake_by_ref(arc_self: &Arc<Self>) {
		//log::trace!("wake {}", arc_self.waker_id);
		arc_self.wakers_triggered.lock().unwrap().push(arc_self.waker_id);
	}
}

pub struct WasmFuture {
	future: Pin<Box<dyn Future<Output = WasmResult>>>,
}

impl WasmFuture {
	pub(crate) fn new(future: impl Future<Output = WasmResult> + 'static) -> WasmFuture {
		WasmFuture { future: Box::pin(future) }
	}

	fn poll(exchange_pointer: *mut WasmExchange, future_pointer: *mut Self, waker_id: u64) -> WasmResult {
		let exchange = unsafe { exchange_pointer.as_mut().unwrap() };
		let future = unsafe { future_pointer.as_mut().unwrap() };
		let waker = futures::task::waker(Arc::new(WasmWaker { wakers_triggered: exchange.wakers_triggered.clone(), waker_id }));
		let mut cx = Context::from_waker(&waker);
		match future.future.as_mut().poll(&mut cx) {
			std::task::Poll::Ready(result) => result,
			std::task::Poll::Pending => WasmResult::pending(),
		}
	}
}

#[wasm_bindgen]
pub fn hakuban_future_poll(exchange_pointer: *mut WasmExchange, future_pointer: *mut WasmFuture, waker_id: u64) -> WasmResult {
	WasmFuture::poll(exchange_pointer, future_pointer, waker_id)
}

#[wasm_bindgen]
pub fn hakuban_future_drop(future: *mut WasmFuture) {
	drop(unsafe { Box::from_raw(future) });
}