|
| 1 | +use std::pin::Pin; |
| 2 | +use std::{ptr, slice, thread}; |
| 3 | +use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; |
| 4 | +use std::time::Duration; |
| 5 | +use crate::async_runtime::future_id::FutureId; |
| 6 | +use crate::error::{Result, RustedComputerError}; |
| 7 | + |
| 8 | +pub mod future_id; |
| 9 | + |
| 10 | +pub struct RustedComputerFuture<T, F> |
| 11 | +where |
| 12 | + F: Fn(String) -> T, |
| 13 | +{ |
| 14 | + pub id: FutureId, |
| 15 | + pub converter: F, |
| 16 | +} |
| 17 | + |
| 18 | +impl<T, F> RustedComputerFuture<T, F> |
| 19 | +where |
| 20 | + F: Fn(String) -> T, |
| 21 | +{ |
| 22 | + pub fn new<G>(caller: G, converter: F) -> Self |
| 23 | + where |
| 24 | + G: Fn() -> FutureId, |
| 25 | + { |
| 26 | + let id = caller(); |
| 27 | + Self { id, converter } |
| 28 | + } |
| 29 | +} |
| 30 | + |
| 31 | +impl<T, F> Future for RustedComputerFuture<T, F> |
| 32 | +where |
| 33 | + F: Fn(String) -> T, |
| 34 | +{ |
| 35 | + type Output = Result<T>; |
| 36 | + |
| 37 | + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 38 | + let poll_result = unsafe { poll(*self.id) }; |
| 39 | + |
| 40 | + let length = (poll_result & 0xFFFFFFFF) as usize; |
| 41 | + let pointer = (poll_result >> 32) as *mut u8; |
| 42 | + |
| 43 | + let slice = unsafe { slice::from_raw_parts_mut(pointer, length) }; |
| 44 | + let boxed_slice = unsafe { Box::from_raw(slice) }; |
| 45 | + let future = str::from_utf8(&boxed_slice).unwrap(); |
| 46 | + |
| 47 | + if future == "P" { |
| 48 | + Poll::Pending |
| 49 | + } else if future == "F" { |
| 50 | + Poll::Ready(Err(RustedComputerError::FutureFailed)) |
| 51 | + } else if future.starts_with("S") { |
| 52 | + let future_result = future[1..].to_owned(); |
| 53 | + let converted_result = (self.converter)(future_result); |
| 54 | + |
| 55 | + Poll::Ready(Ok(converted_result)) |
| 56 | + } else { |
| 57 | + unreachable!() |
| 58 | + } |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +fn noop_raw_waker() -> RawWaker { |
| 63 | + fn clone(_: *const ()) -> RawWaker { |
| 64 | + noop_raw_waker() |
| 65 | + } |
| 66 | + fn no_op(_: *const ()) {} |
| 67 | + |
| 68 | + static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, no_op, no_op, no_op); |
| 69 | + RawWaker::new(ptr::null(), &VTABLE) |
| 70 | +} |
| 71 | + |
| 72 | +fn noop_waker() -> Waker { |
| 73 | + unsafe { Waker::from_raw(noop_raw_waker()) } |
| 74 | +} |
| 75 | + |
| 76 | +pub fn block_on<F: Future>(mut future: F) -> F::Output { |
| 77 | + let mut future = unsafe { Pin::new_unchecked(&mut future) }; |
| 78 | + let waker = noop_waker(); |
| 79 | + let mut cx = Context::from_waker(&waker); |
| 80 | + |
| 81 | + loop { |
| 82 | + match future.as_mut().poll(&mut cx) { |
| 83 | + Poll::Ready(val) => return val, |
| 84 | + Poll::Pending => { |
| 85 | + thread::sleep(Duration::from_millis(100)); |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +#[link(wasm_import_module = "future")] |
| 92 | +unsafe extern "C" { |
| 93 | + #[link_name = "poll"] |
| 94 | + pub fn poll(future_id: i32) -> i64; |
| 95 | +} |
0 commit comments