use crate::{
FromValue, OwnedMut, OwnedRef, RawOwnedMut, RawOwnedRef, Shared, ToValue, UnsafeFromValue,
Value, VmError,
};
use pin_project::pin_project;
use std::fmt;
use std::future;
use std::pin::Pin;
use std::task::{Context, Poll};
value_types!(crate::FUTURE_TYPE, Future => Future, &Future, &mut Future);
type DynFuture = dyn future::Future<Output = Result<Value, VmError>> + 'static;
pub struct Future {
future: Option<Pin<Box<DynFuture>>>,
}
impl Future {
pub fn new<T, O>(future: T) -> Self
where
T: 'static + future::Future<Output = Result<O, VmError>>,
O: ToValue,
{
Self {
future: Some(Box::pin(async move {
let value = future.await?;
Ok(value.to_value()?)
})),
}
}
pub fn is_completed(&self) -> bool {
self.future.is_none()
}
}
impl future::Future for Future {
type Output = Result<Value, VmError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<Value, VmError>> {
let this = self.get_mut();
let mut future = this.future.take().expect("futures can only be polled once");
match future.as_mut().poll(cx) {
Poll::Ready(result) => Poll::Ready(result),
Poll::Pending => {
this.future = Some(future);
Poll::Pending
}
}
}
}
impl fmt::Debug for Future {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Future")
.field("is_completed", &self.future.is_none())
.finish()
}
}
#[pin_project]
pub struct SelectFuture<T, F> {
data: T,
#[pin]
future: F,
}
impl<T, F> SelectFuture<T, F> {
pub fn new(data: T, future: F) -> Self {
Self { data, future }
}
}
impl<T, F> future::Future for SelectFuture<T, F>
where
T: Copy,
F: future::Future<Output = Result<Value, VmError>>,
{
type Output = Result<(T, Value), VmError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let result = this.future.poll(cx);
match result {
Poll::Ready(result) => match result {
Ok(value) => Poll::Ready(Ok((*this.data, value))),
Err(e) => Poll::Ready(Err(e)),
},
Poll::Pending => Poll::Pending,
}
}
}
impl FromValue for Shared<Future> {
fn from_value(value: Value) -> Result<Self, VmError> {
Ok(value.into_future()?)
}
}
impl FromValue for Future {
fn from_value(value: Value) -> Result<Self, VmError> {
let future = value.into_future()?;
Ok(future.take()?)
}
}
impl UnsafeFromValue for &Future {
type Output = *const Future;
type Guard = RawOwnedRef;
unsafe fn unsafe_from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
let future = value.into_future()?;
let (future, guard) = OwnedRef::into_raw(future.owned_ref()?);
Ok((future, guard))
}
unsafe fn to_arg(output: Self::Output) -> Self {
&*output
}
}
impl UnsafeFromValue for &mut Future {
type Output = *mut Future;
type Guard = RawOwnedMut;
unsafe fn unsafe_from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
let future = value.into_future()?;
Ok(OwnedMut::into_raw(future.owned_mut()?))
}
unsafe fn to_arg(output: Self::Output) -> Self {
&mut *output
}
}