use core::{
future::Future,
marker::PhantomData,
pin::{pin, Pin},
ptr,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
use futures::FutureExt;
use pin_project::pin_project;
use crate::{higher_ranked_trait, higher_ranked_type, hkt::Marker};
// higher_ranked_trait! {
// pub type class Effective['lt, E] for<'a> {
// type Bound = &'a (&'lt (), T, E);
//
// type T: { Adapters<'a, Effect = E, T = T> + Sized + 'a }
// where {
// 'lt: 'a,
// T: 'a,
// E: Effect,
// };
//
// type HigherRanked: {} where {
// E: Effect,
// };
// }
// }
// fn do_thing<E: Effect>() -> ObjSafe<'static, i32, E> {
// E::ready(42).with(|x| {
// other::<E>(x).map(|x| x + 1).into()
// }).into()
// }
//
// fn other<E: Effect>(x: &i32) -> ObjSafe<'_, &i32, E> {
// E::ready(x).into()
// }
// pub mod Effective {
//
// }
//
pub trait Adapters<'lt>: Into<<Self::Effect as Effect>::ObjSafe<'lt, Self::T>> + 'lt {
type Effect: Effect;
type T: 'lt;
type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T>: Adapters<'a, Effect = Self::Effect, T = T>
where
'lt: 'a;
fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F>
where
F: FnOnce(Self::T) -> R,
'lt: 'a;
}
/// Trait for effects.
pub trait Effect: Sized + Send + Sync + 'static {
type ObjSafe<'a, T: 'a>: Adapters<'a, Effect = Self, T = T>;
type Ready<'a, T: 'a>: Adapters<'a, Effect = Self, T = T>;
fn ready<'a, T: 'a>(x: T) -> Self::Ready<'a, T>;
type With<'a, T: 'a, R: 'a, F: 'a + FnOnce(&mut T) -> R>: Adapters<'a, Effect = Self, T = R>;
fn with<'a, T: 'a, R: 'a, F: 'a>(x: T, f: F) -> Self::With<'a, T, R::T, F>
where
R: Adapters<'a, Effect = Self>,
F: FnOnce(&mut T) -> R;
}
pub type ObjSafe<'a, T, E> = <E as Effect>::ObjSafe<'a, T>;
pub enum Blocking {}
impl Effect for Blocking {
type ObjSafe<'a, T: 'a> = Value<T>;
type Ready<'a, T: 'a> = Value<T>;
fn ready<'a, T: 'a>(x: T) -> Self::Ready<'a, T> {
Value(x)
}
type With<'a, T: 'a, R: 'a, F: 'a + FnOnce(&mut T) -> R> = Value<R>;
fn with<'a, T: 'a, R: 'a, F: 'a>(x: T, f: F) -> Self::With<'a, T, R::T, F>
where
R: Adapters<'a, Effect = Self>,
F: FnOnce(&mut T) -> R {
let mut ctx = x;
Value(f(&mut ctx))
}
}
pub struct Value<T>(pub T);
impl<'b, U: 'b> Adapters<'b> for Value<U> {
type Effect = Blocking;
type T = U;
type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = Value<T> where 'b: 'a;
fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F>
where
F: FnOnce(Self::T) -> R,
'b: 'a,
{
Value(f(self.0))
}
}
/*
pub enum Async {}
impl Effect for Async {
type ObjSafe<'a, T: 'a> = BoxedFuture<'a, T>;
type Ready<'a, T: 'a> = AsyncValue<T>;
fn ready<'a, T: 'a>(x: T) -> Self::Ready<'a, T> {
AsyncValue(x)
}
}
pub struct AsyncValue<T>(pub T);
pub struct BoxedFuture<'a, T: 'a>(pub Pin<Box<dyn Future<Output = T> + 'a>>);
impl<'b, U: 'b> Adapters<'b> for AsyncValue<U> {
type Effect = Async;
type T = U;
type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncValue<T> where 'b: 'a;
fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F>
where
F: FnOnce(Self::T) -> R,
'b: 'a,
{
AsyncValue(f(self.0))
}
}
impl<'b, U: 'b> Adapters<'b> for BoxedFuture<'b, U> {
type Effect = Async;
type T = U;
type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncMap<Self, F> where 'b: 'a;
fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F>
where
F: FnOnce(Self::T) -> R,
'b: 'a,
{
AsyncMap {
map: futures::FutureExt::map(self, f)
}
}
}
#[pin_project]
pub struct AsyncMap<Fut, F> {
#[pin]
map: futures::future::Map<Fut, F>,
}
impl<'b, U: 'b, Fut0: 'b, F0: 'b> Adapters<'b> for AsyncMap<Fut0, F0>
where
Fut0: Future,
F0: FnOnce(Fut0::Output) -> U,
{
type Effect = Async;
type T = U;
type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncMap<Self, F> where 'b: 'a;
fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F>
where
F: FnOnce(Self::T) -> R,
'b: 'a,
{
AsyncMap {
map: futures::FutureExt::map(self, f)
}
}
}
impl<T, Fut, F> Future for AsyncMap<Fut, F>
where
Fut: Future,
F: FnOnce(Fut::Output) -> T,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.map.poll(cx)
}
}
impl<'a, T> Future for BoxedFuture<'a, T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.0.poll_unpin(cx)
}
}
impl<'a, T, Fut: 'a, F: 'a> From<AsyncMap<Fut, F>> for BoxedFuture<'a, T>
where
Fut: Future,
F: FnOnce(Fut::Output) -> T,
{
fn from(value: AsyncMap<Fut, F>) -> Self {
BoxedFuture(Box::pin(value.map))
}
}
impl<'a, T: 'a> From<AsyncValue<T>> for BoxedFuture<'a, T> {
fn from(value: AsyncValue<T>) -> Self {
BoxedFuture(Box::pin(futures::future::ready(value.0)))
}
}
*/
/*
pub trait ReadyValue: core::future::Future {
fn value(self) -> Self::Output;
}
impl<T: Send> ReadyValue for core::future::Ready<T> {
fn value(self) -> Self::Output {
Spin::block_on(self)
}
}
pub trait BlockOn: 'static {
fn block_on<F>(future: F) -> F::Output
where
F: core::future::Future + Send,
<F as core::future::Future>::Output: Send;
}
/// [`BlockOn`] implementer that just spins on the future.
///
/// This is useful for futures that are alwayd ready.
pub enum Spin {}
impl BlockOn for Spin {
#[inline(always)]
fn block_on<F>(future: F) -> F::Output
where
F: core::future::Future + Send,
{
let waker = noop();
let mut context = Context::from_waker(&waker);
let mut future = pin!(future);
loop {
if let Poll::Ready(value) = future.as_mut().poll(&mut context) {
return value;
}
}
}
}
#[inline]
pub fn noop() -> Waker {
const VTABLE: &RawWakerVTable = &RawWakerVTable::new(
// Cloning just returns a new no-op raw waker
|_| RAW,
// `wake` does nothing
|_| {},
// `wake_by_ref` does nothing
|_| {},
// Dropping does nothing as we don't allocate anything
|_| {},
);
const RAW: RawWaker = RawWaker::new(ptr::null(), VTABLE);
unsafe { Waker::from_raw(RAW) }
}
// pub struct Ready<Output> {
// pub value: Option<Output>,
// }
//
// impl<Output> Ready<Output> {
// pub fn into_inner(self) -> Output {
// self.value.expect("`into_inner` called after completion")
// }
// }
//
// impl<Output> Unpin for Ready<Output> {}
//
// impl<Output> core::future::Future for Ready<Output> {
// type Output = Output;
//
// fn poll(mut self: core::pin::Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
// Poll::Ready(self.value.take().expect("`Ready` polled after completion"))
// }
// }
higher_ranked_type! {
impl SendFuture {
impl['a, Output] type T['a, Output] for core::future::Ready<Output> =
core::future::Ready<Output>
where {
Output: Send
};
impl['a, Output] type HigherRanked['a, Output] for core::future::Ready<Output> =
core::future::Ready<Output>
where {
Output: Send
};
}
}
impl<B: BlockOn> Effect for Blocking<B> {
type Future<T: Send> = core::future::Ready<T>;
#[inline(always)]
fn wrap<'a, F>(future: F) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>>
where
F: core::future::Future + Send + 'a,
<F as core::future::Future>::Output: Send,
{
core::future::ready(B::block_on(future))
}
#[inline(always)]
fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, T, Self::Future<T>> {
core::future::ready(value)
}
#[inline(always)]
fn map<'a, T, U, F>(
future: SendFuture::T<'a, T, Self::Future<T>>,
func: F,
) -> SendFuture::T<'a, U, Self::Future<U>>
where
T: Send,
U: Send,
F: FnOnce(T) -> U + Send + 'a,
{
let value = B::block_on(future);
core::future::ready(func(value))
}
}
mod sealed {
pub enum BoxedFuture<'lt, Output> {
Box(core::pin::Pin<Box<dyn core::future::Future<Output = Output> + Send + 'lt>>),
Ready(core::future::Ready<Output>),
}
impl<'lt, Output> core::future::Future for BoxedFuture<'lt, Output> {
type Output = Output;
fn poll(
mut self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
match &mut *self {
BoxedFuture::Box(future) => future.as_mut().poll(cx),
BoxedFuture::Ready(future) => core::pin::Pin::new(future).poll(cx),
}
}
}
}
#[cfg(feature = "alloc")]
pub struct BoxedFutureHrt<Output>(Marker<Output>);
#[cfg(feature = "alloc")]
higher_ranked_type! {
impl SendFuture {
impl['a, Output] type T['a, Output] for BoxedFutureHrt<Output> =
sealed::BoxedFuture<'a, Output>
where {
Output: Send
};
impl['a, Output] type HigherRanked['a, Output] for sealed::BoxedFuture<'a, Output> =
BoxedFutureHrt<Output>
where {
Output: Send
};
}
}
#[cfg(feature = "alloc")]
pub enum Async {}
#[cfg(feature = "alloc")]
impl Effect for Async {
type Future<T: Send> = BoxedFutureHrt<T>;
fn wrap<'a, F>(future: F) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>>
where
F: core::future::Future + Send + 'a,
<F as core::future::Future>::Output: Send,
{
sealed::BoxedFuture::Box(Box::pin(future))
}
fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, T, Self::Future<T>> {
sealed::BoxedFuture::Ready(core::future::ready(value))
}
fn map<'a, T, U, F>(
future: SendFuture::T<'a, T, Self::Future<T>>,
func: F,
) -> SendFuture::T<'a, U, Self::Future<U>>
where
T: Send,
U: Send,
F: FnOnce(T) -> U + Send + 'a,
{
match future {
sealed::BoxedFuture::Box(future) => Self::wrap(async { func(future.await) }),
sealed::BoxedFuture::Ready(future) => {
let value = Spin::block_on(future);
Self::ready(func(value))
}
}
}
fn wrap_boxed<'a, F>(
future: core::pin::Pin<Box<F>>,
) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>>
where
F: core::future::Future + Send + 'a,
<F as core::future::Future>::Output: Send,
{
sealed::BoxedFuture::Box(future)
}
}
*/