handles_utils/suffix.rs
1//! # Suffix Generator
2//!
3//! `suffix_generator` provides a `SuffixGenerator` struct to generate unique suffix sequences for a given range
4//! and seed, excluding already used suffixes.
5
6use oorandom::Rand32;
7use twox_hash::XxHash64;
8extern crate alloc;
9use alloc::vec::Vec;
10use core::hash::Hasher;
11/// Generate a unique, shuffled suffix iterator.
12///
13/// # Returns
14///
15/// An iterator over the unique, shuffled sequence of suffixes.
16///
17/// # Examples
18///
19/// ```
20/// let min = 100;
21/// let max = 150;
22/// let canonical_base = "myhandle";
23///
24/// let lazy_sequence = handles_utils::suffix::generate_unique_suffixes(min, max, canonical_base);
25/// let suffixes: Vec<u16> = lazy_sequence.collect();
26/// ```
27///
28/// This will output a unique, shuffled sequence of suffixes.
29/// Note: This is a lazy iterator, so it will not be evaluated until it is consumed.
30pub fn generate_unique_suffixes(
31 min: u16,
32 max: u16,
33 canonical_base: &str,
34) -> impl Iterator<Item = u16> + '_ {
35 let seed = generate_seed(canonical_base);
36 let mut rng = Rand32::new(seed);
37
38 let mut indices: Vec<u16> = (min..=max).collect();
39 (min..=max).rev().map(move |i| {
40 let j = rng.rand_range((min as u32)..(i + 1) as u32) as u16;
41 indices.swap((i - min) as usize, (j - min) as usize);
42 indices[(i - min) as usize]
43 })
44}
45
46/// Generate a seed from a unique canonical base handle.
47///
48/// # Arguments
49///
50/// * `canonical_base` - The canonical base as a string slice.
51///
52/// # Returns
53///
54/// A 64-bit seed.
55///
56/// # Examples
57/// ```
58/// let canonical_base = "myuser";
59///
60/// let seed = handles_utils::suffix::generate_seed(canonical_base);
61/// ```
62pub fn generate_seed(canonical_base: &str) -> u64 {
63 let mut hasher = XxHash64::with_seed(0);
64 hasher.write(canonical_base.as_bytes());
65 let value_bytes: [u8; 4] = [0; 4];
66 hasher.write(&value_bytes);
67 hasher.finish()
68}