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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
extern crate alloc;

use crate::BoxFuture;
use alloc::boxed::Box;
use core::future::Future;
use core::ops::Deref;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::time::Duration;

pub struct SpawnedFuture<'a>(u64, &'a dyn InternalRuntime);

impl<'a> Future for SpawnedFuture<'a> {
    type Output = ();

    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
        if self.1.contains(self.0) {
            Poll::Pending
        } else {
            Poll::Ready(())
        }
    }
}

/// Trait to be implemented by async runtimes
pub trait InternalRuntime {
    /// Adds a new future to the queue to be completed.
    fn push_boxed(&mut self, future: BoxFuture<'static, ()>) -> u64;
    /// Returns if a future by some ID is still running.
    fn contains(&self, id: u64) -> bool;
    /// Asynchronously sleeps
    fn sleep<'a>(&self, duration: Duration) -> BoxFuture<'a, ()>;
    /// Stops the runtime
    fn stop(&mut self);
}
/// Auto-trait with the methods that will actually be called by the users of the runtime.
pub trait Runtime<'a> {
    /// Adds a new future to the queue to be completed.
    fn push(&'a mut self, future: impl Future<Output = ()> + 'static) {
        Runtime::push_boxed(self, Box::pin(future))
    }
    /// Adds a new future to the queue to be completed.
    fn push_boxed(&'a mut self, future: BoxFuture<'static, ()>);

    /// Adds a new future to the queue to be completed and returns a future waiting for the added
    /// future's completion.
    fn spawn(&'a mut self, future: impl Future<Output = ()> + 'static) -> SpawnedFuture<'a> {
        Runtime::spawn_boxed(self, Box::pin(future))
    }
    /// Adds a new future to the queue to be completed and returns a future waiting for the added
    /// future's completion.
    fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a>;

    /// Asynchronously sleeps
    fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()>;
    /// Asynchronously sleeps some amount of milliseconds
    fn sleep_ms<'b>(&'a self, amount: u64) -> BoxFuture<'b, ()> {
        self.sleep(Duration::from_millis(amount))
    }

    /// Stops the runtime. This does not exit the process.
    fn stop(&mut self);
}

/// Wrapper for anything that implements InternalRuntime, used to add a Runtime impl.
pub struct RuntimeWrapper<'a>(pub(crate) &'a mut dyn InternalRuntime);

/// Owned wrapper for anything that implements InternalRuntime, used to add a Runtime impl.
pub struct OwnedRuntime<'a>(RuntimeWrapper<'a>, pub(crate) Box<dyn InternalRuntime + 'a>);

impl<'a> Deref for OwnedRuntime<'a> {
    type Target = RuntimeWrapper<'a>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a> Runtime<'a> for RuntimeWrapper<'a> {
    fn push_boxed(&'a mut self, future: BoxFuture<'static, ()>) {
        InternalRuntime::push_boxed(self.0, future);
    }

    fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a> {
        SpawnedFuture(InternalRuntime::push_boxed(self.0, future), self.0)
    }

    fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()> {
        InternalRuntime::sleep(self.0, duration)
    }

    fn stop(&mut self) {
        InternalRuntime::stop(self.0)
    }
}

impl<'a, T: InternalRuntime + Sized> Runtime<'a> for T {
    fn push_boxed(&'a mut self, future: BoxFuture<'static, ()>) {
        InternalRuntime::push_boxed(self, future);
    }

    fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a> {
        SpawnedFuture(InternalRuntime::push_boxed(self, future), self)
    }

    fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()> {
        InternalRuntime::sleep(self, duration)
    }

    fn stop(&mut self) {
        InternalRuntime::stop(self)
    }
}

/// Trait to construct a runtime
pub trait StartableRuntime<'a>: InternalRuntime + Sized + 'a {
    /// Constructs some new runtime
    fn new() -> OwnedRuntime<'a> {
        let mut bx = Box::new(Self::construct());
        OwnedRuntime(
            RuntimeWrapper(unsafe { (bx.as_mut() as *mut dyn InternalRuntime).as_mut().unwrap() }),
            bx,
        )
    }

    /// Internal function to make a new runtime. Only to be used by new() to create an
    /// OwnedRuntime. Automatically implemented for T where T: Default
    fn construct() -> Self;
}

impl<'a, T: InternalRuntime + Sized + 'a> StartableRuntime<'a> for T
where
    T: Default,
{
    fn construct() -> Self {
        Self::default()
    }
}