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

            
36
/// Implementation type for AsyncStdRuntime.
37
#[cfg(all(feature = "native-tls"))]
38
type NativeTlsInner = CompoundRuntime<AsyncStd, AsyncStd, AsyncStd, NativeTlsProvider>;
39

            
40
#[cfg(all(feature = "native-tls"))]
41
10
crate::opaque::implement_opaque_runtime! {
42
10
    AsyncStdNativeTlsRuntime { inner : NativeTlsInner }
43
10
}
44

            
45
#[cfg(feature = "rustls")]
46
/// A [`Runtime`](crate::Runtime) powered by `async_std` and `rustls`.
47
100
#[derive(Clone)]
48
pub struct AsyncStdRustlsRuntime {
49
    /// The actual runtime object.
50
    inner: RustlsInner,
51
}
52

            
53
/// Implementation type for AsyncStdRustlsRuntime.
54
#[cfg(feature = "rustls")]
55
type RustlsInner = CompoundRuntime<AsyncStd, AsyncStd, AsyncStd, RustlsProvider>;
56

            
57
#[cfg(feature = "rustls")]
58
1
crate::opaque::implement_opaque_runtime! {
59
1
    AsyncStdRustlsRuntime { inner: RustlsInner }
60
1
}
61

            
62
#[cfg(all(feature = "native-tls"))]
63
impl AsyncStdNativeTlsRuntime {
64
    /// Return a new [`AsyncStdNativeTlsRuntime`]
65
    ///
66
    /// Generally you should call this function only once, and then use
67
    /// [`Clone::clone()`] to create additional references to that
68
    /// runtime.
69
293
    pub fn create() -> IoResult<Self> {
70
293
        let rt = create_runtime_impl();
71
293
        Ok(AsyncStdNativeTlsRuntime {
72
293
            inner: CompoundRuntime::new(rt, rt, rt, NativeTlsProvider::default()),
73
293
        })
74
293
    }
75

            
76
    /// Return an [`AsyncStdNativeTlsRuntime`] for the currently running
77
    /// `async_std` executor.
78
    ///
79
    /// Note that since async_std executors are global, there is no distinction
80
    /// between this method and [`AsyncStdNativeTlsRuntime::create()`]: it is
81
    /// provided only for API consistency with the Tokio runtimes.
82
1
    pub fn current() -> IoResult<Self> {
83
1
        Self::create()
84
1
    }
85

            
86
    /// Helper to run a single test function in a freshly created runtime.
87
    ///
88
    /// # Panics
89
    ///
90
    /// Panics if we can't create this runtime.
91
    ///
92
    /// # Warning
93
    ///
94
    /// This API is **NOT** for consumption outside Arti. Semver guarantees are not provided.
95
    #[doc(hidden)]
96
48
    pub fn run_test<P, F, O>(func: P) -> O
97
48
    where
98
48
        P: FnOnce(Self) -> F,
99
48
        F: futures::Future<Output = O>,
100
48
    {
101
48
        let runtime = Self::create().expect("Failed to create runtime");
102
48
        runtime.clone().block_on(func(runtime))
103
48
    }
104
}
105

            
106
#[cfg(feature = "rustls")]
107
impl AsyncStdRustlsRuntime {
108
    /// Return a new [`AsyncStdRustlsRuntime`]
109
    ///
110
    /// Generally you should call this function only once, and then use
111
    /// [`Clone::clone()`] to create additional references to that
112
    /// runtime.
113
280
    pub fn create() -> IoResult<Self> {
114
280
        let rt = create_runtime_impl();
115
280
        Ok(AsyncStdRustlsRuntime {
116
280
            inner: CompoundRuntime::new(rt, rt, rt, RustlsProvider::default()),
117
280
        })
118
280
    }
119

            
120
    /// Return an [`AsyncStdRustlsRuntime`] for the currently running
121
    /// `async_std` executor.
122
    ///
123
    /// Note that since async_std executors are global, there is no distinction
124
    /// between this method and [`AsyncStdNativeTlsRuntime::create()`]: it is
125
    /// provided only for API consistency with the Tokio runtimes.
126
1
    pub fn current() -> IoResult<Self> {
127
1
        Self::create()
128
1
    }
129

            
130
    /// Helper to run a single test function in a freshly created runtime.
131
    ///
132
    /// # Panics
133
    ///
134
    /// Panics if we can't create this runtime.
135
    ///
136
    /// # Warning
137
    ///
138
    /// This API is **NOT** for consumption outside Arti. Semver guarantees are not provided.
139
    #[doc(hidden)]
140
48
    pub fn run_test<P, F, O>(func: P) -> O
141
48
    where
142
48
        P: FnOnce(Self) -> F,
143
48
        F: futures::Future<Output = O>,
144
48
    {
145
48
        let runtime = Self::create().expect("Failed to create runtime");
146
48
        runtime.clone().block_on(func(runtime))
147
48
    }
148
}
149

            
150
#[cfg(test)]
151
mod test {
152
    #![allow(clippy::unwrap_used)]
153
    use super::*;
154

            
155
    #[test]
156
    fn current() {
157
        // We should actually have to run this inside a runtime with async_std,
158
        // but let's do it anyway to make sure that "current" works.
159
        let runtime = PreferredRuntime::create().unwrap();
160
        runtime.block_on(async {
161
            #[cfg(feature = "native-tls")]
162
            assert!(AsyncStdNativeTlsRuntime::current().is_ok());
163

            
164
            #[cfg(feature = "rustls")]
165
            assert!(AsyncStdRustlsRuntime::current().is_ok());
166
        });
167
    }
168

            
169
    #[test]
170
    fn debug() {
171
        #[cfg(feature = "native-tls")]
172
        assert_eq!(
173
            format!("{:?}", AsyncStdNativeTlsRuntime::create().unwrap()),
174
            "AsyncStdNativeTlsRuntime { .. }"
175
        );
176
        #[cfg(feature = "rustls")]
177
        assert_eq!(
178
            format!("{:?}", AsyncStdRustlsRuntime::create().unwrap()),
179
            "AsyncStdRustlsRuntime { .. }"
180
        );
181
    }
182
}