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