async_std/
utils.rs

1/// Calls a function and aborts if it panics.
2///
3/// This is useful in unsafe code where we can't recover from panics.
4#[cfg(feature = "default")]
5#[inline]
6pub fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T {
7    struct Bomb;
8
9    impl Drop for Bomb {
10        fn drop(&mut self) {
11            std::process::abort();
12        }
13    }
14
15    let bomb = Bomb;
16    let t = f();
17    std::mem::forget(bomb);
18    t
19}
20
21/// Generates a random number in `0..n`.
22#[cfg(any(feature = "unstable", feature = "default"))]
23pub fn random(n: u32) -> u32 {
24    use std::cell::Cell;
25    use std::num::Wrapping;
26
27    thread_local! {
28        static RNG: Cell<Wrapping<u32>> = {
29            // Take the address of a local value as seed.
30            let mut x = 0i32;
31            let r = &mut x;
32            let addr = r as *mut i32 as usize;
33            Cell::new(Wrapping(addr as u32))
34        }
35    }
36
37    RNG.with(|rng| {
38        // This is the 32-bit variant of Xorshift.
39        //
40        // Source: https://en.wikipedia.org/wiki/Xorshift
41        let mut x = rng.get();
42        x ^= x << 13;
43        x ^= x >> 17;
44        x ^= x << 5;
45        rng.set(x);
46
47        // This is a fast alternative to `x % n`.
48        //
49        // Author: Daniel Lemire
50        // Source: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
51        ((u64::from(x.0)).wrapping_mul(u64::from(n)) >> 32) as u32
52    })
53}
54
55/// Add additional context to errors
56pub(crate) trait Context {
57    fn context(self, message: impl Fn() -> String) -> Self;
58}
59
60/// Declares unstable items.
61#[doc(hidden)]
62macro_rules! cfg_unstable {
63    ($($item:item)*) => {
64        $(
65            #[cfg(feature = "unstable")]
66            #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
67            $item
68        )*
69    }
70}
71
72/// Declares unstable and default items.
73#[doc(hidden)]
74macro_rules! cfg_unstable_default {
75    ($($item:item)*) => {
76        $(
77            #[cfg(all(feature = "default", feature = "unstable"))]
78            #[cfg_attr(feature = "docs", doc(unstable))]
79            $item
80        )*
81    }
82}
83
84/// Declares Unix-specific items.
85#[doc(hidden)]
86macro_rules! cfg_unix {
87    ($($item:item)*) => {
88        $(
89            #[cfg(any(unix, feature = "docs"))]
90            #[cfg_attr(feature = "docs", doc(cfg(unix)))]
91            $item
92        )*
93    }
94}
95
96/// Declares Windows-specific items.
97#[doc(hidden)]
98macro_rules! cfg_windows {
99    ($($item:item)*) => {
100        $(
101            #[cfg(any(windows, feature = "docs"))]
102            #[cfg_attr(feature = "docs", doc(cfg(windows)))]
103            $item
104        )*
105    }
106}
107
108/// Declares items when the "docs" feature is enabled.
109#[doc(hidden)]
110macro_rules! cfg_docs {
111    ($($item:item)*) => {
112        $(
113            #[cfg(feature = "docs")]
114            $item
115        )*
116    }
117}
118
119/// Declares items when the "docs" feature is disabled.
120#[doc(hidden)]
121macro_rules! cfg_not_docs {
122    ($($item:item)*) => {
123        $(
124            #[cfg(not(feature = "docs"))]
125            $item
126        )*
127    }
128}
129
130/// Declares std items.
131#[allow(unused_macros)]
132#[doc(hidden)]
133macro_rules! cfg_std {
134    ($($item:item)*) => {
135        $(
136            #[cfg(feature = "std")]
137            $item
138        )*
139    }
140}
141
142/// Declares default items.
143#[allow(unused_macros)]
144#[doc(hidden)]
145macro_rules! cfg_default {
146    ($($item:item)*) => {
147        $(
148            #[cfg(feature = "default")]
149            $item
150        )*
151    }
152}
153
154/// Defines an extension trait for a base trait.
155///
156/// In generated docs, the base trait will contain methods from the extension trait. In actual
157/// code, the base trait will be re-exported and the extension trait will be hidden. We then
158/// re-export the extension trait from the prelude.
159///
160/// Inside invocations of this macro, we write a definitions that looks similar to the final
161/// rendered docs, and the macro then generates all the boilerplate for us.
162#[doc(hidden)]
163macro_rules! extension_trait {
164    (
165        // Interesting patterns:
166        // - `$name`: trait name that gets rendered in the docs
167        // - `$ext`: name of the hidden extension trait
168        // - `$base`: base trait
169        #[doc = $doc:tt]
170        pub trait $name:ident {
171            $($body_base:tt)*
172        }
173
174        #[doc = $doc_ext:tt]
175        pub trait $ext:ident: $base:path {
176            $($body_ext:tt)*
177        }
178
179        // Shim trait impls that only appear in docs.
180        $($imp:item)*
181    ) => {
182        // A fake `impl Future` type that doesn't borrow.
183        #[allow(dead_code)]
184        mod owned {
185            #[doc(hidden)]
186            pub struct ImplFuture<T>(std::marker::PhantomData<T>);
187        }
188
189        // A fake `impl Future` type that borrows its environment.
190        #[allow(dead_code)]
191        mod borrowed {
192            #[doc(hidden)]
193            pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>);
194        }
195
196        // Render a fake trait combining the bodies of the base trait and the extension trait.
197        #[cfg(feature = "docs")]
198        #[doc = $doc]
199        pub trait $name {
200            extension_trait!(@doc () $($body_base)* $($body_ext)*);
201        }
202
203        // When not rendering docs, re-export the base trait from the futures crate.
204        #[cfg(not(feature = "docs"))]
205        pub use $base as $name;
206
207        // The extension trait that adds methods to any type implementing the base trait.
208        #[doc = $doc_ext]
209        pub trait $ext: $name {
210            extension_trait!(@ext () $($body_ext)*);
211        }
212
213        // Blanket implementation of the extension trait for any type implementing the base trait.
214        impl<T: $name + ?Sized> $ext for T {}
215
216        // Shim trait impls that only appear in docs.
217        $(#[cfg(feature = "docs")] $imp)*
218    };
219
220    // Optimization: expand `$head` eagerly before starting a new method definition.
221    (@ext ($($head:tt)*) #[doc = $d:literal] $($tail:tt)*) => {
222        $($head)* extension_trait!(@ext (#[doc = $d]) $($tail)*);
223    };
224
225    // Parse the return type in an extension method.
226    (@doc ($($head:tt)*) -> impl Future<Output = $out:ty> $(+ $lt:lifetime)? [$f:ty] $($tail:tt)*) => {
227        extension_trait!(@doc ($($head)* -> owned::ImplFuture<$out>) $($tail)*);
228    };
229    (@ext ($($head:tt)*) -> impl Future<Output = $out:ty> $(+ $lt:lifetime)? [$f:ty] $($tail:tt)*) => {
230        extension_trait!(@ext ($($head)* -> $f) $($tail)*);
231    };
232
233    // Parse the return type in an extension method.
234    (@doc ($($head:tt)*) -> impl Future<Output = $out:ty> + $lt:lifetime [$f:ty] $($tail:tt)*) => {
235        extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$lt, $out>) $($tail)*);
236    };
237    (@ext ($($head:tt)*) -> impl Future<Output = $out:ty> + $lt:lifetime [$f:ty] $($tail:tt)*) => {
238        extension_trait!(@ext ($($head)* -> $f) $($tail)*);
239    };
240
241    // Parse a token.
242    (@doc ($($head:tt)*) $token:tt $($tail:tt)*) => {
243        extension_trait!(@doc ($($head)* $token) $($tail)*);
244    };
245    (@ext ($($head:tt)*) $token:tt $($tail:tt)*) => {
246        extension_trait!(@ext ($($head)* $token) $($tail)*);
247    };
248
249    // Handle the end of the token list.
250    (@doc ($($head:tt)*)) => { $($head)* };
251    (@ext ($($head:tt)*)) => { $($head)* };
252
253    // Parse imports at the beginning of the macro.
254    ($import:item $($tail:tt)*) => {
255        #[cfg(feature = "docs")]
256        $import
257
258        extension_trait!($($tail)*);
259    };
260}