1use std::{collections::BTreeSet, sync::Arc};
2
3#[doc(inline)]
4pub use super::{Error, Result};
5use super::{SyncDestination, SyncEventHandler};
6use crate::{
7 backend::{
8 context::{BackendContext, BackendContextBuilder},
9 Backend, BackendBuilder,
10 },
11 email::sync::hunk::EmailSyncHunk,
12 envelope::sync::config::EnvelopeSyncFilters,
13 flag::sync::config::FlagSyncPermissions,
14 folder::sync::{
15 config::{FolderSyncPermissions, FolderSyncStrategy},
16 hunk::FolderSyncHunk,
17 patch::FolderSyncPatches,
18 },
19 maildir::{MaildirContextBuilder, MaildirContextSync},
20 message::sync::config::MessageSyncPermissions,
21 AnyResult,
22};
23
24#[derive(Clone, Default)]
25pub struct SyncPoolConfig {
26 pub left_folder_permissions: Option<FolderSyncPermissions>,
27 pub left_flag_permissions: Option<FlagSyncPermissions>,
28 pub left_message_permissions: Option<MessageSyncPermissions>,
29 pub right_folder_permissions: Option<FolderSyncPermissions>,
30 pub right_flag_permissions: Option<FlagSyncPermissions>,
31 pub right_message_permissions: Option<MessageSyncPermissions>,
32 pub pool_size: Option<usize>,
33 pub folder_filters: Option<FolderSyncStrategy>,
34 pub envelope_filters: Option<EnvelopeSyncFilters>,
35 pub handler: Option<Arc<SyncEventHandler>>,
36 pub dry_run: Option<bool>,
37}
38
39#[derive(Clone)]
40pub struct SyncPoolContextBuilder<L, R>
41where
42 L: BackendContextBuilder,
43 R: BackendContextBuilder,
44{
45 config: SyncPoolConfig,
46 left_cache_builder: BackendBuilder<MaildirContextBuilder>,
47 left_builder: BackendBuilder<L>,
48 right_cache_builder: BackendBuilder<MaildirContextBuilder>,
49 right_builder: BackendBuilder<R>,
50}
51
52impl<L, R> SyncPoolContextBuilder<L, R>
53where
54 L: BackendContextBuilder,
55 R: BackendContextBuilder,
56{
57 pub fn new(
58 config: SyncPoolConfig,
59 left_cache_builder: BackendBuilder<MaildirContextBuilder>,
60 left_builder: BackendBuilder<L>,
61 right_cache_builder: BackendBuilder<MaildirContextBuilder>,
62 right_builder: BackendBuilder<R>,
63 ) -> Self {
64 Self {
65 config,
66 left_cache_builder,
67 left_builder,
68 right_cache_builder,
69 right_builder,
70 }
71 }
72
73 pub async fn build(self) -> AnyResult<SyncPoolContext<L::Context, R::Context>> {
74 let left_folder_permissions = self
75 .config
76 .left_folder_permissions
77 .clone()
78 .or_else(|| {
79 self.left_builder
80 .account_config
81 .folder
82 .as_ref()
83 .and_then(|c| c.sync.as_ref())
84 .map(|c| c.permissions.clone())
85 })
86 .unwrap_or_default();
87
88 let left_flag_permissions = self
89 .config
90 .left_flag_permissions
91 .clone()
92 .or_else(|| {
93 self.left_builder
94 .account_config
95 .flag
96 .as_ref()
97 .and_then(|c| c.sync.as_ref())
98 .map(|c| c.permissions.clone())
99 })
100 .unwrap_or_default();
101
102 let left_message_permissions = self
103 .config
104 .left_message_permissions
105 .clone()
106 .or_else(|| {
107 self.left_builder
108 .account_config
109 .message
110 .as_ref()
111 .and_then(|c| c.sync.as_ref())
112 .map(|c| c.permissions.clone())
113 })
114 .unwrap_or_default();
115
116 let right_folder_permissions = self
117 .config
118 .right_folder_permissions
119 .clone()
120 .or_else(|| {
121 self.right_builder
122 .account_config
123 .folder
124 .as_ref()
125 .and_then(|c| c.sync.as_ref())
126 .map(|c| c.permissions.clone())
127 })
128 .unwrap_or_default();
129
130 let right_flag_permissions = self
131 .config
132 .right_flag_permissions
133 .clone()
134 .or_else(|| {
135 self.right_builder
136 .account_config
137 .flag
138 .as_ref()
139 .and_then(|c| c.sync.as_ref())
140 .map(|c| c.permissions.clone())
141 })
142 .unwrap_or_default();
143
144 let right_message_permissions = self
145 .config
146 .right_message_permissions
147 .clone()
148 .or_else(|| {
149 self.right_builder
150 .account_config
151 .message
152 .as_ref()
153 .and_then(|c| c.sync.as_ref())
154 .map(|c| c.permissions.clone())
155 })
156 .unwrap_or_default();
157
158 let folder_filters = self
159 .config
160 .folder_filters
161 .clone()
162 .or_else(|| {
163 self.right_builder
164 .account_config
165 .folder
166 .as_ref()
167 .and_then(|c| c.sync.as_ref())
168 .map(|c| c.filter.clone())
169 })
170 .unwrap_or_default();
171
172 let envelope_filters = self
173 .config
174 .envelope_filters
175 .clone()
176 .or_else(|| {
177 self.right_builder
178 .account_config
179 .envelope
180 .as_ref()
181 .and_then(|c| c.sync.as_ref())
182 .map(|c| c.filter.clone())
183 })
184 .unwrap_or_default();
185
186 let (left_cache, left, right_cache, right) = tokio::try_join!(
187 self.left_cache_builder.build(),
188 self.left_builder.build(),
189 self.right_cache_builder.build(),
190 self.right_builder.build(),
191 )?;
192
193 Ok(SyncPoolContext {
194 left_cache,
195 left,
196 left_folder_permissions,
197 left_flag_permissions,
198 left_message_permissions,
199 right_cache,
200 right,
201 right_folder_permissions,
202 right_flag_permissions,
203 right_message_permissions,
204 folder_filters,
205 envelope_filters,
206 handler: self.config.handler,
207 dry_run: self.config.dry_run.unwrap_or_default(),
208 })
209 }
210}
211
212pub struct SyncPoolContext<L: BackendContext, R: BackendContext> {
213 pub left_cache: Backend<MaildirContextSync>,
214 pub left: Backend<L>,
215 pub right_cache: Backend<MaildirContextSync>,
216 pub right: Backend<R>,
217 pub left_folder_permissions: FolderSyncPermissions,
218 pub left_flag_permissions: FlagSyncPermissions,
219 pub left_message_permissions: MessageSyncPermissions,
220 pub right_folder_permissions: FolderSyncPermissions,
221 pub right_flag_permissions: FlagSyncPermissions,
222 pub right_message_permissions: MessageSyncPermissions,
223 pub folder_filters: FolderSyncStrategy,
224 pub envelope_filters: EnvelopeSyncFilters,
225 pub handler: Option<Arc<SyncEventHandler>>,
226 pub dry_run: bool,
227}
228
229impl<L: BackendContext, R: BackendContext> SyncPoolContext<L, R> {
230 pub fn apply_folder_permissions(&self, patch: &mut FolderSyncPatches) {
231 use FolderSyncHunk::*;
232 use SyncDestination::*;
233
234 for (_, patch) in patch.iter_mut() {
235 patch.retain(|hunk| match hunk {
236 Create(_, Left) | Cache(_, Left) => self.left_folder_permissions.create,
237 Create(_, Right) | Cache(_, Right) => self.right_folder_permissions.create,
238 Delete(_, Left) | Uncache(_, Left) => self.left_folder_permissions.delete,
239 Delete(_, Right) | Uncache(_, Right) => self.right_folder_permissions.delete,
240 });
241 }
242 }
243
244 pub fn apply_flag_and_message_permissions(&self, patch: &mut BTreeSet<EmailSyncHunk>) {
245 use EmailSyncHunk::*;
246 use SyncDestination::*;
247
248 patch.retain(|hunk| match hunk {
249 GetThenCache(_, _, Left) => self.left_message_permissions.create,
250 GetThenCache(_, _, Right) => self.right_message_permissions.create,
251 CopyThenCache(_, _, _, Left, _) => self.left_message_permissions.create,
252 CopyThenCache(_, _, _, Right, _) => self.right_message_permissions.create,
253 UpdateCachedFlags(_, _, Left) => self.left_flag_permissions.update,
254 UpdateCachedFlags(_, _, Right) => self.right_flag_permissions.update,
255 UpdateFlags(_, _, Left) => self.left_flag_permissions.update,
256 UpdateFlags(_, _, Right) => self.right_flag_permissions.update,
257 Uncache(_, _, Left) | Delete(_, _, Left) => self.left_message_permissions.delete,
258 Uncache(_, _, Right) | Delete(_, _, Right) => self.right_message_permissions.delete,
259 });
260 }
261}