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 ] |
6 | pub 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 = Bomb; |
16 | let t: T = f(); |
17 | std::mem::forget(bomb); |
18 | t |
19 | } |
20 | |
21 | /// Generates a random number in `0..n`. |
22 | #[cfg (feature = "unstable" )] |
23 | pub 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 |
56 | #[cfg (feature = "std" )] |
57 | pub(crate) trait Context { |
58 | fn context(self, message: impl Fn() -> String) -> Self; |
59 | } |
60 | |
61 | #[cfg (all( |
62 | not(target_os = "unknown" ), |
63 | any(feature = "default" , feature = "unstable" ) |
64 | ))] |
65 | mod timer { |
66 | pub type Timer = async_io::Timer; |
67 | } |
68 | |
69 | #[cfg (any(feature = "unstable" , feature = "default" ))] |
70 | pub(crate) fn timer_after(dur: std::time::Duration) -> timer::Timer { |
71 | Timer::after(duration:dur) |
72 | } |
73 | |
74 | #[cfg (any(all(target_arch = "wasm32" , feature = "default" ),))] |
75 | mod timer { |
76 | use std::pin::Pin; |
77 | use std::task::Poll; |
78 | |
79 | use gloo_timers::future::TimeoutFuture; |
80 | |
81 | #[derive (Debug)] |
82 | pub(crate) struct Timer(TimeoutFuture); |
83 | |
84 | impl Timer { |
85 | pub(crate) fn after(dur: std::time::Duration) -> Self { |
86 | // Round up to the nearest millisecond. |
87 | let mut timeout_ms = dur.as_millis() as u32; |
88 | if std::time::Duration::from_millis(timeout_ms as u64) < dur { |
89 | timeout_ms += 1; |
90 | } |
91 | |
92 | Timer(TimeoutFuture::new(timeout_ms)) |
93 | } |
94 | } |
95 | |
96 | impl std::future::Future for Timer { |
97 | type Output = (); |
98 | |
99 | fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> { |
100 | match Pin::new(&mut self.0).poll(cx) { |
101 | Poll::Pending => Poll::Pending, |
102 | Poll::Ready(_) => Poll::Ready(()), |
103 | } |
104 | } |
105 | } |
106 | } |
107 | |
108 | #[cfg (any(feature = "unstable" , feature = "default" ))] |
109 | pub(crate) use timer::*; |
110 | |
111 | /// Defers evaluation of a block of code until the end of the scope. |
112 | #[cfg (feature = "default" )] |
113 | #[doc (hidden)] |
114 | macro_rules! defer { |
115 | ($($body:tt)*) => { |
116 | let _guard = { |
117 | pub struct Guard<F: FnOnce()>(Option<F>); |
118 | |
119 | impl<F: FnOnce()> Drop for Guard<F> { |
120 | fn drop(&mut self) { |
121 | (self.0).take().map(|f| f()); |
122 | } |
123 | } |
124 | |
125 | Guard(Some(|| { |
126 | let _ = { $($body)* }; |
127 | })) |
128 | }; |
129 | }; |
130 | } |
131 | |
132 | /// Declares unstable items. |
133 | #[doc (hidden)] |
134 | macro_rules! cfg_unstable { |
135 | ($($item:item)*) => { |
136 | $( |
137 | #[cfg(feature = "unstable" )] |
138 | #[cfg_attr(feature = "docs" , doc(cfg(unstable)))] |
139 | $item |
140 | )* |
141 | } |
142 | } |
143 | |
144 | /// Declares unstable and default items. |
145 | #[doc (hidden)] |
146 | macro_rules! cfg_unstable_default { |
147 | ($($item:item)*) => { |
148 | $( |
149 | #[cfg(all(feature = "default" , feature = "unstable" ))] |
150 | #[cfg_attr(feature = "docs" , doc(cfg(unstable)))] |
151 | $item |
152 | )* |
153 | } |
154 | } |
155 | |
156 | /// Declares Unix-specific items. |
157 | #[doc (hidden)] |
158 | #[allow (unused_macros)] |
159 | macro_rules! cfg_unix { |
160 | ($($item:item)*) => { |
161 | $( |
162 | #[cfg(any(unix, feature = "docs" ))] |
163 | $item |
164 | )* |
165 | } |
166 | } |
167 | |
168 | /// Declares Windows-specific items. |
169 | #[doc (hidden)] |
170 | #[allow (unused_macros)] |
171 | macro_rules! cfg_windows { |
172 | ($($item:item)*) => { |
173 | $( |
174 | #[cfg(any(windows, feature = "docs" ))] |
175 | $item |
176 | )* |
177 | } |
178 | } |
179 | |
180 | /// Declares items when the "docs" feature is enabled. |
181 | #[doc (hidden)] |
182 | #[allow (unused_macros)] |
183 | macro_rules! cfg_docs { |
184 | ($($item:item)*) => { |
185 | $( |
186 | #[cfg(feature = "docs" )] |
187 | $item |
188 | )* |
189 | } |
190 | } |
191 | |
192 | /// Declares items when the "docs" feature is disabled. |
193 | #[doc (hidden)] |
194 | #[allow (unused_macros)] |
195 | macro_rules! cfg_not_docs { |
196 | ($($item:item)*) => { |
197 | $( |
198 | #[cfg(not(feature = "docs" ))] |
199 | $item |
200 | )* |
201 | } |
202 | } |
203 | |
204 | /// Declares std items. |
205 | #[allow (unused_macros)] |
206 | #[doc (hidden)] |
207 | macro_rules! cfg_std { |
208 | ($($item:item)*) => { |
209 | $( |
210 | #[cfg(feature = "std" )] |
211 | $item |
212 | )* |
213 | } |
214 | } |
215 | |
216 | /// Declares no-std items. |
217 | #[allow (unused_macros)] |
218 | #[doc (hidden)] |
219 | macro_rules! cfg_alloc { |
220 | ($($item:item)*) => { |
221 | $( |
222 | #[cfg(feature = "alloc" )] |
223 | $item |
224 | )* |
225 | } |
226 | } |
227 | |
228 | /// Declares default items. |
229 | #[allow (unused_macros)] |
230 | #[doc (hidden)] |
231 | macro_rules! cfg_default { |
232 | ($($item:item)*) => { |
233 | $( |
234 | #[cfg(feature = "default" )] |
235 | $item |
236 | )* |
237 | } |
238 | } |
239 | |
240 | /// Declares items that use I/O safety. |
241 | #[allow (unused_macros)] |
242 | #[doc (hidden)] |
243 | macro_rules! cfg_io_safety { |
244 | ($($item:item)*) => { |
245 | $( |
246 | #[cfg(feature = "io_safety" )] |
247 | $item |
248 | )* |
249 | } |
250 | } |
251 | |