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