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}