Skip to main content

osp_cli/dsl/parse/
key_spec.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub enum ExactMode {
3    None,
4    CaseInsensitive,
5    CaseSensitive,
6}
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct KeySpec {
10    pub token: String,
11    pub negated: bool,
12    pub existence: bool,
13    pub exact: ExactMode,
14    pub strict_ambiguous: bool,
15}
16
17impl KeySpec {
18    pub fn parse(input: &str) -> Self {
19        let mut remaining = input.trim();
20        let mut negated = false;
21        let mut existence = false;
22        let mut exact = ExactMode::None;
23        let mut strict_ambiguous = false;
24
25        loop {
26            if remaining.starts_with("!=") {
27                break;
28            }
29            if let Some(rest) = remaining.strip_prefix('!') {
30                negated = !negated;
31                remaining = rest.trim_start();
32                continue;
33            }
34            if let Some(rest) = remaining.strip_prefix('?') {
35                existence = true;
36                remaining = rest.trim_start();
37                continue;
38            }
39            if let Some(rest) = remaining.strip_prefix("==") {
40                exact = ExactMode::CaseSensitive;
41                strict_ambiguous = true;
42                remaining = rest.trim_start();
43                continue;
44            }
45            if let Some(rest) = remaining.strip_prefix('=') {
46                exact = ExactMode::CaseInsensitive;
47                remaining = rest.trim_start();
48                continue;
49            }
50            break;
51        }
52
53        Self {
54            token: remaining.to_string(),
55            negated,
56            existence,
57            exact,
58            strict_ambiguous,
59        }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::{ExactMode, KeySpec};
66
67    #[test]
68    fn parses_case_insensitive_exact() {
69        let spec = KeySpec::parse("=uid");
70        assert_eq!(spec.token, "uid");
71        assert_eq!(spec.exact, ExactMode::CaseInsensitive);
72        assert!(!spec.strict_ambiguous);
73    }
74
75    #[test]
76    fn parses_case_sensitive_exact_with_strict() {
77        let spec = KeySpec::parse("==uid");
78        assert_eq!(spec.token, "uid");
79        assert_eq!(spec.exact, ExactMode::CaseSensitive);
80        assert!(spec.strict_ambiguous);
81    }
82
83    #[test]
84    fn parses_negated_existence() {
85        let spec = KeySpec::parse("!?uid");
86        assert_eq!(spec.token, "uid");
87        assert!(spec.negated);
88        assert!(spec.existence);
89    }
90
91    #[test]
92    fn does_not_treat_bang_equal_as_prefix() {
93        let spec = KeySpec::parse("!=uid");
94        assert_eq!(spec.token, "!=uid");
95        assert!(!spec.negated);
96    }
97}