Skip to main content

wreq_rt/rt/
tokio.rs

1//! Tokio IO integration for core.
2use std::{
3    future::Future,
4    pin::Pin,
5    task::{Context, Poll},
6    time::{Duration, Instant},
7};
8
9use pin_project_lite::pin_project;
10use wreq_proto::rt::{Executor, Sleep, Timer};
11
12/// Future executor that utilises `tokio` threads.
13#[non_exhaustive]
14#[derive(Default, Clone, Debug)]
15pub struct TokioExecutor {
16    _priv: (),
17}
18
19/// A Timer that uses the tokio runtime.
20#[non_exhaustive]
21#[derive(Default, Clone, Debug)]
22pub struct TokioTimer {
23    _priv: (),
24}
25
26// Use TokioSleep to get tokio::time::Sleep to implement Unpin.
27// see https://docs.rs/tokio/latest/tokio/time/struct.Sleep.html
28pin_project! {
29    #[derive(Debug)]
30    struct TokioSleep {
31        #[pin]
32        inner: tokio::time::Sleep,
33    }
34}
35
36// ===== impl TokioExecutor =====
37
38impl<Fut> Executor<Fut> for TokioExecutor
39where
40    Fut: Future + Send + 'static,
41    Fut::Output: Send + 'static,
42{
43    #[inline]
44    fn execute(&self, fut: Fut) {
45        tokio::spawn(fut);
46    }
47}
48
49impl TokioExecutor {
50    /// Create new executor that relies on [`tokio::spawn`] to execute futures.
51    #[inline]
52    pub fn new() -> Self {
53        Self { _priv: () }
54    }
55}
56
57// ==== impl TokioTimer =====
58
59impl Timer for TokioTimer {
60    #[inline]
61    fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>> {
62        Box::pin(TokioSleep {
63            inner: tokio::time::sleep(duration),
64        })
65    }
66
67    #[inline]
68    fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>> {
69        Box::pin(TokioSleep {
70            inner: tokio::time::sleep_until(deadline.into()),
71        })
72    }
73
74    #[inline]
75    fn now(&self) -> Instant {
76        tokio::time::Instant::now().into()
77    }
78
79    #[inline]
80    fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
81        sleep.as_mut().reset(new_deadline);
82    }
83}
84
85impl TokioTimer {
86    /// Create a new TokioTimer
87    #[inline]
88    pub fn new() -> Self {
89        Self { _priv: () }
90    }
91}
92
93// ===== impl TokioSleep =====
94
95impl Future for TokioSleep {
96    type Output = ();
97
98    #[inline]
99    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
100        self.project().inner.poll(cx)
101    }
102}
103
104impl Sleep for TokioSleep {
105    #[inline]
106    fn reset(self: Pin<&mut Self>, deadline: Instant) {
107        self.project().inner.as_mut().reset(deadline.into());
108    }
109}