1#![no_std]
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6#[cfg(feature = "alloc")]
7use alloc::boxed::Box;
8use core::{future::Future, marker::PhantomData, pin::Pin};
9
10pub trait ScopedFuture<'upper_bound, 'subject, Bound = ImpliedLifetimeBound<'upper_bound, 'subject>>: Future
75where
76 Bound: sealed::Sealed,
77{
78}
79
80pub type ImpliedLifetimeBound<'upper_bound, 'subject> = PhantomData<&'subject &'upper_bound ()>;
82
83impl<'upper_bound: 'subject, 'subject, Fut: Future + 'subject> ScopedFuture<'upper_bound, 'subject> for Fut {}
84
85mod sealed {
86 pub trait Sealed {}
87 impl<'upper_bound, 'a> Sealed for super::ImpliedLifetimeBound<'upper_bound, 'a> {}
88}
89
90#[cfg(feature = "alloc")]
92pub type ScopedBoxFuture<'upper_bound, 'subject, T> = Pin<Box<dyn ScopedFuture<'upper_bound, 'subject, Output = T> + Send + 'subject>>;
93
94#[cfg(feature = "alloc")]
96pub type ScopedLocalBoxFuture<'upper_bound, 'subject, T> = Pin<Box<dyn ScopedFuture<'upper_bound, 'subject, Output = T> + 'subject>>;
97
98pin_project_lite::pin_project! {
99 #[derive(Clone, Debug)]
101 pub struct ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
102 #[pin]
103 future: Fut,
104 scope: ImpliedLifetimeBound<'upper_bound, 'subject>,
105 }
106}
107
108pub trait ScopedFutureExt: Sized {
110 fn scoped<'upper_bound, 'subject>(self) -> ScopedFutureWrapper<'upper_bound, 'subject, Self>;
112
113 #[cfg(feature = "alloc")]
115 fn scope_boxed<'upper_bound, 'subject>(self) -> ScopedBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
116 where
117 Self: Send + Future + 'subject;
118
119 #[cfg(feature = "alloc")]
121 fn scope_boxed_local<'upper_bound, 'subject>(self) -> ScopedLocalBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
122 where
123 Self: Future + 'subject;
124}
125
126impl<'upper_bound, 'subject, Fut: Future> Future for ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
127 type Output = Fut::Output;
128 fn poll(self: Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> {
129 self.project().future.poll(cx)
130 }
131}
132
133impl<Fut: Future> ScopedFutureExt for Fut {
134 fn scoped<'upper_bound, 'subject>(self) -> ScopedFutureWrapper<'upper_bound, 'subject, Self> {
135 ScopedFutureWrapper { future: self, scope: PhantomData }
136 }
137
138 #[cfg(feature = "alloc")]
139 fn scope_boxed<'upper_bound, 'subject>(self) -> ScopedBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
140 where
141 Self: Send + Future + 'subject,
142 {
143 Box::pin(self)
144 }
145
146 #[cfg(feature = "alloc")]
147 fn scope_boxed_local<'upper_bound, 'subject>(self) -> ScopedLocalBoxFuture<'upper_bound, 'subject, <Self as Future>::Output>
148 where
149 Self: Future + 'subject,
150 {
151 Box::pin(self)
152 }
153}
154
155#[cfg(feature = "alloc")]
156const _: () = {
157 impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + Send + 'subject> From<Pin<Box<Fut>>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
158 fn from(future: Pin<Box<Fut>>) -> Self {
159 future
160 }
161 }
162
163 impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + 'subject> From<Pin<Box<Fut>>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
164 fn from(future: Pin<Box<Fut>>) -> Self {
165 future
166 }
167 }
168
169 impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + Send + 'subject> From<Box<Fut>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
170 fn from(future: Box<Fut>) -> Self {
171 Box::into_pin(future)
172 }
173 }
174
175 impl<'upper_bound, 'subject, T, Fut: Future<Output = T> + 'subject> From<Box<Fut>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
176 fn from(future: Box<Fut>) -> Self {
177 Box::into_pin(future)
178 }
179 }
180
181 impl<'upper_bound, 'subject, T: 'subject> From<Pin<Box<dyn Future<Output = T> + Send + 'subject>>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
182 fn from(future: Pin<Box<dyn Future<Output = T> + Send + 'subject>>) -> Self {
183 Box::pin(future)
184 }
185 }
186
187 impl<'upper_bound, 'subject, T: 'subject> From<Pin<Box<dyn Future<Output = T> + 'subject>>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
188 fn from(future: Pin<Box<dyn Future<Output = T> + 'subject>>) -> Self {
189 Box::pin(future)
190 }
191 }
192
193 impl<'upper_bound, 'subject, T: 'subject> From<Box<dyn Future<Output = T> + Send + 'subject>> for ScopedBoxFuture<'upper_bound, 'subject, T> {
194 fn from(future: Box<dyn Future<Output = T> + Send + 'subject>) -> Self {
195 Box::into_pin(future).into()
196 }
197 }
198
199 impl<'upper_bound, 'subject, T: 'subject> From<Box<dyn Future<Output = T> + 'subject>> for ScopedLocalBoxFuture<'upper_bound, 'subject, T> {
200 fn from(future: Box<dyn Future<Output = T> + 'subject>) -> Self {
201 Box::into_pin(future).into()
202 }
203 }
204
205 impl<'upper_bound, 'subject, T: 'subject> From<ScopedBoxFuture<'upper_bound, 'subject, T>> for Pin<Box<dyn Future<Output = T> + Send + 'subject>> {
206 fn from(future: ScopedBoxFuture<'upper_bound, 'subject, T>) -> Self {
207 Box::pin(future)
208 }
209 }
210
211 impl<'upper_bound, 'subject, T: 'subject> From<ScopedLocalBoxFuture<'upper_bound, 'subject, T>> for Pin<Box<dyn Future<Output = T> + 'subject>> {
212 fn from(future: ScopedLocalBoxFuture<'upper_bound, 'subject, T>) -> Self {
213 Box::pin(future)
214 }
215 }
216};