tuwunel_core/utils/
rand.rs1use 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
15#[must_use]
17pub fn index(len: usize) -> usize {
18 match len {
19 | 0 => 0,
20 | len => rng().random_range(0..len),
21 }
22}
23
24pub fn string(length: usize) -> String {
25 rng()
26 .sample_iter(&rand::distr::Alphanumeric)
27 .take(length)
28 .map(char::from)
29 .collect()
30}
31
32#[must_use]
34pub fn string_from(charset: &[u8], length: usize) -> String {
35 let mut rng = rng();
36 (0..length)
37 .map(|_| char::from(charset[rng.random_range(0..charset.len())]))
38 .collect()
39}
40
41#[inline]
42pub fn string_array<const LENGTH: usize>() -> ArrayString<LENGTH> {
43 let mut ret = ArrayString::<LENGTH>::new();
44 rng()
45 .sample_iter(&rand::distr::Alphanumeric)
46 .take(LENGTH)
47 .map(char::from)
48 .for_each(|c| ret.push(c));
49
50 ret
51}
52
53#[must_use]
54pub fn event_id() -> OwnedEventId {
55 use base64::{
56 Engine,
57 alphabet::URL_SAFE,
58 engine::{GeneralPurpose, general_purpose::NO_PAD},
59 };
60
61 let mut binary: [u8; 32] = [0; _];
62 rand::fill(&mut binary);
63
64 let mut encoded: [u8; 43] = [0; _];
65 GeneralPurpose::new(&URL_SAFE, NO_PAD)
66 .encode_slice(binary, &mut encoded)
67 .expect("Failed to encode binary to base64");
68
69 let event_id: &str = str::from_utf8(&encoded)
70 .expect("Failed to convert array of base64 bytes to valid utf8 str");
71
72 OwnedEventId::from_parts('$', event_id, None)
73 .expect("Failed to generate valid random event_id")
74}
75
76#[must_use]
77pub fn truncate_string(mut str: String, range: Range<u64>) -> String {
78 let len = rng()
79 .random_range(range)
80 .try_into()
81 .unwrap_or(usize::MAX);
82
83 if let Some((i, _)) = str.char_indices().nth(len) {
84 str.truncate(i);
85 }
86
87 str
88}
89
90#[inline]
91#[must_use]
92pub fn truncate_str(str: &str, range: Range<u64>) -> &str {
93 let len = rng()
94 .random_range(range)
95 .try_into()
96 .unwrap_or(usize::MAX);
97
98 str.char_indices()
99 .nth(len)
100 .map(|(i, _)| str.split_at(i).0)
101 .unwrap_or(str)
102}
103
104#[inline]
105#[must_use]
106pub fn time_from_now_secs(range: Range<u64>) -> SystemTime {
107 SystemTime::now()
108 .checked_add(secs(range))
109 .expect("range does not overflow SystemTime")
110}
111
112#[must_use]
113pub fn secs(range: Range<u64>) -> Duration {
114 let mut rng = rng();
115 Duration::from_secs(rng.random_range(range))
116}