radr/
domain.rs

1use std::path::PathBuf;
2
3#[derive(Debug, Clone)]
4pub struct AdrMeta {
5    pub number: u32,
6    pub title: String,
7    pub status: String,
8    pub date: String,
9    pub supersedes: Option<u32>,
10    pub superseded_by: Option<u32>,
11    pub path: PathBuf,
12}
13
14pub fn slugify(s: &str) -> String {
15    let mut out = String::with_capacity(s.len());
16    let mut last_dash = false;
17    for ch in s.chars() {
18        let c = ch.to_ascii_lowercase();
19        if c.is_ascii_alphanumeric() {
20            out.push(c);
21            last_dash = false;
22        } else if (c.is_ascii_whitespace() || c == '-' || c == '_') && !last_dash {
23            out.push('-');
24            last_dash = true;
25        }
26    }
27    while out.ends_with('-') {
28        out.pop();
29    }
30    while out.starts_with('-') {
31        out.remove(0);
32    }
33    if out.is_empty() {
34        "adr".to_string()
35    } else {
36        out
37    }
38}
39
40pub fn parse_number(s: &str) -> anyhow::Result<u32> {
41    let s = s.trim();
42    let s = s.trim_start_matches('0');
43    if s.is_empty() {
44        Ok(0)
45    } else {
46        Ok(s.parse::<u32>()?)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn test_slugify() {
56        assert_eq!(slugify("Hello World"), "hello-world");
57        assert_eq!(slugify("  Multiple   Spaces  "), "multiple-spaces");
58        assert_eq!(slugify("Caps_and-Dashes"), "caps-and-dashes");
59        assert_eq!(slugify("@#Weird!! Title??"), "weird-title");
60        assert_eq!(slugify(""), "adr");
61        // Non-ASCII-only input collapses to default slug
62        assert_eq!(slugify("çåññøñ"), "adr");
63        // Leading/trailing dashes and separators are trimmed/condensed
64        assert_eq!(slugify(" -Hello- -World- "), "hello-world");
65    }
66
67    #[test]
68    fn test_parse_number() {
69        assert_eq!(parse_number("0003").unwrap(), 3);
70        assert_eq!(parse_number("3").unwrap(), 3);
71        assert_eq!(parse_number("0000").unwrap(), 0);
72        assert!(parse_number("abc").is_err());
73    }
74}