1use std::sync::RwLock;
36
37use async_trait::async_trait;
38
39use crate::store::{AddressBookStore, CalendarStore, StoreError};
40use crate::types::{AddressBook, Calendar, Contact, Event, PutResult};
41use crate::xml::etag_of;
42
43pub const EXAMPLE_USER: &str = "alice@example.com";
46
47pub struct InMemoryCalendarStore {
54 inner: RwLock<CalInner>,
55}
56
57struct CalInner {
58 calendars: Vec<(String, Calendar)>, events: Vec<(i64, Event)>, default_created_for: Vec<String>, list_calendars_error: Option<String>,
63 get_calendar_error: Option<String>,
64 list_events_error: Option<String>,
65 get_event_error: Option<String>,
66 event_etag_error: Option<String>,
67 put_event_error: Option<String>,
68 delete_event_error: Option<String>,
69 ensure_default_error: Option<String>,
70}
71
72impl InMemoryCalendarStore {
73 pub fn new() -> Self {
75 Self {
76 inner: RwLock::new(CalInner {
77 calendars: Vec::new(),
78 events: Vec::new(),
79 default_created_for: Vec::new(),
80 list_calendars_error: None,
81 get_calendar_error: None,
82 list_events_error: None,
83 get_event_error: None,
84 event_etag_error: None,
85 put_event_error: None,
86 delete_event_error: None,
87 ensure_default_error: None,
88 }),
89 }
90 }
91
92 pub fn with_calendar(self, owner: &str, cal: Calendar) -> Self {
94 self.inner
95 .write()
96 .unwrap()
97 .calendars
98 .push((owner.to_string(), cal));
99 self
100 }
101
102 pub fn with_event(self, calendar_id: i64, event: Event) -> Self {
104 self.inner.write().unwrap().events.push((calendar_id, event));
105 self
106 }
107
108 pub fn list_calendars_fails(self, msg: &str) -> Self {
110 self.inner.write().unwrap().list_calendars_error = Some(msg.to_string());
111 self
112 }
113
114 pub fn get_calendar_fails(self, msg: &str) -> Self {
116 self.inner.write().unwrap().get_calendar_error = Some(msg.to_string());
117 self
118 }
119
120 pub fn list_events_fails(self, msg: &str) -> Self {
122 self.inner.write().unwrap().list_events_error = Some(msg.to_string());
123 self
124 }
125
126 pub fn get_event_fails(self, msg: &str) -> Self {
128 self.inner.write().unwrap().get_event_error = Some(msg.to_string());
129 self
130 }
131
132 pub fn event_etag_fails(self, msg: &str) -> Self {
134 self.inner.write().unwrap().event_etag_error = Some(msg.to_string());
135 self
136 }
137
138 pub fn put_event_fails(self, msg: &str) -> Self {
140 self.inner.write().unwrap().put_event_error = Some(msg.to_string());
141 self
142 }
143
144 pub fn delete_event_fails(self, msg: &str) -> Self {
146 self.inner.write().unwrap().delete_event_error = Some(msg.to_string());
147 self
148 }
149
150 pub fn ensure_default_fails(self, msg: &str) -> Self {
152 self.inner.write().unwrap().ensure_default_error = Some(msg.to_string());
153 self
154 }
155
156 pub fn events_in(&self, calendar_id: i64) -> Vec<Event> {
158 self.inner
159 .read()
160 .unwrap()
161 .events
162 .iter()
163 .filter(|(c, _)| *c == calendar_id)
164 .map(|(_, e)| e.clone())
165 .collect()
166 }
167
168 pub fn default_calendar_was_created_for(&self, user: &str) -> bool {
170 self.inner
171 .read()
172 .unwrap()
173 .default_created_for
174 .iter()
175 .any(|u| u == user)
176 }
177}
178
179impl Default for InMemoryCalendarStore {
180 fn default() -> Self {
181 Self::new()
182 }
183}
184
185#[async_trait]
186impl CalendarStore for InMemoryCalendarStore {
187 async fn list_calendars(&self, user: &str) -> Result<Vec<Calendar>, StoreError> {
188 let inner = self.inner.read().unwrap();
189 if let Some(ref msg) = inner.list_calendars_error {
190 return Err(msg.clone().into());
191 }
192 Ok(inner
193 .calendars
194 .iter()
195 .filter(|(o, _)| o == user)
196 .map(|(_, c)| c.clone())
197 .collect())
198 }
199
200 async fn get_calendar(
201 &self,
202 user: &str,
203 calendar_name: &str,
204 ) -> Result<Option<Calendar>, StoreError> {
205 let inner = self.inner.read().unwrap();
206 if let Some(ref msg) = inner.get_calendar_error {
207 return Err(msg.clone().into());
208 }
209 Ok(inner
210 .calendars
211 .iter()
212 .find(|(o, c)| o == user && c.name == calendar_name)
213 .map(|(_, c)| c.clone()))
214 }
215
216 async fn list_events(&self, calendar_id: i64) -> Result<Vec<Event>, StoreError> {
217 let inner = self.inner.read().unwrap();
218 if let Some(ref msg) = inner.list_events_error {
219 return Err(msg.clone().into());
220 }
221 Ok(inner
222 .events
223 .iter()
224 .filter(|(c, _)| *c == calendar_id)
225 .map(|(_, e)| e.clone())
226 .collect())
227 }
228
229 async fn get_event(
230 &self,
231 calendar_id: i64,
232 uid: &str,
233 ) -> Result<Option<Event>, StoreError> {
234 let inner = self.inner.read().unwrap();
235 if let Some(ref msg) = inner.get_event_error {
236 return Err(msg.clone().into());
237 }
238 Ok(inner
239 .events
240 .iter()
241 .find(|(c, e)| *c == calendar_id && e.uid == uid)
242 .map(|(_, e)| e.clone()))
243 }
244
245 async fn event_etag(
246 &self,
247 calendar_id: i64,
248 uid: &str,
249 ) -> Result<Option<String>, StoreError> {
250 let inner = self.inner.read().unwrap();
251 if let Some(ref msg) = inner.event_etag_error {
252 return Err(msg.clone().into());
253 }
254 Ok(inner
255 .events
256 .iter()
257 .find(|(c, e)| *c == calendar_id && e.uid == uid)
258 .map(|(_, e)| e.etag.clone()))
259 }
260
261 async fn put_event(
262 &self,
263 calendar_id: i64,
264 uid: &str,
265 icalendar: &str,
266 etag: &str,
267 ) -> Result<PutResult, StoreError> {
268 let mut inner = self.inner.write().unwrap();
269 if let Some(ref msg) = inner.put_event_error {
270 return Err(msg.clone().into());
271 }
272 let pos = inner
273 .events
274 .iter()
275 .position(|(c, e)| *c == calendar_id && e.uid == uid);
276 let created = pos.is_none();
277 if let Some(p) = pos {
278 inner.events[p].1.icalendar = icalendar.to_string();
279 inner.events[p].1.etag = etag.to_string();
280 } else {
281 inner.events.push((
282 calendar_id,
283 Event {
284 uid: uid.to_string(),
285 etag: etag.to_string(),
286 icalendar: icalendar.to_string(),
287 summary: String::new(),
288 dtstart: None,
289 dtend: None,
290 },
291 ));
292 }
293 Ok(PutResult {
294 created,
295 etag: etag.to_string(),
296 })
297 }
298
299 async fn delete_event(
300 &self,
301 calendar_id: i64,
302 uid: &str,
303 ) -> Result<bool, StoreError> {
304 let mut inner = self.inner.write().unwrap();
305 if let Some(ref msg) = inner.delete_event_error {
306 return Err(msg.clone().into());
307 }
308 let before = inner.events.len();
309 inner
310 .events
311 .retain(|(c, e)| !(*c == calendar_id && e.uid == uid));
312 Ok(inner.events.len() < before)
313 }
314
315 async fn ensure_default_calendar(&self, user: &str) -> Result<(), StoreError> {
316 let mut inner = self.inner.write().unwrap();
317 if let Some(ref msg) = inner.ensure_default_error {
318 return Err(msg.clone().into());
319 }
320 let has_any = inner.calendars.iter().any(|(o, _)| o == user);
321 if !has_any {
322 let next_id = (inner.calendars.len() as i64) + 1;
323 inner.calendars.push((
324 user.to_string(),
325 Calendar {
326 id: next_id,
327 name: "Default".to_string(),
328 color: String::new(),
329 description: String::new(),
330 },
331 ));
332 inner.default_created_for.push(user.to_string());
333 }
334 Ok(())
335 }
336}
337
338pub struct InMemoryAddressBookStore {
345 inner: RwLock<AbInner>,
346}
347
348struct AbInner {
349 books: Vec<(String, AddressBook)>,
350 contacts: Vec<(i64, Contact)>,
351 default_created_for: Vec<String>,
352
353 list_books_error: Option<String>,
354 get_book_error: Option<String>,
355 list_contacts_error: Option<String>,
356 get_contact_error: Option<String>,
357 contact_etag_error: Option<String>,
358 put_contact_error: Option<String>,
359 delete_contact_error: Option<String>,
360 ensure_default_error: Option<String>,
361}
362
363impl InMemoryAddressBookStore {
364 pub fn new() -> Self {
366 Self {
367 inner: RwLock::new(AbInner {
368 books: Vec::new(),
369 contacts: Vec::new(),
370 default_created_for: Vec::new(),
371 list_books_error: None,
372 get_book_error: None,
373 list_contacts_error: None,
374 get_contact_error: None,
375 contact_etag_error: None,
376 put_contact_error: None,
377 delete_contact_error: None,
378 ensure_default_error: None,
379 }),
380 }
381 }
382
383 pub fn with_book(self, owner: &str, book: AddressBook) -> Self {
385 self.inner
386 .write()
387 .unwrap()
388 .books
389 .push((owner.to_string(), book));
390 self
391 }
392
393 pub fn with_contact(self, book_id: i64, contact: Contact) -> Self {
395 self.inner.write().unwrap().contacts.push((book_id, contact));
396 self
397 }
398
399 pub fn list_books_fails(self, msg: &str) -> Self {
401 self.inner.write().unwrap().list_books_error = Some(msg.to_string());
402 self
403 }
404
405 pub fn get_book_fails(self, msg: &str) -> Self {
407 self.inner.write().unwrap().get_book_error = Some(msg.to_string());
408 self
409 }
410
411 pub fn list_contacts_fails(self, msg: &str) -> Self {
413 self.inner.write().unwrap().list_contacts_error = Some(msg.to_string());
414 self
415 }
416
417 pub fn get_contact_fails(self, msg: &str) -> Self {
419 self.inner.write().unwrap().get_contact_error = Some(msg.to_string());
420 self
421 }
422
423 pub fn contact_etag_fails(self, msg: &str) -> Self {
425 self.inner.write().unwrap().contact_etag_error = Some(msg.to_string());
426 self
427 }
428
429 pub fn put_contact_fails(self, msg: &str) -> Self {
431 self.inner.write().unwrap().put_contact_error = Some(msg.to_string());
432 self
433 }
434
435 pub fn delete_contact_fails(self, msg: &str) -> Self {
437 self.inner.write().unwrap().delete_contact_error = Some(msg.to_string());
438 self
439 }
440
441 pub fn ensure_default_fails(self, msg: &str) -> Self {
443 self.inner.write().unwrap().ensure_default_error = Some(msg.to_string());
444 self
445 }
446
447 pub fn contacts_in(&self, book_id: i64) -> Vec<Contact> {
449 self.inner
450 .read()
451 .unwrap()
452 .contacts
453 .iter()
454 .filter(|(b, _)| *b == book_id)
455 .map(|(_, c)| c.clone())
456 .collect()
457 }
458}
459
460impl Default for InMemoryAddressBookStore {
461 fn default() -> Self {
462 Self::new()
463 }
464}
465
466#[async_trait]
467impl AddressBookStore for InMemoryAddressBookStore {
468 async fn list_address_books(&self, user: &str) -> Result<Vec<AddressBook>, StoreError> {
469 let inner = self.inner.read().unwrap();
470 if let Some(ref msg) = inner.list_books_error {
471 return Err(msg.clone().into());
472 }
473 Ok(inner
474 .books
475 .iter()
476 .filter(|(o, _)| o == user)
477 .map(|(_, b)| b.clone())
478 .collect())
479 }
480
481 async fn get_address_book(
482 &self,
483 user: &str,
484 book_name: &str,
485 ) -> Result<Option<AddressBook>, StoreError> {
486 let inner = self.inner.read().unwrap();
487 if let Some(ref msg) = inner.get_book_error {
488 return Err(msg.clone().into());
489 }
490 Ok(inner
491 .books
492 .iter()
493 .find(|(o, b)| o == user && b.name == book_name)
494 .map(|(_, b)| b.clone()))
495 }
496
497 async fn list_contacts(&self, book_id: i64) -> Result<Vec<Contact>, StoreError> {
498 let inner = self.inner.read().unwrap();
499 if let Some(ref msg) = inner.list_contacts_error {
500 return Err(msg.clone().into());
501 }
502 Ok(inner
503 .contacts
504 .iter()
505 .filter(|(b, _)| *b == book_id)
506 .map(|(_, c)| c.clone())
507 .collect())
508 }
509
510 async fn get_contact(
511 &self,
512 book_id: i64,
513 uid: &str,
514 ) -> Result<Option<Contact>, StoreError> {
515 let inner = self.inner.read().unwrap();
516 if let Some(ref msg) = inner.get_contact_error {
517 return Err(msg.clone().into());
518 }
519 Ok(inner
520 .contacts
521 .iter()
522 .find(|(b, c)| *b == book_id && c.uid == uid)
523 .map(|(_, c)| c.clone()))
524 }
525
526 async fn contact_etag(
527 &self,
528 book_id: i64,
529 uid: &str,
530 ) -> Result<Option<String>, StoreError> {
531 let inner = self.inner.read().unwrap();
532 if let Some(ref msg) = inner.contact_etag_error {
533 return Err(msg.clone().into());
534 }
535 Ok(inner
536 .contacts
537 .iter()
538 .find(|(b, c)| *b == book_id && c.uid == uid)
539 .map(|(_, c)| c.etag.clone()))
540 }
541
542 async fn put_contact(
543 &self,
544 book_id: i64,
545 uid: &str,
546 vcard: &str,
547 etag: &str,
548 ) -> Result<PutResult, StoreError> {
549 let mut inner = self.inner.write().unwrap();
550 if let Some(ref msg) = inner.put_contact_error {
551 return Err(msg.clone().into());
552 }
553 let pos = inner
554 .contacts
555 .iter()
556 .position(|(b, c)| *b == book_id && c.uid == uid);
557 let created = pos.is_none();
558 if let Some(p) = pos {
559 inner.contacts[p].1.vcard = vcard.to_string();
560 inner.contacts[p].1.etag = etag.to_string();
561 } else {
562 inner.contacts.push((
563 book_id,
564 Contact {
565 uid: uid.to_string(),
566 etag: etag.to_string(),
567 vcard: vcard.to_string(),
568 fn_name: String::new(),
569 email: String::new(),
570 },
571 ));
572 }
573 Ok(PutResult {
574 created,
575 etag: etag.to_string(),
576 })
577 }
578
579 async fn delete_contact(
580 &self,
581 book_id: i64,
582 uid: &str,
583 ) -> Result<bool, StoreError> {
584 let mut inner = self.inner.write().unwrap();
585 if let Some(ref msg) = inner.delete_contact_error {
586 return Err(msg.clone().into());
587 }
588 let before = inner.contacts.len();
589 inner
590 .contacts
591 .retain(|(b, c)| !(*b == book_id && c.uid == uid));
592 Ok(inner.contacts.len() < before)
593 }
594
595 async fn ensure_default_address_book(&self, user: &str) -> Result<(), StoreError> {
596 let mut inner = self.inner.write().unwrap();
597 if let Some(ref msg) = inner.ensure_default_error {
598 return Err(msg.clone().into());
599 }
600 let has = inner.books.iter().any(|(o, _)| o == user);
601 if !has {
602 let next_id = (inner.books.len() as i64) + 1;
603 inner.books.push((
604 user.to_string(),
605 AddressBook {
606 id: next_id,
607 name: "Default".to_string(),
608 description: String::new(),
609 },
610 ));
611 inner.default_created_for.push(user.to_string());
612 }
613 Ok(())
614 }
615}
616
617pub fn make_calendar(id: i64, name: &str) -> Calendar {
623 Calendar {
624 id,
625 name: name.to_string(),
626 color: "#abcdef".to_string(),
627 description: format!("calendar {name}"),
628 }
629}
630
631pub fn make_event(uid: &str, body: &str) -> Event {
633 Event {
634 uid: uid.to_string(),
635 etag: etag_of(body),
636 icalendar: body.to_string(),
637 summary: String::new(),
638 dtstart: None,
639 dtend: None,
640 }
641}
642
643pub fn make_book(id: i64, name: &str) -> AddressBook {
645 AddressBook {
646 id,
647 name: name.to_string(),
648 description: format!("address book {name}"),
649 }
650}
651
652pub fn make_contact(uid: &str, vcard: &str) -> Contact {
654 Contact {
655 uid: uid.to_string(),
656 etag: etag_of(vcard),
657 vcard: vcard.to_string(),
658 fn_name: String::new(),
659 email: String::new(),
660 }
661}
662
663pub fn body_as_str(body: Vec<u8>) -> String {
666 String::from_utf8(body).expect("dav body is utf-8")
667}
668
669pub fn header_value<'a>(
672 headers: &'a [(String, String)],
673 name: &str,
674) -> Option<&'a str> {
675 headers
676 .iter()
677 .find(|(k, _)| k.eq_ignore_ascii_case(name))
678 .map(|(_, v)| v.as_str())
679}