#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
use core::{future::Future, marker::PhantomData, pin::Pin};
pub trait ScopedFuture<'upper_bound, 'subject, Bound = ImpliedLifetimeBound<'upper_bound, 'subject>>: Future
where
Bound: sealed::Sealed,
{
}
pub type ImpliedLifetimeBound<'upper_bound, 'subject> = PhantomData<&'subject &'upper_bound ()>;
impl<'upper_bound: 'subject, 'subject, Fut: Future + 'subject> ScopedFuture<'upper_bound, 'subject> for Fut {}
mod sealed {
pub trait Sealed {}
impl<'upper_bound, 'a> Sealed for super::ImpliedLifetimeBound<'upper_bound, 'a> {}
}
#[cfg(feature = "alloc")]
pub type ScopedBoxFuture<'upper_bound, 'subject, T> = Pin<Box<dyn ScopedFuture<'upper_bound, 'subject, Output = T> + Send + 'subject>>;
#[cfg(feature = "alloc")]
pub type ScopedLocalBoxFuture<'upper_bound, 'subject, T> = Pin<Box<dyn ScopedFuture<'upper_bound, 'subject, Output = T> + 'subject>>;
pin_project_lite::pin_project! {
#[derive(Clone, Debug)]
pub struct ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
#[pin]
future: Fut,
scope: ImpliedLifetimeBound<'upper_bound, 'subject>,
}
}
pub trait ScopedFutureExt: Sized {
fn scoped<'upper_bound, 'subject>(self) -> ScopedFutureWrapper<'upper_bound, 'subject, Self>;
#[cfg(feature = "alloc")]
fn scope_boxed<'upper_bound, 'subject>(self) -> ScopedBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
where
Self: Send + Future + 'subject;
#[cfg(feature = "alloc")]
fn scope_boxed_local<'upper_bound, 'subject>(self) -> ScopedLocalBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
where
Self: Future + 'subject;
}
impl<'upper_bound, 'subject, Fut: Future> Future for ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
type Output = Fut::Output;
fn poll(self: Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> {
self.project().future.poll(cx)
}
}
impl<Fut: Future> ScopedFutureExt for Fut {
fn scoped<'upper_bound, 'subject>(self) -> ScopedFutureWrapper<'upper_bound, 'subject, Self> {
ScopedFutureWrapper { future: self, scope: PhantomData }
}
#[cfg(feature = "alloc")]
fn scope_boxed<'upper_bound, 'subject>(self) -> ScopedBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
where
Self: Send + Future + 'subject,
{
Box::pin(self)
}
#[cfg(feature = "alloc")]
fn scope_boxed_local<'upper_bound, 'subject>(self) -> ScopedLocalBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
where
Self: Future + 'subject,
{
Box::pin(self)
}
}
#[cfg(feature = "alloc")]
const _: () = {
impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + Send + 'subject> From<Pin<Box<Fut>>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Pin<Box<Fut>>) -> Self {
future
}
}
impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + 'subject> From<Pin<Box<Fut>>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Pin<Box<Fut>>) -> Self {
future
}
}
impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + Send + 'subject> From<Box<Fut>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Box<Fut>) -> Self {
Box::into_pin(future)
}
}
impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + 'subject> From<Box<Fut>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Box<Fut>) -> Self {
Box::into_pin(future)
}
}
impl<'upper_bound, 'subject, T: 'subject> From<Pin<Box<dyn Future<Output = T> + Send + 'subject>>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Pin<Box<dyn Future<Output = T> + Send + 'subject>>) -> Self {
Box::pin(future)
}
}
impl<'upper_bound, 'subject, T: 'subject> From<Pin<Box<dyn Future<Output = T> + 'subject>>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Pin<Box<dyn Future<Output = T> + 'subject>>) -> Self {
Box::pin(future)
}
}
impl<'upper_bound, 'subject, T: 'subject> From<Box<dyn Future<Output = T> + Send + 'subject>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Box<dyn Future<Output = T> + Send + 'subject>) -> Self {
Box::into_pin(future).into()
}
}
impl<'upper_bound, 'subject, T: 'subject> From<Box<dyn Future<Output = T> + 'subject>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
fn from(future: Box<dyn Future<Output = T> + 'subject>) -> Self {
Box::into_pin(future).into()
}
}
impl<'upper_bound, 'subject, T: 'subject> From<ScopedBoxFuture<'upper_bound, 'subject, T>> for Pin<Box<dyn Future<Output = T> + Send + 'subject>> {
fn from(future: ScopedBoxFuture<'upper_bound, 'subject, T>) -> Self {
Box::pin(future)
}
}
impl<'upper_bound, 'subject, T: 'subject> From<ScopedLocalBoxFuture<'upper_bound, 'subject, T>> for Pin<Box<dyn Future<Output = T> + 'subject>> {
fn from(future: ScopedLocalBoxFuture<'upper_bound, 'subject, T>) -> Self {
Box::pin(future)
}
}
};