Skip to main content

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}