#![allow(
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::missing_const_for_fn,
clippy::missing_safety_doc,
clippy::doc_markdown,
clippy::type_complexity,
clippy::undocumented_unsafe_blocks,
clippy::no_effect_underscore_binding,
clippy::needless_pass_by_value,
clippy::unused_self,
clippy::needless_pass_by_ref_mut,
clippy::module_name_repetitions,
clippy::unnecessary_wraps
)]
use crate::abi::Overlapped;
use crate::abi::imports;
use crate::boxed::Box;
use crate::cell::{OnceCell, RefCell, UnsafeCell};
use crate::future::Future;
use crate::pin::Pin;
use crate::rc::Rc;
use crate::task::{Context, Poll, Waker};
use crate::vec::Vec;
#[unsafe(no_mangle)]
extern "Rust" fn __getrandom_v03_custom(dest: *mut u8, len: usize) -> Result<(), getrandom::Error> {
unsafe {
imports::get_random(dest, len as u32);
}
Ok(())
}
struct OpState {
overlapped: UnsafeCell<Overlapped>,
buffer: UnsafeCell<Option<Vec<u8>>>,
}
impl OpState {
fn new() -> Rc<Self> {
Rc::new(Self {
overlapped: UnsafeCell::new(Overlapped::default()),
buffer: UnsafeCell::new(None),
})
}
fn with_buffer(buf: Vec<u8>) -> Rc<Self> {
Rc::new(Self {
overlapped: UnsafeCell::new(Overlapped::default()),
buffer: UnsafeCell::new(Some(buf)),
})
}
fn overlapped_ptr(&self) -> *mut Overlapped {
self.overlapped.get()
}
fn is_complete(&self) -> bool {
unsafe { (*self.overlapped.get()).is_complete() }
}
fn snapshot(&self) -> (u32, u64, u64) {
let ov = unsafe { &*self.overlapped.get() };
(ov.error, ov.result_ext, ov.continued)
}
fn take_buffer(&self) -> Option<Vec<u8>> {
unsafe { (*self.buffer.get()).take() }
}
fn buffer_ptr_len(&self) -> Option<(*mut u8, u32)> {
unsafe {
let opt: &mut Option<Vec<u8>> = &mut *self.buffer.get();
opt.as_mut().map(|v| (v.as_mut_ptr(), v.capacity() as u32))
}
}
}
thread_local! {
static COMPLETION_REGISTRY: RefCell<Vec<(Rc<OpState>, Waker)>> =
const { RefCell::new(Vec::new()) };
static MAIN_FUTURE: RefCell<Option<Pin<Box<dyn Future<Output = ()>>>>> =
const { RefCell::new(None) };
static INITIALIZED: OnceCell<()> = const { OnceCell::new() };
}
fn register(state: Rc<OpState>, waker: Waker) {
COMPLETION_REGISTRY.with(|registry| {
registry.borrow_mut().push((state, waker));
});
}
pub fn submit_main<F>(future: F)
where
F: Future<Output = ()> + 'static,
{
MAIN_FUTURE.with(|main| {
*main.borrow_mut() = Some(Box::pin(future));
});
}
fn tick() {
COMPLETION_REGISTRY.with(|registry| {
let mut reg = registry.borrow_mut();
let mut i = 0;
while i < reg.len() {
if reg[i].0.is_complete() {
let (_state, waker) = reg.remove(i);
waker.wake();
} else {
i += 1;
}
}
});
MAIN_FUTURE.with(|main_fut| {
if let Some(fut) = main_fut.borrow_mut().as_mut() {
let waker = noop_waker();
let mut cx = Context::from_waker(&waker);
let _ = fut.as_mut().poll(&mut cx);
}
});
}
fn noop_waker() -> Waker {
use core::task::{RawWaker, RawWakerVTable};
unsafe fn clone(_: *const ()) -> RawWaker {
raw()
}
unsafe fn wake(_: *const ()) {}
unsafe fn wake_by_ref(_: *const ()) {}
unsafe fn drop_(_: *const ()) {}
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop_);
fn raw() -> RawWaker {
RawWaker::new(core::ptr::null(), &VTABLE)
}
unsafe { Waker::from_raw(raw()) }
}
pub struct OverlappedFuture {
state: Rc<OpState>,
op: Option<Box<dyn FnOnce(*mut Overlapped)>>,
started: bool,
}
impl OverlappedFuture {
pub fn new<F>(op: F) -> Self
where
F: FnOnce(*mut Overlapped) + 'static,
{
Self {
state: OpState::new(),
op: Some(Box::new(op)),
started: false,
}
}
}
impl Future for OverlappedFuture {
type Output = (u32, u64, u64);
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if !self.started {
self.started = true;
if let Some(op) = self.op.take() {
op(self.state.overlapped_ptr());
}
if self.state.is_complete() {
return Poll::Ready(self.state.snapshot());
}
register(Rc::clone(&self.state), cx.waker().clone());
return Poll::Pending;
}
if self.state.is_complete() {
Poll::Ready(self.state.snapshot())
} else {
Poll::Pending
}
}
}
pub struct OverlappedBufferFuture {
state: Rc<OpState>,
op: Option<Box<dyn FnOnce(*mut Overlapped, *mut u8, u32)>>,
started: bool,
}
impl OverlappedBufferFuture {
pub fn new<F>(buffer: Vec<u8>, op: F) -> Self
where
F: FnOnce(*mut Overlapped, *mut u8, u32) + 'static,
{
Self {
state: OpState::with_buffer(buffer),
op: Some(Box::new(op)),
started: false,
}
}
}
impl Future for OverlappedBufferFuture {
type Output = (u32, u64, u64, Vec<u8>);
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if !self.started {
self.started = true;
if let Some(op) = self.op.take() {
if let Some((ptr, len)) = self.state.buffer_ptr_len() {
op(self.state.overlapped_ptr(), ptr, len);
}
}
if self.state.is_complete() {
let (e, r, c) = self.state.snapshot();
let buf = self.state.take_buffer().unwrap_or_default();
return Poll::Ready((e, r, c, buf));
}
register(Rc::clone(&self.state), cx.waker().clone());
return Poll::Pending;
}
if self.state.is_complete() {
let (e, r, c) = self.state.snapshot();
let buf = self.state.take_buffer().unwrap_or_default();
Poll::Ready((e, r, c, buf))
} else {
Poll::Pending
}
}
}
unsafe extern "Rust" {
fn guest_init();
}
#[unsafe(no_mangle)]
pub extern "C" fn run() {
INITIALIZED.with(|init| {
if init.get().is_none() {
unsafe { guest_init() };
let _ = init.set(());
}
});
tick();
}
pub fn poll_step() {
tick();
}