1
//! Entry points for use with async_std runtimes.
2
pub use crate::impls::async_std::create_runtime as create_runtime_impl;
3
use crate::{compound::CompoundRuntime, RealCoarseTimeProvider, ToplevelBlockOn};
4
use std::io::Result as IoResult;
5

            
6
#[cfg(feature = "native-tls")]
7
use crate::impls::native_tls::NativeTlsProvider;
8
#[cfg(feature = "rustls")]
9
use crate::impls::rustls::RustlsProvider;
10

            
11
use 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")]
23
pub use AsyncStdNativeTlsRuntime as PreferredRuntime;
24

            
25
#[cfg(all(feature = "rustls", not(feature = "native-tls")))]
26
pub 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")]
31
pub struct AsyncStdNativeTlsRuntime {
32
    /// The actual runtime object.
33
    inner: NativeTlsInner,
34
}
35

            
36
/// Implementation type for AsyncStdRuntime.
37
#[cfg(feature = "native-tls")]
38
type NativeTlsInner = CompoundRuntime<
39
    AsyncStd,
40
    AsyncStd,
41
    RealCoarseTimeProvider,
42
    AsyncStd,
43
    AsyncStd,
44
    NativeTlsProvider,
45
    AsyncStd,
46
>;
47

            
48
#[cfg(feature = "native-tls")]
49
crate::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)]
56
pub struct AsyncStdRustlsRuntime {
57
    /// The actual runtime object.
58
    inner: RustlsInner,
59
}
60

            
61
/// Implementation type for AsyncStdRustlsRuntime.
62
#[cfg(feature = "rustls")]
63
type RustlsInner = CompoundRuntime<
64
    AsyncStd,
65
    AsyncStd,
66
    RealCoarseTimeProvider,
67
    AsyncStd,
68
    AsyncStd,
69
    RustlsProvider,
70
    AsyncStd,
71
>;
72

            
73
#[cfg(feature = "rustls")]
74
crate::opaque::implement_opaque_runtime! {
75
    AsyncStdRustlsRuntime { inner: RustlsInner }
76
}
77

            
78
#[cfg(feature = "native-tls")]
79
impl 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
450
    pub fn create() -> IoResult<Self> {
86
450
        let rt = create_runtime_impl();
87
450
        let ct = RealCoarseTimeProvider::new();
88
450
        Ok(AsyncStdNativeTlsRuntime {
89
450
            inner: CompoundRuntime::new(rt, rt, ct, rt, rt, NativeTlsProvider::default(), rt),
90
450
        })
91
450
    }
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
2
    pub fn current() -> IoResult<Self> {
100
2
        Self::create()
101
2
    }
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
138
    pub fn run_test<P, F, O>(func: P) -> O
114
138
    where
115
138
        P: FnOnce(Self) -> F,
116
138
        F: futures::Future<Output = O>,
117
138
    {
118
138
        let runtime = Self::create().expect("Failed to create runtime");
119
138
        runtime.clone().block_on(func(runtime))
120
138
    }
121
}
122

            
123
#[cfg(feature = "rustls")]
124
impl 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
434
    pub fn create() -> IoResult<Self> {
131
434
        let rt = create_runtime_impl();
132
434
        let ct = RealCoarseTimeProvider::new();
133
434
        Ok(AsyncStdRustlsRuntime {
134
434
            inner: CompoundRuntime::new(rt, rt, ct, rt, rt, RustlsProvider::default(), rt),
135
434
        })
136
434
    }
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
2
    pub fn current() -> IoResult<Self> {
145
2
        Self::create()
146
2
    }
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
138
    pub fn run_test<P, F, O>(func: P) -> O
159
138
    where
160
138
        P: FnOnce(Self) -> F,
161
138
        F: futures::Future<Output = O>,
162
138
    {
163
138
        let runtime = Self::create().expect("Failed to create runtime");
164
138
        runtime.clone().block_on(func(runtime))
165
138
    }
166
}
167

            
168
#[cfg(not(miri))] // async_ztd startup seems to fail under miri
169
#[cfg(test)]
170
mod 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
}