extern crate alloc;
use crate::BoxFuture;
use alloc::boxed::Box;
use core::future::Future;
use core::ops::Deref;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::time::Duration;
pub enum Never {}
impl Never { pub fn into(self) -> ! { loop {} } }
pub struct Stop;
impl Future for Stop {
type Output = Never;
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Pending }
}
pub struct SpawnedFuture<'a>(u64, &'a mut dyn InternalRuntime);
impl<'a> Future for SpawnedFuture<'a> {
type Output = ();
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = self.get_mut();
if me.1.contains(me.0) {
Poll::Pending
} else {
Poll::Ready(())
}
}
}
pub trait InternalRuntime {
fn push_boxed(&mut self, future: BoxFuture<'static, ()>) -> u64;
fn contains(&mut self, id: u64) -> bool;
fn sleep<'a>(&self, duration: Duration) -> BoxFuture<'a, ()>;
fn stop(&mut self) -> Stop;
}
pub trait Runtime<'a> {
fn push(&mut self, future: impl Future<Output = ()> + 'static) {
Runtime::push_boxed(self, Box::pin(future))
}
fn push_boxed(&mut self, future: BoxFuture<'static, ()>);
fn spawn(&'a mut self, future: impl Future<Output = ()> + 'static) -> SpawnedFuture<'a> {
Runtime::spawn_boxed(self, Box::pin(future))
}
fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a>;
fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()>;
fn sleep_ms<'b>(&'a self, amount: u64) -> BoxFuture<'b, ()> {
self.sleep(Duration::from_millis(amount))
}
fn stop(&mut self) -> Stop;
}
pub struct RuntimeWrapper<'a>(pub(crate) &'a mut dyn InternalRuntime);
pub struct OwnedRuntime<'a>(RuntimeWrapper<'a>, pub(crate) Box<dyn InternalRuntime + 'a>);
impl<'a> Deref for OwnedRuntime<'a> {
type Target = RuntimeWrapper<'a>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a> Runtime<'a> for RuntimeWrapper<'a> {
fn push_boxed(&mut self, future: BoxFuture<'static, ()>) {
InternalRuntime::push_boxed(self.0, future);
}
fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a> {
SpawnedFuture(InternalRuntime::push_boxed(self.0, future), self.0)
}
fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()> {
InternalRuntime::sleep(self.0, duration)
}
fn stop(&mut self) -> Stop {
InternalRuntime::stop(self.0)
}
}
impl<'a, T: InternalRuntime + Sized> Runtime<'a> for T {
fn push_boxed(&mut self, future: BoxFuture<'static, ()>) {
InternalRuntime::push_boxed(self, future);
}
fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a> {
SpawnedFuture(InternalRuntime::push_boxed(self, future), self)
}
fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()> {
InternalRuntime::sleep(self, duration)
}
fn stop(&mut self) -> Stop {
InternalRuntime::stop(self)
}
}
pub trait StartableRuntime<'a>: InternalRuntime + Sized + 'a {
fn new() -> OwnedRuntime<'a> {
let mut bx = Box::new(Self::construct());
OwnedRuntime(
RuntimeWrapper(unsafe { (bx.as_mut() as *mut dyn InternalRuntime).as_mut().unwrap() }),
bx,
)
}
fn construct() -> Self;
}
impl<'a, T: InternalRuntime + Sized + 'a> StartableRuntime<'a> for T
where
T: Default,
{
fn construct() -> Self {
Self::default()
}
}