sieve/compiler/grammar/tests/
test_spamtest.rs1use serde::{Deserialize, Serialize};
25
26use crate::compiler::{
27 grammar::{instruction::CompilerState, Capability, Comparator},
28 lexer::{word::Word, Token},
29 CompileError, Value,
30};
31
32use crate::compiler::grammar::{test::Test, MatchType};
33
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40pub struct TestSpamTest {
41 pub value: Value,
42 pub match_type: MatchType,
43 pub comparator: Comparator,
44 pub percent: bool,
45 pub is_not: bool,
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
49pub(crate) struct TestVirusTest {
50 pub value: Value,
51 pub match_type: MatchType,
52 pub comparator: Comparator,
53 pub is_not: bool,
54}
55
56impl<'x> CompilerState<'x> {
57 pub(crate) fn parse_test_spamtest(&mut self) -> Result<Test, CompileError> {
58 let mut match_type = MatchType::Is;
59 let mut comparator = Comparator::AsciiCaseMap;
60 let mut percent = false;
61 let value;
62
63 loop {
64 let token_info = self.tokens.unwrap_next()?;
65 match token_info.token {
66 Token::Tag(
67 word @ (Word::Is
68 | Word::Contains
69 | Word::Matches
70 | Word::Value
71 | Word::Count
72 | Word::Regex),
73 ) => {
74 self.validate_argument(
75 1,
76 match word {
77 Word::Value | Word::Count => Capability::Relational.into(),
78 Word::Regex => Capability::Regex.into(),
79 Word::List => Capability::ExtLists.into(),
80 _ => None,
81 },
82 token_info.line_num,
83 token_info.line_pos,
84 )?;
85
86 match_type = self.parse_match_type(word)?;
87 }
88 Token::Tag(Word::Comparator) => {
89 self.validate_argument(2, None, token_info.line_num, token_info.line_pos)?;
90 comparator = self.parse_comparator()?;
91 }
92 Token::Tag(Word::Percent) => {
93 self.validate_argument(
94 3,
95 Capability::SpamTestPlus.into(),
96 token_info.line_num,
97 token_info.line_pos,
98 )?;
99 percent = true;
100 }
101 _ => {
102 value = self.parse_string_token(token_info)?;
103 break;
104 }
105 }
106 }
107
108 Ok(Test::SpamTest(TestSpamTest {
109 value,
110 percent,
111 match_type,
112 comparator,
113 is_not: false,
114 }))
115 }
116
117 pub(crate) fn parse_test_virustest(&mut self) -> Result<Test, CompileError> {
118 let mut match_type = MatchType::Is;
119 let mut comparator = Comparator::AsciiCaseMap;
120 let value;
121
122 loop {
123 let token_info = self.tokens.unwrap_next()?;
124 match token_info.token {
125 Token::Tag(
126 word @ (Word::Is
127 | Word::Contains
128 | Word::Matches
129 | Word::Value
130 | Word::Count
131 | Word::Regex),
132 ) => {
133 self.validate_argument(
134 1,
135 match word {
136 Word::Value | Word::Count => Capability::Relational.into(),
137 Word::Regex => Capability::Regex.into(),
138 Word::List => Capability::ExtLists.into(),
139 _ => None,
140 },
141 token_info.line_num,
142 token_info.line_pos,
143 )?;
144
145 match_type = self.parse_match_type(word)?;
146 }
147 Token::Tag(Word::Comparator) => {
148 self.validate_argument(2, None, token_info.line_num, token_info.line_pos)?;
149 comparator = self.parse_comparator()?;
150 }
151 _ => {
152 value = self.parse_string_token(token_info)?;
153 break;
154 }
155 }
156 }
157
158 Ok(Test::VirusTest(TestVirusTest {
159 value,
160 match_type,
161 comparator,
162 is_not: false,
163 }))
164 }
165}