1#[doc = include_str!("../README.md")]
2use {clap::ValueEnum, unicode_segmentation::UnicodeSegmentation};
3
4fn split(s: &str) -> Vec<String> {
5 UnicodeSegmentation::graphemes(s, true)
6 .map(|x| x.to_string())
7 .collect()
8}
9
10pub struct Counter {
11 current: usize,
12 alphabet: Vec<String>,
13}
14
15impl Counter {
16 pub fn new(alphabet: &str, start: usize) -> Counter {
17 Counter {
18 current: start,
19 alphabet: split(alphabet),
20 }
21 }
22
23 fn get(&self, x: usize) -> String {
24 let length = self.alphabet.len();
25 let d = x / length;
26 let r = x % length;
27 let t = self.alphabet[r].clone();
28 if d == 0 {
29 t
30 } else {
31 format!("{}{t}", self.get(d - 1))
32 }
33 }
34}
35
36impl std::iter::Iterator for Counter {
37 type Item = String;
38
39 fn next(&mut self) -> Option<Self::Item> {
40 let r = self.to_string();
41 self.current += 1;
42 Some(r)
43 }
44}
45
46impl std::fmt::Display for Counter {
47 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
48 write!(f, "{}", self.get(self.current))
49 }
50}
51
52#[derive(Clone, ValueEnum)]
53pub enum Kind {
54 EnglishUpper,
55 EnglishLower,
56}
57
58impl Kind {
59 pub fn counter(&self, start: usize) -> Counter {
60 match self {
61 Kind::EnglishUpper => Counter::new("ABCDEFGHIJKLMNOPQRSTUVWXYZ", start),
62 Kind::EnglishLower => Counter::new("abcdefghijklmnopqrstuvwxyz", start),
63 }
64 }
65}