sieve/compiler/grammar/tests/
test_mailbox.rs1use crate::{
8 Metadata,
9 compiler::{
10 CompileError, RawValue, Value,
11 grammar::{
12 Capability, Comparator,
13 instruction::{CompilerState, MapLocalVars},
14 },
15 lexer::{Token, word::Word},
16 },
17};
18
19use crate::compiler::grammar::{MatchType, test::Test};
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(
23 any(test, feature = "serde"),
24 derive(serde::Serialize, serde::Deserialize)
25)]
26pub(crate) struct TestMailboxExists {
27 pub mailbox_names: Box<[Value]>,
28 pub is_not: bool,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
32#[cfg_attr(
33 any(test, feature = "serde"),
34 derive(serde::Serialize, serde::Deserialize)
35)]
36pub(crate) struct TestMetadataExists {
37 pub mailbox: Option<Value>,
38 pub annotation_names: Box<[Value]>,
39 pub is_not: bool,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
51#[cfg_attr(
52 any(test, feature = "serde"),
53 derive(serde::Serialize, serde::Deserialize)
54)]
55pub(crate) struct TestMetadata {
56 pub match_type: MatchType,
57 pub comparator: Comparator,
58 pub medatata: Metadata<Value>,
59 pub key_list: Box<[Value]>,
60 pub is_not: bool,
61}
62
63impl CompilerState<'_> {
71 pub(crate) fn parse_test_mailboxexists(&mut self) -> Result<Test, CompileError> {
72 Ok(Test::MailboxExists(Box::new(TestMailboxExists {
73 mailbox_names: self.parse_strings(false)?.into(),
74 is_not: false,
75 })))
76 }
77
78 pub(crate) fn parse_test_metadataexists(&mut self) -> Result<Test, CompileError> {
79 Ok(Test::MetadataExists(Box::new(TestMetadataExists {
80 mailbox: self.parse_string()?.into(),
81 annotation_names: self.parse_strings(false)?.into(),
82 is_not: false,
83 })))
84 }
85
86 pub(crate) fn parse_test_servermetadataexists(&mut self) -> Result<Test, CompileError> {
87 Ok(Test::MetadataExists(Box::new(TestMetadataExists {
88 mailbox: None,
89 annotation_names: self.parse_strings(false)?.into(),
90 is_not: false,
91 })))
92 }
93
94 pub(crate) fn parse_test_metadata(&mut self) -> Result<Test, CompileError> {
95 let mut match_type = MatchType::Is;
96 let mut comparator = Comparator::AsciiCaseMap;
97 let mut mailbox = None;
98 let mut annotation_name = None;
99 let key_list: Vec<RawValue>;
100
101 loop {
102 let token_info = self.tokens.unwrap_next()?;
103 match token_info.token {
104 Token::Tag(
105 word @ (Word::Is
106 | Word::Contains
107 | Word::Matches
108 | Word::Value
109 | Word::Count
110 | Word::Regex),
111 ) => {
112 self.validate_argument(
113 1,
114 match word {
115 Word::Value | Word::Count => Capability::Relational.into(),
116 Word::Regex => Capability::Regex.into(),
117 Word::List => Capability::ExtLists.into(),
118 _ => None,
119 },
120 token_info.line_num,
121 token_info.line_pos,
122 )?;
123
124 match_type = self.parse_match_type(word)?;
125 }
126 Token::Tag(Word::Comparator) => {
127 self.validate_argument(2, None, token_info.line_num, token_info.line_pos)?;
128 comparator = self.parse_comparator()?;
129 }
130 _ => {
131 if mailbox.is_none() {
132 mailbox = self.parse_string_token(token_info)?.into();
133 } else if annotation_name.is_none() {
134 annotation_name = self.parse_string_token(token_info)?.into();
135 } else {
136 key_list = self.parse_raw_strings_token(token_info)?;
137 break;
138 }
139 }
140 }
141 }
142 let key_list = self.validate_match(&match_type, &comparator, key_list)?;
143
144 Ok(Test::Metadata(Box::new(TestMetadata {
145 match_type,
146 comparator,
147 medatata: Metadata::Mailbox {
148 name: mailbox.unwrap(),
149 annotation: annotation_name.unwrap(),
150 },
151 key_list: key_list.into(),
152 is_not: false,
153 })))
154 }
155
156 pub(crate) fn parse_test_servermetadata(&mut self) -> Result<Test, CompileError> {
157 let mut match_type = MatchType::Is;
158 let mut comparator = Comparator::AsciiCaseMap;
159 let mut annotation_name = None;
160 let key_list: Vec<RawValue>;
161
162 loop {
163 let token_info = self.tokens.unwrap_next()?;
164 match token_info.token {
165 Token::Tag(
166 word @ (Word::Is
167 | Word::Contains
168 | Word::Matches
169 | Word::Value
170 | Word::Count
171 | Word::Regex),
172 ) => {
173 self.validate_argument(
174 1,
175 match word {
176 Word::Value | Word::Count => Capability::Relational.into(),
177 Word::Regex => Capability::Regex.into(),
178 Word::List => Capability::ExtLists.into(),
179 _ => None,
180 },
181 token_info.line_num,
182 token_info.line_pos,
183 )?;
184
185 match_type = self.parse_match_type(word)?;
186 }
187 Token::Tag(Word::Comparator) => {
188 self.validate_argument(2, None, token_info.line_num, token_info.line_pos)?;
189 comparator = self.parse_comparator()?;
190 }
191 _ => {
192 if annotation_name.is_none() {
193 annotation_name = self.parse_string_token(token_info)?.into();
194 } else {
195 key_list = self.parse_raw_strings_token(token_info)?;
196 break;
197 }
198 }
199 }
200 }
201 let key_list = self.validate_match(&match_type, &comparator, key_list)?;
202
203 Ok(Test::Metadata(Box::new(TestMetadata {
204 match_type,
205 comparator,
206 medatata: Metadata::Server {
207 annotation: annotation_name.unwrap(),
208 },
209 key_list: key_list.into(),
210 is_not: false,
211 })))
212 }
213}
214
215impl MapLocalVars for Metadata<Value> {
216 fn map_local_vars(&mut self, last_id: u16) {
217 match self {
218 Metadata::Mailbox { name, annotation } => {
219 name.map_local_vars(last_id);
220 annotation.map_local_vars(last_id);
221 }
222 Metadata::Server { annotation } => {
223 annotation.map_local_vars(last_id);
224 }
225 }
226 }
227}