#[cfg(feature = "arbitrary")]
use arbitrary::Arbitrary;
#[cfg(feature = "bounded-static")]
use bounded_static::ToStatic;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::core::{Atom, AtomError};
#[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 Flag<'a> {
Seen,
Answered,
Flagged,
Deleted,
Draft,
Extension(FlagExtension<'a>),
Keyword(Atom<'a>),
}
impl<'a> Flag<'a> {
pub fn system<A>(value: A) -> Result<Self, FlagError<'a, A::Error>>
where
A: TryInto<Atom<'a>>,
{
let atom = value.try_into()?;
match atom.as_ref().to_ascii_lowercase().as_ref() {
"answered" => Ok(Self::Answered),
"flagged" => Ok(Self::Flagged),
"deleted" => Ok(Self::Deleted),
"seen" => Ok(Self::Seen),
"draft" => Ok(Self::Draft),
_ => Err(FlagError::IsAnExtensionFlag { candidate: atom }),
}
}
pub fn extension<A>(value: A) -> Result<Self, FlagError<'a, A::Error>>
where
A: TryInto<Atom<'a>>,
{
let atom = value.try_into()?;
match atom.as_ref().to_ascii_lowercase().as_ref() {
"answered" | "flagged" | "deleted" | "seen" | "draft" => {
Err(FlagError::IsASystemFlag { candidate: atom })
}
_ => Ok(Self::Extension(FlagExtension(atom))),
}
}
pub fn system_or_extension(atom: Atom<'a>) -> Self {
match Self::system(atom) {
Ok(system) => system,
Err(FlagError::Atom(_)) => unreachable!(),
Err(FlagError::IsASystemFlag { .. }) => unreachable!(),
Err(FlagError::IsAnExtensionFlag { candidate }) => {
Self::Extension(FlagExtension(candidate))
}
}
}
}
#[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>),
AllowNewKeywords,
}
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FlagExtension<'a>(pub(crate) Atom<'a>);
impl<'a> TryFrom<Atom<'a>> for FlagExtension<'a> {
type Error = FlagError<'a, AtomError>;
fn try_from(value: Atom<'a>) -> Result<Self, Self::Error> {
match value.as_ref().to_ascii_lowercase().as_ref() {
"answered" | "flagged" | "deleted" | "seen" | "draft" => {
Err(FlagError::IsASystemFlag { candidate: value })
}
_ => Ok(Self(value)),
}
}
}
impl<'a> AsRef<str> for FlagExtension<'a> {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
#[derive(Clone, Debug, Eq, Error, Hash, Ord, PartialEq, PartialOrd)]
pub enum FlagError<'a, A> {
#[error(transparent)]
Atom(#[from] A),
#[error("Is a system flag.")]
IsASystemFlag { candidate: Atom<'a> },
#[error("Is an extension flag.")]
IsAnExtensionFlag { candidate: Atom<'a> },
}
#[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 FlagNameAttribute<'a> {
Noinferiors,
Noselect,
Marked,
Unmarked,
Extension(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(atom),
}
}
}
#[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,
}