#![cfg_attr(not(feature = "std"), no_std)]
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 = "std")]
pub type ScopedBoxFuture<'upper_bound, 'subject, T> = Pin<Box<dyn ScopedFuture<'upper_bound, 'subject, Output = T> + Send + 'subject>>;
#[cfg(feature = "std")]
pub type ScopedLocalBoxFuture<'upper_bound, 'subject, T> = Pin<Box<dyn ScopedFuture<'upper_bound, 'subject, Output = T> + 'subject>>;
#[derive(Clone, Debug)]
pub struct ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
future: Fut,
scope: ImpliedLifetimeBound<'upper_bound, 'subject>,
}
pub trait ScopedFutureExt: Sized {
fn scoped<'upper_bound, 'subject>(self) -> ScopedFutureWrapper<'upper_bound, 'subject, Self>;
#[cfg(feature = "std")]
fn scope_boxed<'upper_bound, 'subject>(self) -> ScopedBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
where
Self: Send + Future + 'subject;
#[cfg(feature = "std")]
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> ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
pin_utils::unsafe_pinned!(future: Fut);
}
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.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 = "std")]
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 = "std")]
fn scope_boxed_local<'upper_bound, 'subject>(self) -> ScopedLocalBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
where
Self: Future + 'subject,
{
Box::pin(self)
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
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)
}
}
}
}