Skip to main content

sift_core/query/
spec.rs

1bitflags::bitflags! {
2    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
3    pub struct QueryFlags: u8 {
4        const FIXED_STRINGS    = 1 << 0;
5        const CASE_INSENSITIVE = 1 << 1;
6        const WORD_REGEXP      = 1 << 2;
7        const LINE_REGEXP      = 1 << 3;
8        const INVERT_MATCH     = 1 << 4;
9    }
10}
11
12#[derive(Debug, Clone)]
13pub struct QuerySpec<'a> {
14    pub patterns: &'a [String],
15    pub flags: QueryFlags,
16}
17
18impl QuerySpec<'_> {
19    #[must_use]
20    pub const fn fixed_strings(&self) -> bool {
21        self.flags.contains(QueryFlags::FIXED_STRINGS)
22    }
23
24    #[must_use]
25    pub const fn case_insensitive(&self) -> bool {
26        self.flags.contains(QueryFlags::CASE_INSENSITIVE)
27    }
28
29    #[must_use]
30    pub const fn word_regexp(&self) -> bool {
31        self.flags.contains(QueryFlags::WORD_REGEXP)
32    }
33
34    #[must_use]
35    pub const fn line_regexp(&self) -> bool {
36        self.flags.contains(QueryFlags::LINE_REGEXP)
37    }
38
39    #[must_use]
40    pub const fn invert_match(&self) -> bool {
41        self.flags.contains(QueryFlags::INVERT_MATCH)
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn empty_flags_all_return_false() {
51        let spec = QuerySpec {
52            patterns: &[],
53            flags: QueryFlags::empty(),
54        };
55        assert!(!spec.fixed_strings());
56        assert!(!spec.case_insensitive());
57        assert!(!spec.word_regexp());
58        assert!(!spec.line_regexp());
59        assert!(!spec.invert_match());
60    }
61
62    #[test]
63    fn fixed_strings_flag_returns_true() {
64        let spec = QuerySpec {
65            patterns: &[],
66            flags: QueryFlags::FIXED_STRINGS,
67        };
68        assert!(spec.fixed_strings());
69    }
70
71    #[test]
72    fn case_insensitive_flag_returns_true() {
73        let spec = QuerySpec {
74            patterns: &[],
75            flags: QueryFlags::CASE_INSENSITIVE,
76        };
77        assert!(spec.case_insensitive());
78    }
79
80    #[test]
81    fn word_regexp_flag_returns_true() {
82        let spec = QuerySpec {
83            patterns: &[],
84            flags: QueryFlags::WORD_REGEXP,
85        };
86        assert!(spec.word_regexp());
87    }
88
89    #[test]
90    fn line_regexp_flag_returns_true() {
91        let spec = QuerySpec {
92            patterns: &[],
93            flags: QueryFlags::LINE_REGEXP,
94        };
95        assert!(spec.line_regexp());
96    }
97
98    #[test]
99    fn invert_match_flag_returns_true() {
100        let spec = QuerySpec {
101            patterns: &[],
102            flags: QueryFlags::INVERT_MATCH,
103        };
104        assert!(spec.invert_match());
105    }
106
107    #[test]
108    fn multiple_flags_all_return_true() {
109        let mut flags = QueryFlags::empty();
110        flags |= QueryFlags::FIXED_STRINGS;
111        flags |= QueryFlags::CASE_INSENSITIVE;
112        flags |= QueryFlags::WORD_REGEXP;
113        let spec = QuerySpec {
114            patterns: &["test".to_string()],
115            flags,
116        };
117        assert!(spec.fixed_strings());
118        assert!(spec.case_insensitive());
119        assert!(spec.word_regexp());
120        assert!(!spec.line_regexp());
121        assert!(!spec.invert_match());
122    }
123}