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