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 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}