1use crate::Error;
13use ahash::AHashMap;
14use chrono::{DateTime, Utc};
15use serde::{Deserialize, Serialize};
16use std::fmt::{self, Display, Formatter};
17
18use super::{request::ResultReference, Object, RequestParams};
19
20pub trait SetObject: Object {
21 type SetArguments: Default;
22
23 fn new(create_id: Option<usize>) -> Self;
24 fn create_id(&self) -> Option<String>;
25}
26
27#[derive(Debug, Clone, Serialize)]
28pub struct SetRequest<O: SetObject> {
29 #[serde(rename = "accountId")]
30 #[serde(skip_serializing_if = "Option::is_none")]
31 account_id: Option<String>,
32
33 #[serde(rename = "ifInState")]
34 #[serde(skip_serializing_if = "Option::is_none")]
35 if_in_state: Option<String>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
38 create: Option<AHashMap<String, O>>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
41 update: Option<AHashMap<String, O>>,
42
43 #[serde(skip_serializing_if = "Option::is_none")]
44 destroy: Option<Vec<String>>,
45
46 #[serde(rename = "#destroy")]
47 #[serde(skip_deserializing)]
48 #[serde(skip_serializing_if = "Option::is_none")]
49 destroy_ref: Option<ResultReference>,
50
51 #[serde(flatten)]
52 arguments: O::SetArguments,
53}
54
55#[derive(Debug, Clone, Deserialize)]
56pub struct SetResponse<O: SetObject> {
57 #[serde(rename = "accountId")]
58 account_id: Option<String>,
59
60 #[serde(rename = "oldState")]
61 old_state: Option<String>,
62
63 #[serde(rename = "newState")]
64 new_state: Option<String>,
65
66 #[serde(rename = "created")]
67 created: Option<AHashMap<String, O>>,
68
69 #[serde(rename = "updated")]
70 updated: Option<AHashMap<String, Option<O>>>,
71
72 #[serde(rename = "destroyed")]
73 destroyed: Option<Vec<String>>,
74
75 #[serde(rename = "notCreated")]
76 not_created: Option<AHashMap<String, SetError<O::Property>>>,
77
78 #[serde(rename = "notUpdated")]
79 not_updated: Option<AHashMap<String, SetError<O::Property>>>,
80
81 #[serde(rename = "notDestroyed")]
82 not_destroyed: Option<AHashMap<String, SetError<O::Property>>>,
83}
84
85#[derive(Debug, Clone, Deserialize)]
86pub struct SetError<U>
87where
88 U: Display,
89{
90 #[serde(rename = "type")]
91 pub type_: SetErrorType,
92 description: Option<String>,
93 properties: Option<Vec<U>>,
94}
95
96#[derive(Debug, Clone, Deserialize, Eq, PartialEq)]
97pub enum SetErrorType {
98 #[serde(rename = "forbidden")]
99 Forbidden,
100 #[serde(rename = "overQuota")]
101 OverQuota,
102 #[serde(rename = "tooLarge")]
103 TooLarge,
104 #[serde(rename = "rateLimit")]
105 RateLimit,
106 #[serde(rename = "notFound")]
107 NotFound,
108 #[serde(rename = "invalidPatch")]
109 InvalidPatch,
110 #[serde(rename = "willDestroy")]
111 WillDestroy,
112 #[serde(rename = "invalidProperties")]
113 InvalidProperties,
114 #[serde(rename = "singleton")]
115 Singleton,
116 #[serde(rename = "mailboxHasChild")]
117 MailboxHasChild,
118 #[serde(rename = "mailboxHasEmail")]
119 MailboxHasEmail,
120 #[serde(rename = "blobNotFound")]
121 BlobNotFound,
122 #[serde(rename = "tooManyKeywords")]
123 TooManyKeywords,
124 #[serde(rename = "tooManyMailboxes")]
125 TooManyMailboxes,
126 #[serde(rename = "forbiddenFrom")]
127 ForbiddenFrom,
128 #[serde(rename = "invalidEmail")]
129 InvalidEmail,
130 #[serde(rename = "tooManyRecipients")]
131 TooManyRecipients,
132 #[serde(rename = "noRecipients")]
133 NoRecipients,
134 #[serde(rename = "invalidRecipients")]
135 InvalidRecipients,
136 #[serde(rename = "forbiddenMailFrom")]
137 ForbiddenMailFrom,
138 #[serde(rename = "forbiddenToSend")]
139 ForbiddenToSend,
140 #[serde(rename = "cannotUnsend")]
141 CannotUnsend,
142 #[serde(rename = "alreadyExists")]
143 AlreadyExists,
144 #[serde(rename = "invalidScript")]
145 InvalidScript,
146 #[serde(rename = "scriptIsActive")]
147 ScriptIsActive,
148}
149
150impl<O: SetObject> SetRequest<O> {
151 pub fn new(params: RequestParams) -> Self {
152 Self {
153 account_id: if O::requires_account_id() {
154 params.account_id.into()
155 } else {
156 None
157 },
158 if_in_state: None,
159 create: None,
160 update: None,
161 destroy: None,
162 destroy_ref: None,
163 arguments: Default::default(),
164 }
165 }
166
167 pub fn account_id(&mut self, account_id: impl Into<String>) -> &mut Self {
168 if O::requires_account_id() {
169 self.account_id = Some(account_id.into());
170 }
171 self
172 }
173
174 pub fn if_in_state(&mut self, if_in_state: impl Into<String>) -> &mut Self {
175 self.if_in_state = Some(if_in_state.into());
176 self
177 }
178
179 pub fn create(&mut self) -> &mut O {
180 let create_id = self.create.as_ref().map_or(0, |c| c.len());
181 let create_id_str = format!("c{}", create_id);
182 self.create
183 .get_or_insert_with(AHashMap::new)
184 .insert(create_id_str.clone(), O::new(create_id.into()));
185 self.create
186 .as_mut()
187 .unwrap()
188 .get_mut(&create_id_str)
189 .unwrap()
190 }
191
192 pub fn create_with_id(&mut self, create_id: impl Into<String>) -> &mut O {
193 let create_id = create_id.into();
194 self.create
195 .get_or_insert_with(AHashMap::new)
196 .insert(create_id.clone(), O::new(0.into()));
197 self.create.as_mut().unwrap().get_mut(&create_id).unwrap()
198 }
199
200 pub fn create_item(&mut self, item: O) -> String {
201 let create_id = self.create.as_ref().map_or(0, |c| c.len());
202 let create_id_str = format!("c{}", create_id);
203 self.create
204 .get_or_insert_with(AHashMap::new)
205 .insert(create_id_str.clone(), item);
206 create_id_str
207 }
208
209 pub fn update(&mut self, id: impl Into<String>) -> &mut O {
210 let id: String = id.into();
211 self.update
212 .get_or_insert_with(AHashMap::new)
213 .insert(id.clone(), O::new(None));
214 self.update.as_mut().unwrap().get_mut(&id).unwrap()
215 }
216
217 pub fn update_item(&mut self, id: impl Into<String>, item: O) {
218 self.update
219 .get_or_insert_with(AHashMap::new)
220 .insert(id.into(), item);
221 }
222
223 pub fn destroy<U, V>(&mut self, ids: U) -> &mut Self
224 where
225 U: IntoIterator<Item = V>,
226 V: Into<String>,
227 {
228 self.destroy
229 .get_or_insert_with(Vec::new)
230 .extend(ids.into_iter().map(|id| id.into()));
231 self.destroy_ref = None;
232 self
233 }
234
235 pub fn destroy_ref(&mut self, reference: ResultReference) -> &mut Self {
236 self.destroy_ref = reference.into();
237 self.destroy = None;
238 self
239 }
240
241 pub fn arguments(&mut self) -> &mut O::SetArguments {
242 &mut self.arguments
243 }
244}
245
246impl<O: SetObject> SetResponse<O> {
247 pub fn account_id(&self) -> Option<&str> {
248 self.account_id.as_deref()
249 }
250
251 pub fn old_state(&self) -> Option<&str> {
252 self.old_state.as_deref()
253 }
254
255 pub fn new_state(&self) -> &str {
256 self.new_state.as_deref().unwrap_or("")
257 }
258
259 pub fn take_new_state(&mut self) -> String {
260 self.new_state.take().unwrap_or_default()
261 }
262
263 pub fn created(&mut self, id: &str) -> crate::Result<O> {
264 if let Some(result) = self.created.as_mut().and_then(|r| r.remove(id)) {
265 Ok(result)
266 } else if let Some(error) = self.not_created.as_mut().and_then(|r| r.remove(id)) {
267 Err(error.to_string_error().into())
268 } else {
269 Err(Error::Internal(format!("Id {} not found.", id)))
270 }
271 }
272
273 pub fn updated(&mut self, id: &str) -> crate::Result<Option<O>> {
274 if let Some(result) = self.updated.as_mut().and_then(|r| r.remove(id)) {
275 Ok(result)
276 } else if let Some(error) = self.not_updated.as_mut().and_then(|r| r.remove(id)) {
277 Err(error.to_string_error().into())
278 } else {
279 Err(Error::Internal(format!("Id {} not found.", id)))
280 }
281 }
282
283 pub fn destroyed(&mut self, id: &str) -> crate::Result<()> {
284 if self
285 .destroyed
286 .as_ref()
287 .map_or(false, |r| r.iter().any(|i| i == id))
288 {
289 Ok(())
290 } else if let Some(error) = self.not_destroyed.as_mut().and_then(|r| r.remove(id)) {
291 Err(error.to_string_error().into())
292 } else {
293 Err(Error::Internal(format!("Id {} not found.", id)))
294 }
295 }
296
297 pub fn created_ids(&self) -> Option<impl Iterator<Item = &String>> {
298 self.created.as_ref().map(|map| map.keys())
299 }
300
301 pub fn updated_ids(&self) -> Option<impl Iterator<Item = &String>> {
302 self.updated.as_ref().map(|map| map.keys())
303 }
304
305 pub fn take_updated_ids(&mut self) -> Option<Vec<String>> {
306 self.updated
307 .take()
308 .map(|map| map.into_iter().map(|(k, _)| k).collect())
309 }
310
311 pub fn destroyed_ids(&self) -> Option<impl Iterator<Item = &String>> {
312 self.destroyed.as_ref().map(|list| list.iter())
313 }
314
315 pub fn take_destroyed_ids(&mut self) -> Option<Vec<String>> {
316 self.destroyed.take()
317 }
318
319 pub fn not_created_ids(&self) -> Option<impl Iterator<Item = &String>> {
320 self.not_created.as_ref().map(|map| map.keys())
321 }
322
323 pub fn not_updated_ids(&self) -> Option<impl Iterator<Item = &String>> {
324 self.not_updated.as_ref().map(|map| map.keys())
325 }
326
327 pub fn not_destroyed_ids(&self) -> Option<impl Iterator<Item = &String>> {
328 self.not_destroyed.as_ref().map(|map| map.keys())
329 }
330
331 pub fn has_updated(&self) -> bool {
332 self.updated.as_ref().map_or(false, |m| !m.is_empty())
333 }
334
335 pub fn has_created(&self) -> bool {
336 self.created.as_ref().map_or(false, |m| !m.is_empty())
337 }
338
339 pub fn has_destroyed(&self) -> bool {
340 self.destroyed.as_ref().map_or(false, |m| !m.is_empty())
341 }
342
343 pub fn unwrap_update_errors(&self) -> crate::Result<()> {
344 if let Some(errors) = &self.not_updated {
345 if let Some(err) = errors.values().next() {
346 return Err(err.to_string_error().into());
347 }
348 }
349 Ok(())
350 }
351
352 pub fn unwrap_create_errors(&self) -> crate::Result<()> {
353 if let Some(errors) = &self.not_created {
354 if let Some(err) = errors.values().next() {
355 return Err(err.to_string_error().into());
356 }
357 }
358 Ok(())
359 }
360}
361
362impl<U: Display> SetError<U> {
363 pub fn error(&self) -> &SetErrorType {
364 &self.type_
365 }
366
367 pub fn description(&self) -> Option<&str> {
368 self.description.as_deref()
369 }
370
371 pub fn properties(&self) -> Option<&[U]> {
372 self.properties.as_deref()
373 }
374
375 pub fn to_string_error(&self) -> SetError<String> {
376 SetError {
377 type_: self.type_.clone(),
378 description: self.description.as_ref().map(|s| s.to_string()),
379 properties: self
380 .properties
381 .as_ref()
382 .map(|s| s.iter().map(|s| s.to_string()).collect()),
383 }
384 }
385}
386
387impl<U: Display> Display for SetError<U> {
388 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
389 self.type_.fmt(f)?;
390 if let Some(description) = &self.description {
391 write!(f, ": {}", description)?;
392 }
393 if let Some(properties) = &self.properties {
394 write!(
395 f,
396 " (properties: {})",
397 properties
398 .iter()
399 .map(|v| v.to_string())
400 .collect::<Vec<String>>()
401 .join(", ")
402 )?;
403 }
404 Ok(())
405 }
406}
407
408impl Display for SetErrorType {
409 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
410 match self {
411 SetErrorType::Forbidden => write!(f, "forbidden"),
412 SetErrorType::OverQuota => write!(f, "overQuota"),
413 SetErrorType::TooLarge => write!(f, "tooLarge"),
414 SetErrorType::RateLimit => write!(f, "rateLimit"),
415 SetErrorType::NotFound => write!(f, "notFound"),
416 SetErrorType::InvalidPatch => write!(f, "invalidPatch"),
417 SetErrorType::WillDestroy => write!(f, "willDestroy"),
418 SetErrorType::InvalidProperties => write!(f, "invalidProperties"),
419 SetErrorType::Singleton => write!(f, "singleton"),
420 SetErrorType::MailboxHasChild => write!(f, "mailboxHasChild"),
421 SetErrorType::MailboxHasEmail => write!(f, "mailboxHasEmail"),
422 SetErrorType::BlobNotFound => write!(f, "blobNotFound"),
423 SetErrorType::TooManyKeywords => write!(f, "tooManyKeywords"),
424 SetErrorType::TooManyMailboxes => write!(f, "tooManyMailboxes"),
425 SetErrorType::ForbiddenFrom => write!(f, "forbiddenFrom"),
426 SetErrorType::InvalidEmail => write!(f, "invalidEmail"),
427 SetErrorType::TooManyRecipients => write!(f, "tooManyRecipients"),
428 SetErrorType::NoRecipients => write!(f, "noRecipients"),
429 SetErrorType::InvalidRecipients => write!(f, "invalidRecipients"),
430 SetErrorType::ForbiddenMailFrom => write!(f, "forbiddenMailFrom"),
431 SetErrorType::ForbiddenToSend => write!(f, "forbiddenToSend"),
432 SetErrorType::CannotUnsend => write!(f, "cannotUnsend"),
433 SetErrorType::AlreadyExists => write!(f, "alreadyExists"),
434 SetErrorType::InvalidScript => write!(f, "invalidScript"),
435 SetErrorType::ScriptIsActive => write!(f, "scriptIsActive"),
436 }
437 }
438}
439
440pub fn from_timestamp(timestamp: i64) -> DateTime<Utc> {
441 DateTime::from_timestamp(timestamp, 0).unwrap_or_default()
442}
443
444pub fn string_not_set(string: &Option<String>) -> bool {
445 matches!(string, Some(string) if string.is_empty())
446}
447
448pub fn date_not_set(date: &Option<DateTime<Utc>>) -> bool {
449 matches!(date, Some(date) if date.timestamp() == 0)
450}
451
452pub fn list_not_set<O>(list: &Option<Vec<O>>) -> bool {
453 matches!(list, Some(list) if list.is_empty() )
454}
455
456pub fn map_not_set<K, V>(list: &Option<AHashMap<K, V>>) -> bool {
457 matches!(list, Some(list) if list.is_empty() )
458}