textlane_core/helpers/
slug.rs1use std::collections::HashMap;
2
3use crate::helpers::slug_table::REMOVED;
4
5#[derive(Debug, Default)]
7pub struct Slugger {
8 occurrences: HashMap<String, usize>,
9}
10
11impl Slugger {
12 pub fn reserve(&mut self, value: &str) {
14 self.occurrences.entry(value.to_owned()).or_insert(0);
15 }
16
17 pub fn slug(&mut self, value: &str) -> String {
19 let original = create_slug(value);
20 let mut result = original.clone();
21 while self.occurrences.contains_key(&result) {
22 let count = self.occurrences.entry(original.clone()).or_default();
23 *count += 1;
24 result = format!("{original}-{count}");
25 }
26 self.occurrences.insert(result.clone(), 0);
27 result
28 }
29}
30
31pub fn create_slug(value: &str) -> String {
33 value
34 .to_lowercase()
35 .chars()
36 .filter(|character| !is_removed(*character))
37 .map(|character| if character == ' ' { '-' } else { character })
38 .collect()
39}
40
41fn is_removed(character: char) -> bool {
42 let code = u32::from(character);
43 REMOVED
44 .binary_search_by(|(start, end)| {
45 if *end < code {
46 std::cmp::Ordering::Less
47 } else if *start > code {
48 std::cmp::Ordering::Greater
49 } else {
50 std::cmp::Ordering::Equal
51 }
52 })
53 .is_ok()
54}