unicount_lib/
lib.rs

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