Skip to main content

ito_common/id/
mod.rs

1//! Identifier parsing and lightweight ID heuristics.
2
3mod change_id;
4mod error;
5mod module_id;
6mod spec_id;
7
8pub use change_id::parse_change_id;
9pub use change_id::{ChangeId, ParsedChangeId};
10pub use error::IdParseError;
11pub use module_id::parse_module_id;
12pub use module_id::{ModuleId, ParsedModuleId};
13pub use spec_id::parse_spec_id;
14pub use spec_id::{ParsedSpecId, SpecId};
15
16/// Quick heuristic used by CLI prompts to detect a likely change id.
17pub fn looks_like_change_id(input: &str) -> bool {
18    let input = input.trim();
19    if input.is_empty() {
20        return false;
21    }
22
23    let mut digit_prefix_len = 0usize;
24    let mut has_hyphen = false;
25    let mut has_underscore = false;
26
27    for ch in input.chars() {
28        if ch.is_ascii_digit() && digit_prefix_len == 0 {
29            digit_prefix_len = 1;
30            continue;
31        }
32
33        if ch.is_ascii_digit() && digit_prefix_len > 0 {
34            digit_prefix_len += 1;
35            continue;
36        }
37
38        if digit_prefix_len == 0 {
39            break;
40        }
41
42        match ch {
43            '-' => has_hyphen = true,
44            '_' => has_underscore = true,
45            _ => {}
46        }
47    }
48
49    digit_prefix_len > 0 && has_hyphen && has_underscore
50}
51
52/// Quick heuristic used by CLI prompts to detect a likely module id.
53pub fn looks_like_module_id(input: &str) -> bool {
54    let input = input.trim();
55    let Some(first) = input.chars().next() else {
56        return false;
57    };
58    first.is_ascii_digit()
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn looks_like_change_id_requires_digits_hyphen_and_underscore() {
67        assert!(looks_like_change_id("001-02_hello"));
68        assert!(!looks_like_change_id("-02_hello"));
69        assert!(!looks_like_change_id("001_hello"));
70        assert!(!looks_like_change_id("001-02hello"));
71        assert!(!looks_like_change_id("abc-02_hello"));
72    }
73
74    #[test]
75    fn looks_like_module_id_is_digit_prefixed() {
76        assert!(looks_like_module_id("001"));
77        assert!(looks_like_module_id("001_demo"));
78        assert!(looks_like_module_id(" 001_demo "));
79        assert!(!looks_like_module_id(""));
80        assert!(!looks_like_module_id("demo"));
81        assert!(!looks_like_module_id("_001_demo"));
82    }
83}