trillium_testing/runtimeless/
runtime.rs1use futures_lite::{Stream, future};
2use std::{future::Future, sync::Arc, thread, time::Duration};
3use trillium_server_common::{DroppableFuture, Runtime, RuntimeTrait};
4
5#[derive(Debug, Clone, Copy, Default)]
7pub struct RuntimelessRuntime(());
8impl RuntimeTrait for RuntimelessRuntime {
9 fn spawn<Fut>(
10 &self,
11 fut: Fut,
12 ) -> DroppableFuture<impl Future<Output = Option<Fut::Output>> + Send + 'static>
13 where
14 Fut: Future + Send + 'static,
15 Fut::Output: Send + 'static,
16 {
17 let rt = *self;
18 let (send, receive) = async_channel::bounded(1);
19 thread::spawn(move || {
20 let _ = send.send_blocking(rt.block_on(fut));
21 });
22 DroppableFuture::new(async move { receive.recv().await.ok() })
23 }
24
25 async fn delay(&self, duration: Duration) {
26 let (send, receive) = async_channel::bounded(1);
27 thread::spawn(move || {
28 thread::sleep(duration);
29 let _ = send.send_blocking(());
30 });
31 let _ = receive.recv().await;
32 }
33
34 fn interval(&self, period: Duration) -> impl Stream<Item = ()> + Send + 'static {
35 let (send, receive) = async_channel::bounded(1);
36 thread::spawn(move || {
37 loop {
38 thread::sleep(period);
39 if send.send_blocking(()).is_err() {
40 break;
41 }
42 }
43 });
44
45 receive
46 }
47
48 fn block_on<Fut: Future>(&self, fut: Fut) -> Fut::Output {
49 future::block_on(fut)
50 }
51}
52
53impl From<RuntimelessRuntime> for Runtime {
54 fn from(value: RuntimelessRuntime) -> Self {
55 Arc::new(value).into()
56 }
57}
58
59impl RuntimelessRuntime {
60 pub fn spawn<Fut>(
70 &self,
71 fut: Fut,
72 ) -> DroppableFuture<impl Future<Output = Option<Fut::Output>> + Send + 'static + use<Fut>>
73 where
74 Fut: Future + Send + 'static,
75 Fut::Output: Send + 'static,
76 {
77 let rt = *self;
78 let (send, receive) = async_channel::bounded(1);
79 thread::spawn(move || {
80 let _ = send.send_blocking(rt.block_on(fut));
81 });
82 DroppableFuture::new(async move { receive.recv().await.ok() })
83 }
84
85 pub async fn delay(&self, duration: Duration) {
87 RuntimeTrait::delay(self, duration).await
88 }
89
90 pub fn interval(&self, period: Duration) -> impl Stream<Item = ()> + Send + 'static + use<> {
92 let (send, receive) = async_channel::bounded(1);
93 thread::spawn(move || {
94 loop {
95 thread::sleep(period);
96 if send.is_closed() {
97 break;
98 }
99 let _ = send.send_blocking(());
100 }
101 });
102
103 receive
104 }
105
106 pub fn block_on<Fut: Future>(&self, fut: Fut) -> Fut::Output {
108 future::block_on(fut)
109 }
110
111 pub async fn timeout<Fut>(&self, duration: Duration, fut: Fut) -> Option<Fut::Output>
113 where
114 Fut: Future + Send,
115 Fut::Output: Send + 'static,
116 {
117 RuntimeTrait::timeout(self, duration, fut).await
118 }
119}