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}