sieve/compiler/grammar/actions/action_fileinto.rs
1/*
2 * Copyright (c) 2020-2023, Stalwart Labs Ltd.
3 *
4 * This file is part of the Stalwart Sieve Interpreter.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 * in the LICENSE file at the top-level directory of this distribution.
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * You can be released from the requirements of the AGPLv3 license by
20 * purchasing a commercial license. Please contact licensing@stalw.art
21 * for more details.
22*/
23
24use serde::{Deserialize, Serialize};
25
26use crate::compiler::{
27 grammar::{
28 instruction::{CompilerState, Instruction},
29 Capability,
30 },
31 lexer::{word::Word, Token},
32 CompileError, Value,
33};
34
35#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36pub struct FileInto {
37 pub copy: bool,
38 pub create: bool,
39 pub folder: Value,
40 pub flags: Vec<Value>,
41 pub mailbox_id: Option<Value>,
42 pub special_use: Option<Value>,
43}
44
45impl<'x> CompilerState<'x> {
46 pub(crate) fn parse_fileinto(&mut self) -> Result<(), CompileError> {
47 let folder;
48 let mut copy = false;
49 let mut create = false;
50 let mut flags = Vec::new();
51 let mut mailbox_id = None;
52 let mut special_use = None;
53
54 loop {
55 let token_info = self.tokens.unwrap_next()?;
56 match token_info.token {
57 Token::Tag(Word::Copy) => {
58 self.validate_argument(
59 1,
60 Capability::Copy.into(),
61 token_info.line_num,
62 token_info.line_pos,
63 )?;
64 copy = true;
65 }
66 Token::Tag(Word::Create) => {
67 self.validate_argument(
68 2,
69 Capability::Mailbox.into(),
70 token_info.line_num,
71 token_info.line_pos,
72 )?;
73 create = true;
74 }
75 Token::Tag(Word::Flags) => {
76 self.validate_argument(
77 3,
78 Capability::Imap4Flags.into(),
79 token_info.line_num,
80 token_info.line_pos,
81 )?;
82 flags = self.parse_strings(false)?;
83 }
84 Token::Tag(Word::MailboxId) => {
85 self.validate_argument(
86 4,
87 Capability::Mailbox.into(),
88 token_info.line_num,
89 token_info.line_pos,
90 )?;
91 mailbox_id = self.parse_string()?.into();
92 }
93 Token::Tag(Word::SpecialUse) => {
94 self.validate_argument(
95 5,
96 Capability::SpecialUse.into(),
97 token_info.line_num,
98 token_info.line_pos,
99 )?;
100 special_use = self.parse_string()?.into();
101 }
102 _ => {
103 folder = self.parse_string_token(token_info)?;
104 break;
105 }
106 }
107 }
108
109 self.instructions.push(Instruction::FileInto(FileInto {
110 folder,
111 copy,
112 create,
113 flags,
114 mailbox_id,
115 special_use,
116 }));
117 Ok(())
118 }
119}