tor_rtcompat/
async_std.rs

1//! Entry points for use with async_std runtimes.
2pub use crate::impls::async_std::create_runtime as create_runtime_impl;
3use crate::{compound::CompoundRuntime, RealCoarseTimeProvider, ToplevelBlockOn};
4use std::io::Result as IoResult;
5
6#[cfg(feature = "native-tls")]
7use crate::impls::native_tls::NativeTlsProvider;
8#[cfg(feature = "rustls")]
9use crate::impls::rustls::RustlsProvider;
10
11use async_executors::AsyncStd;
12
13/// An alias for the async_std runtime that we prefer to use, based on whatever TLS
14/// implementation has been enabled.
15///
16/// If only one of `native_tls` and `rustls` bas been enabled within the
17/// `tor-rtcompat` crate, that will be the TLS backend that this uses.
18///
19/// Currently, `native_tls` is preferred over `rustls` when both are available,
20/// because of its maturity within Arti.  However, this might change in the
21/// future.
22#[cfg(feature = "native-tls")]
23pub use AsyncStdNativeTlsRuntime as PreferredRuntime;
24
25#[cfg(all(feature = "rustls", not(feature = "native-tls")))]
26pub use AsyncStdRustlsRuntime as PreferredRuntime;
27
28/// A [`Runtime`](crate::Runtime) powered by `async_std` and `native_tls`.
29#[derive(Clone)]
30#[cfg(feature = "native-tls")]
31pub struct AsyncStdNativeTlsRuntime {
32    /// The actual runtime object.
33    inner: NativeTlsInner,
34}
35
36/// Implementation type for AsyncStdRuntime.
37#[cfg(feature = "native-tls")]
38type NativeTlsInner = CompoundRuntime<
39    AsyncStd,
40    AsyncStd,
41    RealCoarseTimeProvider,
42    AsyncStd,
43    AsyncStd,
44    NativeTlsProvider,
45    AsyncStd,
46>;
47
48#[cfg(feature = "native-tls")]
49crate::opaque::implement_opaque_runtime! {
50    AsyncStdNativeTlsRuntime { inner : NativeTlsInner }
51}
52
53#[cfg(feature = "rustls")]
54/// A [`Runtime`](crate::Runtime) powered by `async_std` and `rustls`.
55#[derive(Clone)]
56pub struct AsyncStdRustlsRuntime {
57    /// The actual runtime object.
58    inner: RustlsInner,
59}
60
61/// Implementation type for AsyncStdRustlsRuntime.
62#[cfg(feature = "rustls")]
63type RustlsInner = CompoundRuntime<
64    AsyncStd,
65    AsyncStd,
66    RealCoarseTimeProvider,
67    AsyncStd,
68    AsyncStd,
69    RustlsProvider,
70    AsyncStd,
71>;
72
73#[cfg(feature = "rustls")]
74crate::opaque::implement_opaque_runtime! {
75    AsyncStdRustlsRuntime { inner: RustlsInner }
76}
77
78#[cfg(feature = "native-tls")]
79impl AsyncStdNativeTlsRuntime {
80    /// Return a new [`AsyncStdNativeTlsRuntime`]
81    ///
82    /// Generally you should call this function only once, and then use
83    /// [`Clone::clone()`] to create additional references to that
84    /// runtime.
85    pub fn create() -> IoResult<Self> {
86        let rt = create_runtime_impl();
87        let ct = RealCoarseTimeProvider::new();
88        Ok(AsyncStdNativeTlsRuntime {
89            inner: CompoundRuntime::new(rt, rt, ct, rt, rt, NativeTlsProvider::default(), rt),
90        })
91    }
92
93    /// Return an [`AsyncStdNativeTlsRuntime`] for the currently running
94    /// `async_std` executor.
95    ///
96    /// Note that since async_std executors are global, there is no distinction
97    /// between this method and [`AsyncStdNativeTlsRuntime::create()`]: it is
98    /// provided only for API consistency with the Tokio runtimes.
99    pub fn current() -> IoResult<Self> {
100        Self::create()
101    }
102
103    /// Helper to run a single test function in a freshly created runtime.
104    ///
105    /// # Panics
106    ///
107    /// Panics if we can't create this runtime.
108    ///
109    /// # Warning
110    ///
111    /// This API is **NOT** for consumption outside Arti. Semver guarantees are not provided.
112    #[doc(hidden)]
113    pub fn run_test<P, F, O>(func: P) -> O
114    where
115        P: FnOnce(Self) -> F,
116        F: futures::Future<Output = O>,
117    {
118        let runtime = Self::create().expect("Failed to create runtime");
119        runtime.clone().block_on(func(runtime))
120    }
121}
122
123#[cfg(feature = "rustls")]
124impl AsyncStdRustlsRuntime {
125    /// Return a new [`AsyncStdRustlsRuntime`]
126    ///
127    /// Generally you should call this function only once, and then use
128    /// [`Clone::clone()`] to create additional references to that
129    /// runtime.
130    pub fn create() -> IoResult<Self> {
131        let rt = create_runtime_impl();
132        let ct = RealCoarseTimeProvider::new();
133        Ok(AsyncStdRustlsRuntime {
134            inner: CompoundRuntime::new(rt, rt, ct, rt, rt, RustlsProvider::default(), rt),
135        })
136    }
137
138    /// Return an [`AsyncStdRustlsRuntime`] for the currently running
139    /// `async_std` executor.
140    ///
141    /// Note that since async_std executors are global, there is no distinction
142    /// between this method and [`AsyncStdNativeTlsRuntime::create()`]: it is
143    /// provided only for API consistency with the Tokio runtimes.
144    pub fn current() -> IoResult<Self> {
145        Self::create()
146    }
147
148    /// Helper to run a single test function in a freshly created runtime.
149    ///
150    /// # Panics
151    ///
152    /// Panics if we can't create this runtime.
153    ///
154    /// # Warning
155    ///
156    /// This API is **NOT** for consumption outside Arti. Semver guarantees are not provided.
157    #[doc(hidden)]
158    pub fn run_test<P, F, O>(func: P) -> O
159    where
160        P: FnOnce(Self) -> F,
161        F: futures::Future<Output = O>,
162    {
163        let runtime = Self::create().expect("Failed to create runtime");
164        runtime.clone().block_on(func(runtime))
165    }
166}
167
168#[cfg(not(miri))] // async_ztd startup seems to fail under miri
169#[cfg(test)]
170mod test {
171    // @@ begin test lint list maintained by maint/add_warning @@
172    #![allow(clippy::bool_assert_comparison)]
173    #![allow(clippy::clone_on_copy)]
174    #![allow(clippy::dbg_macro)]
175    #![allow(clippy::mixed_attributes_style)]
176    #![allow(clippy::print_stderr)]
177    #![allow(clippy::print_stdout)]
178    #![allow(clippy::single_char_pattern)]
179    #![allow(clippy::unwrap_used)]
180    #![allow(clippy::unchecked_duration_subtraction)]
181    #![allow(clippy::useless_vec)]
182    #![allow(clippy::needless_pass_by_value)]
183    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
184    use super::*;
185
186    #[test]
187    fn current() {
188        // We should actually have to run this inside a runtime with async_std,
189        // but let's do it anyway to make sure that "current" works.
190        let runtime = PreferredRuntime::create().unwrap();
191        runtime.block_on(async {
192            #[cfg(feature = "native-tls")]
193            assert!(AsyncStdNativeTlsRuntime::current().is_ok());
194
195            #[cfg(feature = "rustls")]
196            assert!(AsyncStdRustlsRuntime::current().is_ok());
197        });
198    }
199
200    #[test]
201    fn debug() {
202        #[cfg(feature = "native-tls")]
203        assert_eq!(
204            format!("{:?}", AsyncStdNativeTlsRuntime::create().unwrap()),
205            "AsyncStdNativeTlsRuntime { .. }"
206        );
207        #[cfg(feature = "rustls")]
208        assert_eq!(
209            format!("{:?}", AsyncStdRustlsRuntime::create().unwrap()),
210            "AsyncStdRustlsRuntime { .. }"
211        );
212    }
213}