mailrs_dav/types.rs
1//! Minimal CalDAV / CardDAV-facing data types.
2//!
3//! These are intentionally decoupled from any backing store (PostgreSQL, SQLite,
4//! filesystem, etc.). A [`CalendarStore`](crate::store::CalendarStore) or
5//! [`AddressBookStore`](crate::store::AddressBookStore) implementation is
6//! responsible for mapping its own representation into these shapes.
7
8use chrono::{DateTime, Utc};
9
10/// A CalDAV calendar collection.
11///
12/// The `id` is the store's native primary key; the `name` is what gets exposed
13/// as the URL path segment and `<D:displayname>` in PROPFIND output.
14#[derive(Debug, Clone)]
15pub struct Calendar {
16 /// Store-native primary key. Surfaces as the FK on every event row.
17 pub id: i64,
18 /// URL-safe collection name; also returned as `<D:displayname>` in PROPFIND.
19 pub name: String,
20 /// CSS-style color (e.g. `#ff8800`). Returned as `<apple:calendar-color>`
21 /// for client compatibility; empty string means "client picks".
22 pub color: String,
23 /// Free-form description; returned as `<C:calendar-description>`.
24 pub description: String,
25}
26
27/// A single VEVENT (or other VCOMPONENT) stored under a calendar.
28///
29/// The raw `icalendar` text is kept as the canonical form; structured fields
30/// (`summary`, `dtstart`, `dtend`) are projections used for query/reporting
31/// performance and may be re-derived from the raw text by the store.
32#[derive(Debug, Clone)]
33pub struct Event {
34 /// iCalendar `UID` property — globally unique per RFC 5545 §3.8.4.7.
35 /// Doubles as the URL path segment in `/dav/.../events/{uid}.ics`.
36 pub uid: String,
37 /// Strong validator returned as the `ETag` HTTP header and on
38 /// `getetag` PROPFIND queries. Stable for as long as the body bytes are
39 /// unchanged.
40 pub etag: String,
41 /// Verbatim RFC 5545 iCalendar text — the canonical form. PUT bodies
42 /// round-trip unchanged through GET so client VTIMEZONE / X-* extensions
43 /// survive.
44 pub icalendar: String,
45 /// Projection of the iCalendar `SUMMARY` property; safe for listing UIs.
46 pub summary: String,
47 /// Projection of `DTSTART` (UTC-normalised). `None` when the event lacks a
48 /// start time (rare; e.g. floating VTODO).
49 pub dtstart: Option<DateTime<Utc>>,
50 /// Projection of `DTEND` (UTC-normalised). `None` for instantaneous events
51 /// or VTODO entries without an end.
52 pub dtend: Option<DateTime<Utc>>,
53}
54
55/// A CardDAV address book collection.
56#[derive(Debug, Clone)]
57pub struct AddressBook {
58 /// Store-native primary key. Surfaces as the FK on every contact row.
59 pub id: i64,
60 /// URL-safe collection name; also returned as `<D:displayname>`.
61 pub name: String,
62 /// Free-form description; returned as `<CR:addressbook-description>`.
63 pub description: String,
64}
65
66/// A single vCard stored under an address book.
67#[derive(Debug, Clone)]
68pub struct Contact {
69 /// vCard `UID` property — globally unique per RFC 6350 §6.7.6. Also the
70 /// URL path segment in `/dav/.../contacts/{uid}.vcf`.
71 pub uid: String,
72 /// Strong validator returned as `ETag` and on `getetag` PROPFIND queries.
73 pub etag: String,
74 /// Verbatim RFC 6350 vCard text — the canonical form. PUT bodies round-
75 /// trip unchanged through GET so client X-* extensions survive.
76 pub vcard: String,
77 /// Projection of the vCard `FN` (formatted name) property; safe for
78 /// listing UIs. Field name is `fn_name` because `fn` is a Rust keyword.
79 pub fn_name: String,
80 /// Primary email projection (first `EMAIL` property value, or empty).
81 pub email: String,
82}
83
84/// Result of a successful PUT (event or contact).
85#[derive(Debug, Clone)]
86pub struct PutResult {
87 /// `true` when the resource didn't exist before this PUT.
88 pub created: bool,
89 /// The etag the handler will return in the `ETag` response header (RFC
90 /// 4791 §5.3.2 / RFC 6352 §6.3.2). Typically the same value the store
91 /// recorded — equality is the contract clients depend on.
92 pub etag: String,
93}