#![deprecated = "A lot of unsafe code that is not necessary (use the `run!`-macro instead)"]
use crate::{err, error::Error};
use core::{
future::Future,
marker::{PhantomData, PhantomPinned},
mem,
pin::Pin,
ptr,
task::{Context, Poll},
};
#[repr(C, align(64))]
pub struct FutureBox<Output = (), const SIZE: usize = 64> {
storage: [u8; SIZE],
impl_poll: unsafe fn(self_: Pin<&mut Self>, context: &mut Context) -> Poll<Output>,
impl_drop: unsafe fn(self_: &mut Self),
_output: PhantomData<Output>,
_pinned: PhantomPinned,
}
impl<Output, const SIZE: usize> FutureBox<Output, SIZE> {
pub fn new<T>(future: T) -> Result<Self, Error>
where
T: Future<Output = Output> + 'static,
{
if mem::size_of::<T>() > SIZE {
return Err(err!("Future is too large"));
}
if mem::align_of::<T>() > mem::align_of::<Self>() {
return Err(err!("Future has an unsupported alignment"));
}
let mut storage = [0; SIZE];
let future_ptr = ptr::addr_of!(future) as *const u8;
unsafe { storage.as_mut_ptr().copy_from_nonoverlapping(future_ptr, mem::size_of_val(&future)) };
mem::forget(future);
Ok(Self {
storage,
impl_poll: Self::impl_poll::<T>,
impl_drop: Self::impl_drop::<T>,
_output: PhantomData,
_pinned: PhantomPinned,
})
}
unsafe fn impl_poll<T>(self: Pin<&mut Self>, context: &mut Context) -> Poll<Output>
where
T: Future<Output = Output>,
{
let this = unsafe { self.get_unchecked_mut() };
let future_ptr = this.storage.as_mut_ptr() as *mut T;
let future = unsafe { future_ptr.as_mut() }.expect("future pointer is NULL");
let future = Pin::new_unchecked(future);
future.poll(context)
}
unsafe fn impl_drop<T>(&mut self)
where
T: Future<Output = Output>,
{
let future_ptr = self.storage.as_mut_ptr() as *mut T;
ptr::drop_in_place(future_ptr);
}
}
impl<Output, const SIZE: usize> Drop for FutureBox<Output, SIZE> {
fn drop(&mut self) {
unsafe { (self.impl_drop)(self) }
}
}
impl<Output, const SIZE: usize> Future for FutureBox<Output, SIZE> {
type Output = Output;
fn poll(self: Pin<&mut Self>, context: &mut Context) -> Poll<Self::Output> {
unsafe { (self.impl_poll)(self, context) }
}
}