unicount_lib/
lib.rs

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}