Skip to main content

io_maildir/entry/
types.rs

1//! Maildir entry types: full body, lightweight handle, and the
2//! platform-specific info-section separator.
3
4use core::hash::{Hash, Hasher};
5
6use alloc::vec::Vec;
7
8use crate::{flag::types::MaildirFlags, path::FsPath};
9
10#[cfg(unix)]
11pub static INFORMATIONAL_SUFFIX_SEPARATOR: char = ':';
12#[cfg(windows)]
13pub static INFORMATIONAL_SUFFIX_SEPARATOR: char = ';';
14
15/// A Maildir entry: on-disk path plus body bytes.
16#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
17pub struct MaildirFullEntry {
18    pub(crate) path: FsPath,
19    pub(crate) contents: Vec<u8>,
20}
21
22impl MaildirFullEntry {
23    pub fn path(&self) -> &FsPath {
24        &self.path
25    }
26
27    pub fn id(&self) -> Option<&str> {
28        let file_name = self.path.file_name()?;
29
30        let id = match file_name.rsplit_once(INFORMATIONAL_SUFFIX_SEPARATOR) {
31            Some((id, _)) => id,
32            None => file_name,
33        };
34
35        Some(id)
36    }
37
38    pub fn contents(&self) -> &[u8] {
39        &self.contents
40    }
41
42    #[cfg(feature = "parser")]
43    pub fn parsed(&self) -> Option<mail_parser::Message<'_>> {
44        mail_parser::MessageParser::new().parse(&self.contents)
45    }
46
47    #[cfg(feature = "parser")]
48    pub fn headers(&self) -> Option<mail_parser::Message<'_>> {
49        mail_parser::MessageParser::new()
50            .with_minimal_headers()
51            .parse(&self.contents)
52    }
53}
54
55impl From<MaildirFullEntry> for Vec<u8> {
56    fn from(msg: MaildirFullEntry) -> Self {
57        msg.contents
58    }
59}
60
61impl From<(FsPath, Vec<u8>)> for MaildirFullEntry {
62    fn from((path, contents): (FsPath, Vec<u8>)) -> Self {
63        Self { path, contents }
64    }
65}
66
67impl Hash for MaildirFullEntry {
68    fn hash<H: Hasher>(&self, state: &mut H) {
69        self.path.hash(state);
70    }
71}
72
73/// Lightweight handle to a Maildir entry file (path only, no body).
74#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
75pub struct MaildirEntry {
76    path: FsPath,
77}
78
79impl MaildirEntry {
80    pub fn from_path(path: impl Into<FsPath>) -> Self {
81        Self { path: path.into() }
82    }
83
84    pub fn path(&self) -> &FsPath {
85        &self.path
86    }
87
88    /// Returns the entry id (filename before the `:2,` flags
89    /// separator).
90    pub fn id(&self) -> Option<&str> {
91        let file_name = self.path.file_name()?;
92
93        Some(
94            match file_name.rsplit_once(INFORMATIONAL_SUFFIX_SEPARATOR) {
95                Some((id, _)) => id,
96                None => file_name,
97            },
98        )
99    }
100
101    /// Parses the flags encoded in the filename.
102    pub fn flags(&self) -> MaildirFlags {
103        MaildirFlags::from(&self.path)
104    }
105}
106
107impl From<FsPath> for MaildirEntry {
108    fn from(path: FsPath) -> Self {
109        Self::from_path(path)
110    }
111}
112
113impl From<MaildirEntry> for FsPath {
114    fn from(entry: MaildirEntry) -> Self {
115        entry.path
116    }
117}