1use std::{convert::TryFrom, path::Path};
23
24use super::*;
25use crate::{
26 backends::MailboxHash,
27 email::{Envelope, EnvelopeHash},
28 error::*,
29};
30
31#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
32pub struct ModSequence(pub std::num::NonZeroU64);
33
34impl TryFrom<i64> for ModSequence {
35 type Error = ();
36 fn try_from(val: i64) -> std::result::Result<Self, ()> {
37 std::num::NonZeroU64::new(val as u64)
38 .map(|u| Ok(Self(u)))
39 .unwrap_or(Err(()))
40 }
41}
42
43impl std::fmt::Display for ModSequence {
44 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
45 write!(fmt, "{}", &self.0)
46 }
47}
48
49#[derive(Debug)]
50pub struct CachedEnvelope {
51 pub inner: Envelope,
52 pub uid: UID,
53 pub mailbox_hash: MailboxHash,
54 pub modsequence: Option<ModSequence>,
55}
56
57#[derive(Clone, Copy, Debug)]
58pub struct CachedState {
59 pub uidvalidity: UID,
60 pub highestmodseq: Option<ModSequence>,
61}
62
63pub fn ignore_not_found(err: Error) -> Result<()> {
66 if matches!(err.kind, ErrorKind::NotFound) {
67 return Ok(());
68 }
69 Err(err)
70}
71
72pub trait ImapCache: Send + std::fmt::Debug {
73 fn reset(&mut self) -> Result<()>;
74 fn mailbox_state(&mut self, mailbox_hash: MailboxHash) -> Result<Option<CachedState>>;
75
76 fn max_uid(&mut self, mailbox_hash: MailboxHash) -> Result<Option<UID>>;
77
78 fn find_envelope(
79 &mut self,
80 identifier: std::result::Result<UID, EnvelopeHash>,
81 mailbox_hash: MailboxHash,
82 ) -> Result<Option<CachedEnvelope>>;
83
84 fn update(
85 &mut self,
86 mailbox_hash: MailboxHash,
87 refresh_events: &[(UID, RefreshEvent)],
88 ) -> Result<()>;
89
90 fn update_mailbox(
91 &mut self,
92 mailbox_hash: MailboxHash,
93 select_response: &SelectResponse,
94 ) -> Result<()>;
95
96 fn insert_envelopes(
97 &mut self,
98 mailbox_hash: MailboxHash,
99 fetches: &[FetchResponse<'_>],
100 ) -> Result<()>;
101
102 fn envelopes(
103 &mut self,
104 mailbox_hash: MailboxHash,
105 max_uid: UID,
106 batch_size: usize,
107 ) -> Result<Option<Vec<EnvelopeHash>>>;
108
109 fn init_mailbox(
110 &mut self,
111 mailbox_hash: MailboxHash,
112 select_response: &SelectResponse,
113 ) -> Result<()>;
114
115 fn rfc822(
116 &mut self,
117 identifier: std::result::Result<UID, EnvelopeHash>,
118 mailbox_hash: MailboxHash,
119 ) -> Result<Option<Vec<u8>>>;
120
121 fn update_flags(
122 &mut self,
123 env_hashes: EnvelopeHashBatch,
124 mailbox_hash: MailboxHash,
125 flags: SmallVec<[FlagOp; 8]>,
126 ) -> Result<()>;
127}
128
129pub trait ImapCacheReset: Send + std::fmt::Debug {
130 fn reset_db(uid_store: &UIDStore, data_dir: Option<&Path>) -> Result<()>
131 where
132 Self: Sized;
133}
134
135impl ImapCache for Arc<UIDStore> {
136 fn reset(&mut self) -> Result<()> {
137 if !self.keep_offline_cache.load(Ordering::SeqCst) {
138 return Ok(());
139 }
140 #[cfg(feature = "sqlite3")]
141 {
142 sync::sqlite3_cache::Sqlite3Cache::reset_db(self, None)?;
143 }
144 Ok(())
145 }
146
147 fn mailbox_state(&mut self, mailbox_hash: MailboxHash) -> Result<Option<CachedState>> {
148 if !self.keep_offline_cache.load(Ordering::SeqCst) {
149 return Ok(None);
150 }
151 let mut mutex = self.offline_cache.lock().unwrap();
152 self.init_cache(&mut mutex)?;
153
154 if let Some(ref mut cache_handle) = *mutex {
155 return cache_handle.mailbox_state(mailbox_hash);
156 }
157 Ok(None)
158 }
159
160 fn max_uid(&mut self, mailbox_hash: MailboxHash) -> Result<Option<UID>> {
161 if !self.keep_offline_cache.load(Ordering::SeqCst) {
162 return Ok(None);
163 }
164 let mut mutex = self.offline_cache.lock().unwrap();
165 self.init_cache(&mut mutex)?;
166
167 if let Some(ref mut cache_handle) = *mutex {
168 return cache_handle.max_uid(mailbox_hash);
169 }
170 Ok(None)
171 }
172
173 fn find_envelope(
174 &mut self,
175 identifier: std::result::Result<UID, EnvelopeHash>,
176 mailbox_hash: MailboxHash,
177 ) -> Result<Option<CachedEnvelope>> {
178 if !self.keep_offline_cache.load(Ordering::SeqCst) {
179 return Ok(None);
180 }
181 let mut mutex = self.offline_cache.lock().unwrap();
182 self.init_cache(&mut mutex)?;
183
184 if let Some(ref mut cache_handle) = *mutex {
185 return cache_handle.find_envelope(identifier, mailbox_hash);
186 }
187 Ok(None)
188 }
189
190 fn update(
191 &mut self,
192 mailbox_hash: MailboxHash,
193 refresh_events: &[(UID, RefreshEvent)],
194 ) -> Result<()> {
195 if !self.keep_offline_cache.load(Ordering::SeqCst) {
196 return Ok(());
197 }
198 let mut mutex = self.offline_cache.lock().unwrap();
199 self.init_cache(&mut mutex)?;
200
201 if let Some(ref mut cache_handle) = *mutex {
202 return cache_handle.update(mailbox_hash, refresh_events);
203 }
204 Ok(())
205 }
206
207 fn update_mailbox(
208 &mut self,
209 mailbox_hash: MailboxHash,
210 select_response: &SelectResponse,
211 ) -> Result<()> {
212 if !self.keep_offline_cache.load(Ordering::SeqCst) {
213 return Ok(());
214 }
215 let mut mutex = self.offline_cache.lock().unwrap();
216 self.init_cache(&mut mutex)?;
217
218 if let Some(ref mut cache_handle) = *mutex {
219 return cache_handle.update_mailbox(mailbox_hash, select_response);
220 }
221 Ok(())
222 }
223
224 fn insert_envelopes(
225 &mut self,
226 mailbox_hash: MailboxHash,
227 fetches: &[FetchResponse<'_>],
228 ) -> Result<()> {
229 if !self.keep_offline_cache.load(Ordering::SeqCst) {
230 return Ok(());
231 }
232 let mut mutex = self.offline_cache.lock().unwrap();
233 self.init_cache(&mut mutex)?;
234
235 if let Some(ref mut cache_handle) = *mutex {
236 return cache_handle.insert_envelopes(mailbox_hash, fetches);
237 }
238 Ok(())
239 }
240
241 fn envelopes(
242 &mut self,
243 mailbox_hash: MailboxHash,
244 max_uid: UID,
245 batch_size: usize,
246 ) -> Result<Option<Vec<EnvelopeHash>>> {
247 if !self.keep_offline_cache.load(Ordering::SeqCst) {
248 return Ok(None);
249 }
250 let mut mutex = self.offline_cache.lock().unwrap();
251 self.init_cache(&mut mutex)?;
252
253 if let Some(ref mut cache_handle) = *mutex {
254 return cache_handle.envelopes(mailbox_hash, max_uid, batch_size);
255 }
256 Ok(None)
257 }
258
259 fn init_mailbox(
260 &mut self,
261 mailbox_hash: MailboxHash,
262 select_response: &SelectResponse,
263 ) -> Result<()> {
264 if !self.keep_offline_cache.load(Ordering::SeqCst) {
265 return Ok(());
266 }
267 let mut mutex = self.offline_cache.lock().unwrap();
268 self.init_cache(&mut mutex)?;
269
270 if let Some(ref mut cache_handle) = *mutex {
271 return cache_handle.init_mailbox(mailbox_hash, select_response);
272 }
273 Ok(())
274 }
275
276 fn rfc822(
277 &mut self,
278 identifier: std::result::Result<UID, EnvelopeHash>,
279 mailbox_hash: MailboxHash,
280 ) -> Result<Option<Vec<u8>>> {
281 if !self.keep_offline_cache.load(Ordering::SeqCst) {
282 return Ok(None);
283 }
284 let mut mutex = self.offline_cache.lock().unwrap();
285 self.init_cache(&mut mutex)?;
286
287 if let Some(ref mut cache_handle) = *mutex {
288 return cache_handle.rfc822(identifier, mailbox_hash);
289 }
290 Ok(None)
291 }
292
293 fn update_flags(
294 &mut self,
295 env_hashes: EnvelopeHashBatch,
296 mailbox_hash: MailboxHash,
297 flags: SmallVec<[FlagOp; 8]>,
298 ) -> Result<()> {
299 if !self.keep_offline_cache.load(Ordering::SeqCst) {
300 return Ok(());
301 }
302 let mut mutex = self.offline_cache.lock().unwrap();
303 self.init_cache(&mut mutex)?;
304
305 if let Some(ref mut cache_handle) = *mutex {
306 return cache_handle.update_flags(env_hashes, mailbox_hash, flags);
307 }
308 Ok(())
309 }
310}