vuot 0.0.1

Run recursive async functions without overflowing the stack
Documentation
//! Most of the examples are just doing CPU-y operations, so just spinning is
//! more efficient.

use std::future::Future;
use std::pin::pin;
use std::ptr::null;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};

/// Spins, polling the provided future until it returns a result.  This is
/// preferable to something like `pollster` only if you know that your futures
/// are CPU-bound and will never wait on anything.
pub fn block_on<T>(future: impl Future<Output = T>) -> T {
    let mut future = pin!(future);
    let waker = noop();
    let mut context = Context::from_waker(&waker);

    loop {
        match future.as_mut().poll(&mut context) {
            Poll::Pending => continue,
            Poll::Ready(result) => break result,
        }
    }
}

/// Create a waker that does absolutely nothing.
fn noop() -> Waker {
    const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
    const RAW: RawWaker = RawWaker::new(null(), &VTABLE);

    unsafe fn clone(_: *const ()) -> RawWaker {
        RAW
    }

    unsafe fn wake(_: *const ()) {}
    unsafe fn wake_by_ref(_: *const ()) {}
    unsafe fn drop(_: *const ()) {}

    // Safety: none of the functions do anything, and `clone` returns the
    // correct raw waker.
    unsafe { Waker::from_raw(RAW) }
}