Skip to main content

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}