osp_cli/dsl/parse/
key_spec.rs1#[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}