use std::fmt::{Display, Formatter};
#[cfg(feature = "arbitrary")]
use arbitrary::Arbitrary;
#[cfg(feature = "bounded-static")]
use bounded_static::ToStatic;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{core::Atom, error::ValidationError};
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Flag<'a> {
Answered,
Deleted,
Draft,
Flagged,
Seen,
Extension(FlagExtension<'a>),
Keyword(Atom<'a>),
}
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FlagExtension<'a>(Atom<'a>);
impl<'a> Flag<'a> {
pub fn system(atom: Atom<'a>) -> Self {
match atom.as_ref().to_ascii_lowercase().as_ref() {
"answered" => Self::Answered,
"deleted" => Self::Deleted,
"draft" => Self::Draft,
"flagged" => Self::Flagged,
"seen" => Self::Seen,
_ => Self::Extension(FlagExtension(atom)),
}
}
pub fn keyword(atom: Atom<'a>) -> Self {
Self::Keyword(atom)
}
}
impl<'a> TryFrom<&'a str> for Flag<'a> {
type Error = ValidationError;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
Ok(if let Some(value) = value.strip_prefix('\\') {
Self::system(Atom::try_from(value)?)
} else {
Self::keyword(Atom::try_from(value)?)
})
}
}
impl<'a> Display for Flag<'a> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
Flag::Answered => f.write_str("\\Answered"),
Flag::Deleted => f.write_str("\\Deleted"),
Flag::Draft => f.write_str("\\Draft"),
Flag::Flagged => f.write_str("\\Flagged"),
Flag::Seen => f.write_str("\\Seen"),
Flag::Extension(other) => write!(f, "\\{}", other.0),
Flag::Keyword(atom) => write!(f, "{}", atom),
}
}
}
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum FlagFetch<'a> {
Flag(Flag<'a>),
Recent,
}
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum FlagPerm<'a> {
Flag(Flag<'a>),
Asterisk,
}
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum FlagNameAttribute<'a> {
Noinferiors,
Noselect,
Marked,
Unmarked,
Extension(FlagNameAttributeExtension<'a>),
}
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FlagNameAttributeExtension<'a>(Atom<'a>);
impl<'a> FlagNameAttribute<'a> {
pub fn is_selectability(&self) -> bool {
matches!(
self,
FlagNameAttribute::Noselect | FlagNameAttribute::Marked | FlagNameAttribute::Unmarked
)
}
}
impl<'a> From<Atom<'a>> for FlagNameAttribute<'a> {
fn from(atom: Atom<'a>) -> Self {
match atom.as_ref().to_ascii_lowercase().as_ref() {
"noinferiors" => Self::Noinferiors,
"noselect" => Self::Noselect,
"marked" => Self::Marked,
"unmarked" => Self::Unmarked,
_ => Self::Extension(FlagNameAttributeExtension(atom)),
}
}
}
impl<'a> Display for FlagNameAttribute<'a> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
Self::Noinferiors => f.write_str("\\Noinferiors"),
Self::Noselect => f.write_str("\\Noselect"),
Self::Marked => f.write_str("\\Marked"),
Self::Unmarked => f.write_str("\\Unmarked"),
Self::Extension(extension) => write!(f, "\\{}", extension.0),
}
}
}
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StoreType {
Replace,
Add,
Remove,
}
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StoreResponse {
Answer,
Silent,
}