|
187 | 187 | #![doc(html_root_url = "https://docs.rs/nb/1.0.0")]
|
188 | 188 |
|
189 | 189 | use core::fmt;
|
| 190 | +use core::future::Future; |
| 191 | +use core::pin::Pin; |
| 192 | +use core::task::{Context, Poll}; |
| 193 | +use pin_project_lite::pin_project; |
190 | 194 |
|
191 | 195 | /// A non-blocking result
|
192 | 196 | pub type Result<T, E> = ::core::result::Result<T, Error<E>>;
|
@@ -265,3 +269,47 @@ macro_rules! block {
|
265 | 269 | }
|
266 | 270 | };
|
267 | 271 | }
|
| 272 | +pin_project! { |
| 273 | + pub struct NbFuture<Ok, Err, Gen: FnMut() -> Result<Ok, Err>> { |
| 274 | + gen: Gen, |
| 275 | + } |
| 276 | +} |
| 277 | + |
| 278 | +impl<Ok, Err, Gen: FnMut() -> Result<Ok, Err>> From<Gen> for NbFuture<Ok, Err, Gen> { |
| 279 | + fn from(gen: Gen) -> Self { |
| 280 | + Self { gen } |
| 281 | + } |
| 282 | +} |
| 283 | + |
| 284 | +impl<Ok, Err, Gen: FnMut() -> Result<Ok, Err>> Future for NbFuture<Ok, Err, Gen> { |
| 285 | + type Output = core::result::Result<Ok, Err>; |
| 286 | + |
| 287 | + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 288 | + let this = self.project(); |
| 289 | + let res = (this.gen)(); |
| 290 | + |
| 291 | + match res { |
| 292 | + Ok(res) => Poll::Ready(Ok(res)), |
| 293 | + Err(Error::WouldBlock) => Poll::Pending, |
| 294 | + Err(Error::Other(err)) => Poll::Ready(Err(err)), |
| 295 | + } |
| 296 | + } |
| 297 | +} |
| 298 | + |
| 299 | +/// The equivalent of [block], expect instead of blocking this creates a |
| 300 | +/// [Future] which can `.await`ed. |
| 301 | +/// |
| 302 | +/// # Input |
| 303 | +/// |
| 304 | +/// An expression `$e` that evaluates to `nb::Result<T, E>` |
| 305 | +/// |
| 306 | +/// # Output |
| 307 | +/// |
| 308 | +/// - `Ok(t)` if `$e` evaluates to `Ok(t)` |
| 309 | +/// - `Err(e)` if `$e` evaluates to `Err(nb::Error::Other(e))` |
| 310 | +#[macro_export] |
| 311 | +macro_rules! fut { |
| 312 | + ($call:expr) => {{ |
| 313 | + nb::NbFuture::from(|| $call) |
| 314 | + }}; |
| 315 | +} |
0 commit comments