1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! # Suffix Generator
//!
//! `suffix_generator` provides a `SuffixGenerator` struct to generate unique suffix sequences for a given range
//! and seed, excluding already used suffixes.

use oorandom::Rand32;
use twox_hash::XxHash64;
extern crate alloc;
use alloc::vec::Vec;
use core::hash::Hasher;
/// Generate a unique, shuffled suffix iterator.
///
/// # Returns
///
/// An iterator over the unique, shuffled sequence of suffixes.
///
/// # Examples
///
/// ```
/// let min = 100;
/// let max = 150;
/// let canonical_base = "myhandle";
///
/// let lazy_sequence = handles_utils::suffix::generate_unique_suffixes(min, max, canonical_base);
/// let suffixes: Vec<u16> = lazy_sequence.collect();
/// ```
///
/// This will output a unique, shuffled sequence of suffixes.
/// Note: This is a lazy iterator, so it will not be evaluated until it is consumed.
pub fn generate_unique_suffixes(
	min: u16,
	max: u16,
	canonical_base: &str,
) -> impl Iterator<Item = u16> + '_ {
	let seed = generate_seed(canonical_base);
	let mut rng = Rand32::new(seed);

	let mut indices: Vec<u16> = (min..=max).collect();
	(min..=max).rev().map(move |i| {
		let j = rng.rand_range((min as u32)..(i + 1) as u32) as u16;
		indices.swap((i - min) as usize, (j - min) as usize);
		indices[(i - min) as usize]
	})
}

/// Generate a seed from a unique canonical base handle.
///
/// # Arguments
///
/// * `canonical_base` - The canonical base as a string slice.
///
/// # Returns
///
/// A 64-bit seed.
///
/// # Examples
/// ```
/// let canonical_base = "myuser";
///
/// let seed = handles_utils::suffix::generate_seed(canonical_base);
/// ```
pub fn generate_seed(canonical_base: &str) -> u64 {
	let mut hasher = XxHash64::with_seed(0);
	hasher.write(canonical_base.as_bytes());
	let value_bytes: [u8; 4] = [0; 4];
	hasher.write(&value_bytes);
	hasher.finish()
}