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}