seqset/
lib.rs

1pub const DEFAULT_CHARSET: &'static str = "abcdefghijklmnopqrstuvwxyzæøå";
2
3#[derive(Debug, Clone, Copy)]
4pub struct Sequence<'a> {
5    charset: &'a str,
6    output_length: usize,
7    charset_size: usize,
8    n: usize,
9    // the last valid value for `n` in the sequence (before the pattern repeats)
10    last_valid_n: usize,
11}
12
13impl<'a> Sequence<'a> {
14    pub fn new(output_length: usize) -> Self {
15        Self::with_charset(output_length, DEFAULT_CHARSET)
16    }
17
18    pub fn with_charset(output_length: usize, charset: &'a str) -> Self {
19        let charset_size = charset.chars().count();
20        let last_valid_n = if output_length == 0 {
21            0
22        } else {
23            (charset_size as f64).powi(output_length as i32) as usize
24        };
25
26        Self {
27            output_length,
28            charset,
29            charset_size,
30            n: 0,
31            last_valid_n,
32        }
33    }
34}
35
36impl<'a> Iterator for Sequence<'a> {
37    type Item = String;
38
39    fn next(&mut self) -> Option<Self::Item> {
40        if self.n >= self.last_valid_n {
41            return None;
42        }
43
44        let mut pattern = String::with_capacity(self.output_length);
45        for position in (0..self.output_length).rev() {
46            let i = (self.n / (self.charset_size as f64).powi(position as i32) as usize)
47                % self.charset_size;
48            let c = self.charset.chars().nth(i).expect("index is out of bounds");
49            pattern.push(c);
50        }
51
52        self.n += 1;
53        Some(pattern)
54    }
55}