protonmail_client/flag.rs
1//! IMAP message flags
2//!
3//! Provides a strongly-typed enum for IMAP flags instead of raw
4//! strings. Standard system flags have dedicated variants; arbitrary
5//! keyword flags use the `Keyword` variant.
6
7use std::fmt;
8
9/// An IMAP message flag.
10///
11/// System flags (prefixed with `\` in the IMAP protocol) have
12/// dedicated variants. User-defined keyword flags use [`Flag::Keyword`].
13///
14/// # Examples
15///
16/// ```
17/// use protonmail_client::Flag;
18///
19/// let seen = Flag::Seen;
20/// assert_eq!(seen.as_imap_str(), "\\Seen");
21///
22/// let kw = Flag::Keyword("$Important".to_string());
23/// assert_eq!(kw.as_imap_str(), "$Important");
24/// ```
25#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub enum Flag {
27 /// Message has been read (`\Seen`).
28 Seen,
29 /// Message has been answered (`\Answered`).
30 Answered,
31 /// Message is flagged for attention (`\Flagged`).
32 Flagged,
33 /// Message is marked for deletion (`\Deleted`).
34 Deleted,
35 /// Message is a draft (`\Draft`).
36 Draft,
37 /// A user-defined keyword flag (no `\` prefix).
38 Keyword(String),
39}
40
41impl Flag {
42 /// The IMAP wire representation of this flag.
43 ///
44 /// System flags include the leading backslash (e.g. `\Seen`).
45 /// Keyword flags are returned as-is.
46 #[must_use]
47 pub fn as_imap_str(&self) -> &str {
48 match self {
49 Self::Seen => "\\Seen",
50 Self::Answered => "\\Answered",
51 Self::Flagged => "\\Flagged",
52 Self::Deleted => "\\Deleted",
53 Self::Draft => "\\Draft",
54 Self::Keyword(kw) => kw,
55 }
56 }
57}
58
59impl fmt::Display for Flag {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.write_str(self.as_imap_str())
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn system_flags() {
71 assert_eq!(Flag::Seen.as_imap_str(), "\\Seen");
72 assert_eq!(Flag::Answered.as_imap_str(), "\\Answered");
73 assert_eq!(Flag::Flagged.as_imap_str(), "\\Flagged");
74 assert_eq!(Flag::Deleted.as_imap_str(), "\\Deleted");
75 assert_eq!(Flag::Draft.as_imap_str(), "\\Draft");
76 }
77
78 #[test]
79 fn keyword_flag() {
80 let kw = Flag::Keyword("$Important".to_string());
81 assert_eq!(kw.as_imap_str(), "$Important");
82 }
83
84 #[test]
85 fn display_matches_imap_str() {
86 assert_eq!(format!("{}", Flag::Seen), "\\Seen");
87 assert_eq!(format!("{}", Flag::Keyword("$Junk".to_string())), "$Junk");
88 }
89}