Skip to main content

io_vdir/
collection.rs

1//! Vdir collections: the [`VdirCollection`] handle plus the I/O-free
2//! coroutines managing collection directories and their metadata
3//! files (create, delete, list, rename, update).
4//!
5//! A collection is a directory holding items; it may also carry the
6//! optional metadata markers (display name, description, color)
7//! defined by the [vdir specification]. The coroutine submodules own
8//! one operation each; this module owns the shared handle and the
9//! marker file names they read and write.
10//!
11//! [vdir specification]: https://vdirsyncer.pimutils.org/en/stable/vdir.html#metadata
12
13use core::hash::{Hash, Hasher};
14
15use alloc::string::String;
16
17use crate::path::VdirPath;
18
19pub mod create;
20pub mod delete;
21pub mod list;
22pub mod rename;
23pub mod update;
24
25/// File name of the optional UTF-8 display name marker.
26pub(crate) const DISPLAYNAME: &str = "displayname";
27
28/// File name of the optional UTF-8 description marker.
29pub(crate) const DESCRIPTION: &str = "description";
30
31/// File name of the optional `#RRGGBB` color marker.
32pub(crate) const COLOR: &str = "color";
33
34/// A Vdir collection.
35///
36/// Represents a directory that contains only items (vCard or
37/// iCalendar files). A collection may also carry the optional
38/// [metadata] files defined by the vdir specification.
39///
40/// See [`crate::item::VdirItem`].
41///
42/// [metadata]: https://vdirsyncer.pimutils.org/en/stable/vdir.html#metadata
43#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
44#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
45pub struct VdirCollection {
46    /// On-disk directory of the collection.
47    pub path: VdirPath,
48    /// Display name of the collection, when the `displayname` file
49    /// exists and is non-empty.
50    pub display_name: Option<String>,
51    /// Description of the collection, when the `description` file
52    /// exists and is non-empty.
53    pub description: Option<String>,
54    /// ASCII `#RRGGBB` hex color of the collection, when the `color`
55    /// file exists and is non-empty.
56    pub color: Option<String>,
57}
58
59impl VdirCollection {
60    /// Wraps `path` as a bare collection with no metadata. Performs
61    /// no filesystem check.
62    pub fn from_path(path: impl Into<VdirPath>) -> Self {
63        Self {
64            path: path.into(),
65            display_name: None,
66            description: None,
67            color: None,
68        }
69    }
70
71    /// Returns the collection id: the final path component, or an
72    /// empty string when the path has no file name.
73    pub fn id(&self) -> &str {
74        self.path.file_name().unwrap_or("")
75    }
76}
77
78impl Hash for VdirCollection {
79    fn hash<H: Hasher>(&self, state: &mut H) {
80        self.path.hash(state);
81    }
82}
83
84impl AsRef<VdirPath> for VdirCollection {
85    fn as_ref(&self) -> &VdirPath {
86        &self.path
87    }
88}
89
90impl From<VdirPath> for VdirCollection {
91    fn from(path: VdirPath) -> Self {
92        Self::from_path(path)
93    }
94}