use abnf_core::streaming::SP;
use imap_types::{
core::Atom,
flag::{Flag, FlagNameAttribute},
};
use nom::{
branch::alt,
bytes::streaming::{tag, tag_no_case},
combinator::{map, value},
multi::{separated_list0, separated_list1},
sequence::{delimited, preceded},
IResult,
};
use crate::rfc3501::core::atom;
pub fn flag(input: &[u8]) -> IResult<&[u8], Flag> {
alt((
value(Flag::Answered, tag_no_case(b"\\Answered")),
value(Flag::Flagged, tag_no_case(b"\\Flagged")),
value(Flag::Deleted, tag_no_case(b"\\Deleted")),
value(Flag::Seen, tag_no_case(b"\\Seen")),
value(Flag::Draft, tag_no_case(b"\\Draft")),
flag_keyword,
map(flag_extension, Flag::Extension),
))(input)
}
pub fn flag_fetch(input: &[u8]) -> IResult<&[u8], Flag> {
alt((flag, value(Flag::Recent, tag_no_case(b"\\Recent"))))(input)
}
pub fn flag_perm(input: &[u8]) -> IResult<&[u8], Flag> {
alt((flag, value(Flag::Permanent, tag(b"\\*"))))(input)
}
#[inline]
pub fn flag_keyword(input: &[u8]) -> IResult<&[u8], Flag> {
map(atom, Flag::Keyword)(input)
}
pub fn flag_list(input: &[u8]) -> IResult<&[u8], Vec<Flag>> {
delimited(tag(b"("), separated_list0(SP, flag), tag(b")"))(input)
}
pub fn mbx_list_flags(input: &[u8]) -> IResult<&[u8], Vec<FlagNameAttribute>> {
let (remaining, flags) = separated_list1(SP, alt((mbx_list_sflag, mbx_list_oflag)))(input)?;
let sflag_count = flags
.iter()
.filter(|&flag| FlagNameAttribute::is_selectability(flag))
.count();
if sflag_count > 1 {
return Err(nom::Err::Failure(nom::error::make_error(
input,
nom::error::ErrorKind::Verify,
)));
}
Ok((remaining, flags))
}
pub fn mbx_list_oflag(input: &[u8]) -> IResult<&[u8], FlagNameAttribute> {
alt((
value(
FlagNameAttribute::Noinferiors,
tag_no_case(b"\\Noinferiors"),
),
map(flag_extension, FlagNameAttribute::Extension),
))(input)
}
pub fn mbx_list_sflag(input: &[u8]) -> IResult<&[u8], FlagNameAttribute> {
alt((
value(FlagNameAttribute::Noselect, tag_no_case(b"\\Noselect")),
value(FlagNameAttribute::Marked, tag_no_case(b"\\Marked")),
value(FlagNameAttribute::Unmarked, tag_no_case(b"\\Unmarked")),
))(input)
}
pub fn flag_extension(input: &[u8]) -> IResult<&[u8], Atom> {
preceded(tag(b"\\"), atom)(input)
}