Skip to main content

tuwunel_core/utils/
rand.rs

1use std::{
2	ops::Range,
3	time::{Duration, SystemTime},
4};
5
6use arrayvec::ArrayString;
7use rand::{RngExt, rng, seq::SliceRandom};
8use ruma::OwnedEventId;
9
10pub fn shuffle<T>(vec: &mut [T]) {
11	let mut rng = rng();
12	vec.shuffle(&mut rng);
13}
14
15pub fn string(length: usize) -> String {
16	rng()
17		.sample_iter(&rand::distr::Alphanumeric)
18		.take(length)
19		.map(char::from)
20		.collect()
21}
22
23#[inline]
24pub fn string_array<const LENGTH: usize>() -> ArrayString<LENGTH> {
25	let mut ret = ArrayString::<LENGTH>::new();
26	rng()
27		.sample_iter(&rand::distr::Alphanumeric)
28		.take(LENGTH)
29		.map(char::from)
30		.for_each(|c| ret.push(c));
31
32	ret
33}
34
35#[must_use]
36pub fn event_id() -> OwnedEventId {
37	use base64::{
38		Engine,
39		alphabet::URL_SAFE,
40		engine::{GeneralPurpose, general_purpose::NO_PAD},
41	};
42
43	let mut binary: [u8; 32] = [0; _];
44	rand::fill(&mut binary);
45
46	let mut encoded: [u8; 43] = [0; _];
47	GeneralPurpose::new(&URL_SAFE, NO_PAD)
48		.encode_slice(binary, &mut encoded)
49		.expect("Failed to encode binary to base64");
50
51	let event_id: &str = str::from_utf8(&encoded)
52		.expect("Failed to convert array of base64 bytes to valid utf8 str");
53
54	OwnedEventId::from_parts('$', event_id, None)
55		.expect("Failed to generate valid random event_id")
56}
57
58#[must_use]
59pub fn truncate_string(mut str: String, range: Range<u64>) -> String {
60	let len = rng()
61		.random_range(range)
62		.try_into()
63		.unwrap_or(usize::MAX);
64
65	if let Some((i, _)) = str.char_indices().nth(len) {
66		str.truncate(i);
67	}
68
69	str
70}
71
72#[inline]
73#[must_use]
74pub fn truncate_str(str: &str, range: Range<u64>) -> &str {
75	let len = rng()
76		.random_range(range)
77		.try_into()
78		.unwrap_or(usize::MAX);
79
80	str.char_indices()
81		.nth(len)
82		.map(|(i, _)| str.split_at(i).0)
83		.unwrap_or(str)
84}
85
86#[inline]
87#[must_use]
88pub fn time_from_now_secs(range: Range<u64>) -> SystemTime {
89	SystemTime::now()
90		.checked_add(secs(range))
91		.expect("range does not overflow SystemTime")
92}
93
94#[must_use]
95pub fn secs(range: Range<u64>) -> Duration {
96	let mut rng = rng();
97	Duration::from_secs(rng.random_range(range))
98}