use serde::{Deserialize, Serialize};
use crate::{impl_default, impl_display, Error, Result};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Flag {
Read,
Starred,
Collapsed,
Mentioned,
StreamWildcardMentioned,
TopicWildcardMentioned,
HasAlertWord,
Historical,
}
impl Flag {
pub const READ: &str = "read";
pub const STARRED: &str = "starred";
pub const COLLAPSED: &str = "collapsed";
pub const MENTIONED: &str = "mentioned";
pub const STREAM_WILDCARD_MENTIONED: &str = "stream_wildcard_mentioned";
pub const TOPIC_WILDCARD_MENTIONED: &str = "topic_wildcard_mentioned";
pub const HAS_ALERT_WORD: &str = "has_alert_word";
pub const HISTORICAL: &str = "historical";
pub const fn new() -> Self {
Self::Read
}
pub const fn as_str(&self) -> &'static str {
match self {
Self::Read => Self::READ,
Self::Starred => Self::STARRED,
Self::Collapsed => Self::COLLAPSED,
Self::Mentioned => Self::MENTIONED,
Self::StreamWildcardMentioned => Self::STREAM_WILDCARD_MENTIONED,
Self::TopicWildcardMentioned => Self::TOPIC_WILDCARD_MENTIONED,
Self::HasAlertWord => Self::HAS_ALERT_WORD,
Self::Historical => Self::HISTORICAL,
}
}
pub fn try_from_str(val: &str) -> Result<Self> {
match val.to_lowercase().as_str() {
Self::READ => Ok(Self::Read),
Self::STARRED => Ok(Self::Starred),
Self::COLLAPSED => Ok(Self::Collapsed),
Self::MENTIONED => Ok(Self::Mentioned),
Self::STREAM_WILDCARD_MENTIONED => Ok(Self::StreamWildcardMentioned),
Self::TOPIC_WILDCARD_MENTIONED => Ok(Self::TopicWildcardMentioned),
Self::HAS_ALERT_WORD => Ok(Self::HasAlertWord),
Self::HISTORICAL => Ok(Self::Historical),
s => Err(Error::invalid_field(
"flag",
s,
format!(
"{} | {} | {} | {} | {} | {} | {} | {}",
Self::READ,
Self::STARRED,
Self::COLLAPSED,
Self::MENTIONED,
Self::STREAM_WILDCARD_MENTIONED,
Self::TOPIC_WILDCARD_MENTIONED,
Self::HAS_ALERT_WORD,
Self::HISTORICAL
),
)),
}
}
}
impl From<Flag> for &'static str {
fn from(val: Flag) -> Self {
val.as_str()
}
}
impl From<Flag> for String {
fn from(val: Flag) -> Self {
val.as_str().to_string()
}
}
impl TryFrom<&str> for Flag {
type Error = Error;
fn try_from(val: &str) -> Result<Self> {
Self::try_from_str(val)
}
}
impl TryFrom<&String> for Flag {
type Error = Error;
fn try_from(val: &String) -> Result<Self> {
Self::try_from_str(val.as_str())
}
}
impl TryFrom<String> for Flag {
type Error = Error;
fn try_from(val: String) -> Result<Self> {
Self::try_from_str(val.as_str())
}
}
impl_default!(Flag);
impl_display!(Flag);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_flag() {
[
(Flag::Read, Flag::READ),
(Flag::Starred, Flag::STARRED),
(Flag::Collapsed, Flag::COLLAPSED),
(Flag::Mentioned, Flag::MENTIONED),
(
Flag::StreamWildcardMentioned,
Flag::STREAM_WILDCARD_MENTIONED,
),
(Flag::TopicWildcardMentioned, Flag::TOPIC_WILDCARD_MENTIONED),
(Flag::HasAlertWord, Flag::HAS_ALERT_WORD),
(Flag::Historical, Flag::HISTORICAL),
]
.into_iter()
.for_each(|(flag, flag_str)| {
let flag_json = flag.to_string();
assert_eq!(flag.as_str(), flag_str);
assert_eq!(serde_json::to_string(&flag).unwrap(), flag_json);
assert_eq!(serde_json::from_str::<Flag>(&flag_json).unwrap(), flag);
});
}
}