imap_client/tasks/tasks/
store.rs1use std::{collections::HashMap, num::NonZeroU32};
2
3use imap_next::imap_types::{
4 command::CommandBody,
5 core::Vec1,
6 fetch::MessageDataItem,
7 flag::{Flag, StoreResponse, StoreType},
8 response::{Data, StatusBody, StatusKind},
9 sequence::SequenceSet,
10};
11use tracing::warn;
12
13use super::TaskError;
14use crate::tasks::Task;
15
16#[derive(Clone, Debug)]
18pub struct StoreTask {
19 sequence_set: SequenceSet,
20 kind: StoreType,
21 flags: Vec<Flag<'static>>,
22 uid: bool,
23 output: HashMap<NonZeroU32, Vec1<MessageDataItem<'static>>>,
24}
25
26impl StoreTask {
27 pub fn new(sequence_set: SequenceSet, kind: StoreType, flags: Vec<Flag<'static>>) -> Self {
28 Self {
29 sequence_set,
30 kind,
31 flags,
32 uid: true,
33 output: Default::default(),
34 }
35 }
36
37 pub fn set_uid(&mut self, uid: bool) {
38 self.uid = uid;
39 }
40
41 pub fn with_uid(mut self, uid: bool) -> Self {
42 self.set_uid(uid);
43 self
44 }
45
46 pub fn silent(self) -> SilentStoreTask {
47 SilentStoreTask::new(self)
48 }
49}
50
51impl Task for StoreTask {
52 type Output = Result<HashMap<NonZeroU32, Vec1<MessageDataItem<'static>>>, TaskError>;
53
54 fn command_body(&self) -> CommandBody<'static> {
55 CommandBody::Store {
56 sequence_set: self.sequence_set.clone(),
57 kind: self.kind,
58 response: StoreResponse::Answer,
59 flags: self.flags.clone(),
60 uid: self.uid,
61 }
62 }
63
64 fn process_data(&mut self, data: Data<'static>) -> Option<Data<'static>> {
65 if let Data::Fetch { items, seq } = data {
66 if let Some(items) = self.output.insert(seq, items) {
67 warn!(seq, ?items, "received duplicate items");
68 }
69
70 None
71 } else {
72 Some(data)
73 }
74 }
75
76 fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
77 match status_body.kind {
78 StatusKind::Ok => Ok(self.output),
79 StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
80 StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
81 }
82 }
83}
84
85#[derive(Clone, Debug)]
89pub struct SilentStoreTask(StoreTask);
90
91impl SilentStoreTask {
92 pub fn new(store: StoreTask) -> Self {
93 Self(store)
94 }
95}
96
97impl Task for SilentStoreTask {
98 type Output = Result<(), TaskError>;
99
100 fn command_body(&self) -> CommandBody<'static> {
101 CommandBody::Store {
102 sequence_set: self.0.sequence_set.clone(),
103 kind: self.0.kind,
104 response: StoreResponse::Silent,
105 flags: self.0.flags.clone(),
106 uid: self.0.uid,
107 }
108 }
109
110 fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
111 match status_body.kind {
112 StatusKind::Ok => Ok(()),
113 StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
114 StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
115 }
116 }
117}