1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
use core::{
    pin::pin,
    ptr,
    task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};

use super::BlockOn;

/// [`BlockOn`] implementer that just spins on the future.
///
/// This is useful for futures that are alwayd ready.
pub enum Spin {}

impl BlockOn for Spin {
    #[inline(always)]
    fn block_on<F>(future: F) -> F::Output
    where
        F: core::future::Future + Send,
    {
        let waker = noop();
        let mut context = Context::from_waker(&waker);

        let mut future = pin!(future);
        loop {
            if let Poll::Ready(value) = future.as_mut().poll(&mut context) {
                return value;
            }
        }
    }
}

#[inline]
pub fn noop() -> Waker {
    const VTABLE: &RawWakerVTable = &RawWakerVTable::new(
        // Cloning just returns a new no-op raw waker
        |_| RAW,
        // `wake` does nothing
        |_| {},
        // `wake_by_ref` does nothing
        |_| {},
        // Dropping does nothing as we don't allocate anything
        |_| {},
    );
    const RAW: RawWaker = RawWaker::new(ptr::null(), VTABLE);
    unsafe { Waker::from_raw(RAW) }
}