Skip to main content

zulip_api/message/
flag.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{impl_default, impl_display, Error, Result};
4
5/// Represents an available Zulip message flag.
6///
7/// Flags are annotations to messages indicating additional state.
8#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
9#[serde(rename_all = "snake_case")]
10pub enum Flag {
11    Read,
12    Starred,
13    Collapsed,
14    Mentioned,
15    StreamWildcardMentioned,
16    TopicWildcardMentioned,
17    HasAlertWord,
18    Historical,
19}
20
21impl Flag {
22    /// Represents the string value for the read [Flag].
23    pub const READ: &str = "read";
24    /// Represents the string value for the starred [Flag].
25    pub const STARRED: &str = "starred";
26    /// Represents the string value for the collapsed [Flag].
27    pub const COLLAPSED: &str = "collapsed";
28    /// Represents the string value for the mentioned [Flag].
29    pub const MENTIONED: &str = "mentioned";
30    /// Represents the string value for the stream wildcard mentioned [Flag].
31    pub const STREAM_WILDCARD_MENTIONED: &str = "stream_wildcard_mentioned";
32    /// Represents the string value for the topic wildcard mentioned [Flag].
33    pub const TOPIC_WILDCARD_MENTIONED: &str = "topic_wildcard_mentioned";
34    /// Represents the string value for the has alert word [Flag].
35    pub const HAS_ALERT_WORD: &str = "has_alert_word";
36    /// Represents the string value for the historical [Flag].
37    pub const HISTORICAL: &str = "historical";
38
39    /// Creates a new [Flag].
40    pub const fn new() -> Self {
41        Self::Read
42    }
43
44    /// Gets the [Flag] string representation.
45    pub const fn as_str(&self) -> &'static str {
46        match self {
47            Self::Read => Self::READ,
48            Self::Starred => Self::STARRED,
49            Self::Collapsed => Self::COLLAPSED,
50            Self::Mentioned => Self::MENTIONED,
51            Self::StreamWildcardMentioned => Self::STREAM_WILDCARD_MENTIONED,
52            Self::TopicWildcardMentioned => Self::TOPIC_WILDCARD_MENTIONED,
53            Self::HasAlertWord => Self::HAS_ALERT_WORD,
54            Self::Historical => Self::HISTORICAL,
55        }
56    }
57
58    /// Attempts to convert a string into a [Flag].
59    pub fn try_from_str(val: &str) -> Result<Self> {
60        match val.to_lowercase().as_str() {
61            Self::READ => Ok(Self::Read),
62            Self::STARRED => Ok(Self::Starred),
63            Self::COLLAPSED => Ok(Self::Collapsed),
64            Self::MENTIONED => Ok(Self::Mentioned),
65            Self::STREAM_WILDCARD_MENTIONED => Ok(Self::StreamWildcardMentioned),
66            Self::TOPIC_WILDCARD_MENTIONED => Ok(Self::TopicWildcardMentioned),
67            Self::HAS_ALERT_WORD => Ok(Self::HasAlertWord),
68            Self::HISTORICAL => Ok(Self::Historical),
69            s => Err(Error::invalid_field(
70                "flag",
71                s,
72                format!(
73                    "{} | {} | {} | {} | {} | {} | {} | {}",
74                    Self::READ,
75                    Self::STARRED,
76                    Self::COLLAPSED,
77                    Self::MENTIONED,
78                    Self::STREAM_WILDCARD_MENTIONED,
79                    Self::TOPIC_WILDCARD_MENTIONED,
80                    Self::HAS_ALERT_WORD,
81                    Self::HISTORICAL
82                ),
83            )),
84        }
85    }
86}
87
88impl From<Flag> for &'static str {
89    fn from(val: Flag) -> Self {
90        val.as_str()
91    }
92}
93
94impl From<Flag> for String {
95    fn from(val: Flag) -> Self {
96        val.as_str().to_string()
97    }
98}
99
100impl TryFrom<&str> for Flag {
101    type Error = Error;
102
103    fn try_from(val: &str) -> Result<Self> {
104        Self::try_from_str(val)
105    }
106}
107
108impl TryFrom<&String> for Flag {
109    type Error = Error;
110
111    fn try_from(val: &String) -> Result<Self> {
112        Self::try_from_str(val.as_str())
113    }
114}
115
116impl TryFrom<String> for Flag {
117    type Error = Error;
118
119    fn try_from(val: String) -> Result<Self> {
120        Self::try_from_str(val.as_str())
121    }
122}
123
124impl_default!(Flag);
125impl_display!(Flag);
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130
131    #[test]
132    fn test_flag() {
133        [
134            (Flag::Read, Flag::READ),
135            (Flag::Starred, Flag::STARRED),
136            (Flag::Collapsed, Flag::COLLAPSED),
137            (Flag::Mentioned, Flag::MENTIONED),
138            (
139                Flag::StreamWildcardMentioned,
140                Flag::STREAM_WILDCARD_MENTIONED,
141            ),
142            (Flag::TopicWildcardMentioned, Flag::TOPIC_WILDCARD_MENTIONED),
143            (Flag::HasAlertWord, Flag::HAS_ALERT_WORD),
144            (Flag::Historical, Flag::HISTORICAL),
145        ]
146        .into_iter()
147        .for_each(|(flag, flag_str)| {
148            let flag_json = flag.to_string();
149
150            assert_eq!(flag.as_str(), flag_str);
151
152            assert_eq!(serde_json::to_string(&flag).unwrap(), flag_json);
153            assert_eq!(serde_json::from_str::<Flag>(&flag_json).unwrap(), flag);
154        });
155    }
156}