tuwunel_core/utils/mod.rs
1//! Reusable helpers and extension traits for core services.
2//!
3//! The module groups compile-time assertions, closure-producing macros, and
4//! common utilities shared across workspace crates. Frequently used helpers are
5//! re-exported through a single import path.
6
7pub mod arrayvec;
8pub mod bool;
9pub mod bytes;
10pub mod content_disposition;
11pub mod debug;
12pub mod defer;
13pub mod future;
14pub mod hash;
15pub mod html;
16pub mod json;
17pub mod math;
18pub mod mutex;
19pub mod mutex_map;
20pub mod option;
21pub mod rand;
22pub mod result;
23pub mod secret;
24pub mod set;
25pub mod stream;
26pub mod string;
27pub mod sys;
28#[cfg(test)]
29mod tests;
30pub mod time;
31pub mod two_phase_counter;
32pub mod unhandled;
33pub mod url;
34
35pub use ::ctor::ctor;
36pub use ::dtor::dtor;
37pub use ::tuwunel_macros::{async_noinline, implement};
38
39pub use self::{
40 arrayvec::ArrayVecExt,
41 bool::BoolExt,
42 bytes::{increment, u64_from_bytes, u64_from_u8},
43 debug::slice_truncated as debug_slice_truncated,
44 future::{BoolExt as FutureBoolExt, OptionStream, TryExtExt as TryFutureExtExt},
45 hash::sha256::delimited as calculate_hash,
46 json::{deserialize_from_str, serialized_len, to_canonical_object},
47 mutex::MutexExt,
48 mutex_map::{Guard as MutexMapGuard, MutexMap},
49 option::OptionExt,
50 rand::{shuffle, string as random_string, string_from as random_string_from},
51 secret::{Secret, is_set as is_secret_set, resolve as resolve_secret},
52 stream::{IterStream, ReadyExt, Tools as StreamTools, TryReadyExt},
53 string::{str_from_bytes, string_from_bytes},
54 sys::compute::available_parallelism,
55 time::{
56 exponential_backoff::{
57 continue_exponential_backoff, continue_exponential_backoff_secs,
58 exponential_backoff_remaining, exponential_backoff_remaining_secs,
59 exponential_backoff_streak_cap,
60 },
61 now_millis as millis_since_unix_epoch, timepoint_ago, timepoint_from_now,
62 timepoint_has_passed,
63 },
64 url::SanitizedUri,
65};
66
67/// Asserts at compile time that `T` implements `Send`.
68///
69/// The generic bound supplies the assertion, and the function performs no
70/// runtime work.
71pub const fn assert_send<T: Send>() {}
72
73/// Asserts at compile time that `T` implements `Sync`.
74///
75/// The generic bound supplies the assertion, and the function performs no
76/// runtime work.
77pub const fn assert_sync<T: Sync>() {}
78
79/// Accepts any type, including an unsized type, without performing work.
80///
81/// The `?Sized` bound removes the implicit `Sized` requirement. The const
82/// signature permits use from const contexts.
83pub const fn assert_dst<T: ?Sized>() {}
84
85/// Asserts at compile time that `T` implements `Sized`.
86///
87/// The generic bound supplies the assertion, and the function performs no
88/// runtime work.
89pub const fn assert_sized<T: Sized>() {}
90
91/// Asserts at compile time that `T` implements `Unpin`.
92///
93/// The generic bound supplies the assertion, and the function performs no
94/// runtime work.
95pub const fn assert_unpin<T: Unpin>() {}
96
97/// Asserts at compile time that `T` implements `UnwindSafe`.
98///
99/// The generic bound supplies the assertion, and the function performs no
100/// runtime work.
101pub const fn assert_unwind_safe<T: std::panic::UnwindSafe>() {}
102
103/// Asserts at compile time that `T` implements `RefUnwindSafe`.
104///
105/// The generic bound supplies the assertion, and the function performs no
106/// runtime work.
107pub const fn assert_ref_unwind_safe<T: std::panic::RefUnwindSafe>() {}
108
109/// Extracts the payload from any listed tuple variant into an `Option`.
110///
111/// The expression is matched once, and a listed variant returns
112/// `Some(payload)`. Every other variant returns `None`.
113#[macro_export]
114macro_rules! extract_variant {
115 ( $e:expr_2021, $( $variant:path )|* ) => {
116 match $e {
117 $( $variant(value) => Some(value), )*
118 _ => None,
119 }
120 };
121}
122
123/// Extracts a pattern-bound value into an `Option`.
124///
125/// The expression is matched once against the supplied pattern. A match returns
126/// the named binding in `Some`, while every other value returns `None`.
127#[macro_export]
128macro_rules! extract {
129 ($e:expr_2021, $out:ident in $variant:pat) => {
130 match $e {
131 | $variant => Some($out),
132 | _ => None,
133 }
134 };
135}
136
137/// Creates a closure that reports whether its input is nonempty.
138///
139/// The generated closure delegates to `is_empty` and negates the result.
140#[macro_export]
141macro_rules! is_not_empty {
142 () => {
143 |x| !x.is_empty()
144 };
145}
146
147/// Creates a closure that applies one callable to every field of a tuple.
148///
149/// Tuple arities from one through five are supported. The callable tokens are
150/// expanded once for each field and therefore may be evaluated more than once.
151#[macro_export]
152macro_rules! apply {
153 (1, $($idx:tt)+) => {
154 |t| (($($idx)+)(t.0),)
155 };
156
157 (2, $($idx:tt)+) => {
158 |t| (($($idx)+)(t.0), ($($idx)+)(t.1),)
159 };
160
161 (3, $($idx:tt)+) => {
162 |t| (($($idx)+)(t.0), ($($idx)+)(t.1), ($($idx)+)(t.2),)
163 };
164
165 (4, $($idx:tt)+) => {
166 |t| (($($idx)+)(t.0), ($($idx)+)(t.1), ($($idx)+)(t.2), ($($idx)+)(t.3),)
167 };
168
169 (5, $($idx:tt)+) => {
170 |t| (($($idx)+)(t.0), ($($idx)+)(t.1), ($($idx)+)(t.2), ($($idx)+)(t.3), ($($idx)+)(t.4),)
171 };
172}
173
174/// Expands a type or expression into a two-element tuple with identical
175/// entries.
176///
177/// The type form produces `(T, T)`. The expression form evaluates the supplied
178/// expression separately for each tuple element.
179#[macro_export]
180macro_rules! pair_of {
181 ($decl:ty) => {
182 ($decl, $decl)
183 };
184
185 ($init:expr_2021) => {
186 ($init, $init)
187 };
188}
189
190/// Creates a Boolean identity closure.
191///
192/// The generated closure applies logical negation twice, making it usable where
193/// a predicate function is required.
194#[macro_export]
195macro_rules! is_true {
196 () => {
197 |x| !!x
198 };
199}
200
201/// Creates a closure that negates a Boolean input.
202///
203/// The generated closure returns `!x` and can be passed directly to predicate
204/// combinators.
205#[macro_export]
206macro_rules! is_false {
207 () => {
208 |x| !x
209 };
210}
211
212/// Creates a closure that reports whether its input differs from zero.
213///
214/// The generated closure compares each input with the integer literal `0`.
215#[macro_export]
216macro_rules! is_nonzero {
217 () => {
218 |x| x != 0
219 };
220}
221
222/// Creates a closure that reports whether its input matches zero.
223///
224/// The generated closure uses a literal pattern through `is_matching!`.
225#[macro_export]
226macro_rules! is_zero {
227 () => {
228 $crate::is_matching!(0)
229 };
230}
231
232/// Creates a closure that compares each input with a supplied value for
233/// equality.
234///
235/// The comparison target remains inside the closure body and is evaluated on
236/// every call.
237#[macro_export]
238macro_rules! is_equal_to {
239 ($val:ident) => {
240 |x| x == $val
241 };
242
243 ($val:expr_2021) => {
244 |x| x == $val
245 };
246}
247
248/// Creates a closure that compares each input with a supplied value for
249/// inequality.
250///
251/// The comparison target remains inside the closure body and is evaluated on
252/// every call.
253#[macro_export]
254macro_rules! is_not_equal_to {
255 ($val:ident) => {
256 |x| x != $val
257 };
258
259 ($val:expr_2021) => {
260 |x| x != $val
261 };
262}
263
264/// Creates a closure that reports whether each input is less than a supplied
265/// value.
266///
267/// The comparison target remains inside the closure body and is evaluated on
268/// every call.
269#[macro_export]
270macro_rules! is_less_than {
271 ($val:ident) => {
272 |x| x < $val
273 };
274
275 ($val:expr_2021) => {
276 |x| x < $val
277 };
278}
279
280/// Creates a closure that tests its input with a `matches!` pattern.
281///
282/// The supplied tokens can contain any pattern form accepted by `matches!`. The
283/// closure returns false when the input does not match.
284#[macro_export]
285macro_rules! is_matching {
286 ($val:ident) => {
287 |x| matches!(x, $val)
288 };
289
290 ($($val:tt)+) => {
291 |x| matches!(x, $($val)+)
292 };
293}
294
295/// Creates a two-argument closure that compares its inputs for equality.
296///
297/// The generated closure returns the result of `a == b`.
298#[macro_export]
299macro_rules! is_equal {
300 () => {
301 |a, b| a == b
302 };
303}
304
305/// Creates a closure that dereferences an indexed tuple field.
306///
307/// The tuple argument is received by value, and the selected field is returned
308/// through unary dereference.
309#[macro_export]
310macro_rules! deref_at {
311 ($idx:tt) => {
312 |t| *t.$idx
313 };
314}
315
316/// Creates a closure that borrows an indexed tuple field.
317///
318/// The generated `ref` pattern borrows the tuple argument before returning a
319/// reference to the selected field.
320#[macro_export]
321macro_rules! ref_at {
322 ($idx:tt) => {
323 |ref t| &t.$idx
324 };
325}
326
327/// Creates a closure that returns an indexed field from a referenced tuple by
328/// value.
329///
330/// The generated pattern destructures the shared reference before selecting the
331/// field. Moving the tuple from that reference therefore requires a copyable
332/// value.
333#[macro_export]
334macro_rules! val_at {
335 ($idx:tt) => {
336 |&t| t.$idx
337 };
338}
339
340/// Creates a closure that selects an indexed tuple field by value.
341///
342/// The generated closure consumes its tuple argument and returns the selected
343/// field.
344#[macro_export]
345macro_rules! at {
346 ($idx:tt) => {
347 |t| t.$idx
348 };
349}