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::debug;
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 modifiers: Default::default(),
57 sequence_set: self.sequence_set.clone(),
58 kind: self.kind,
59 response: StoreResponse::Answer,
60 flags: self.flags.clone(),
61 uid: self.uid,
62 }
63 }
64
65 fn process_data(&mut self, data: Data<'static>) -> Option<Data<'static>> {
66 if let Data::Fetch { items, seq } = data {
67 if let Some(items) = self.output.insert(seq, items) {
68 debug!(seq, ?items, "received duplicate items");
69 }
70
71 None
72 } else {
73 Some(data)
74 }
75 }
76
77 fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
78 match status_body.kind {
79 StatusKind::Ok => Ok(self.output),
80 StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
81 StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
82 }
83 }
84}
85
86#[derive(Clone, Debug)]
90pub struct SilentStoreTask(StoreTask);
91
92impl SilentStoreTask {
93 pub fn new(store: StoreTask) -> Self {
94 Self(store)
95 }
96}
97
98impl Task for SilentStoreTask {
99 type Output = Result<(), TaskError>;
100
101 fn command_body(&self) -> CommandBody<'static> {
102 CommandBody::Store {
103 modifiers: Default::default(),
104 sequence_set: self.0.sequence_set.clone(),
105 kind: self.0.kind,
106 response: StoreResponse::Silent,
107 flags: self.0.flags.clone(),
108 uid: self.0.uid,
109 }
110 }
111
112 fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
113 match status_body.kind {
114 StatusKind::Ok => Ok(()),
115 StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
116 StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
117 }
118 }
119}