use std::num::NonZeroU64;
use abnf_core::streaming::sp;
#[cfg(feature = "ext_condstore_qresync")]
use imap_types::extensions::condstore_qresync::{AttributeFlag, EntryTypeReq};
use nom::{
branch::alt,
bytes::streaming::{tag, tag_no_case},
character::streaming::char,
combinator::{map, map_res, opt, value},
sequence::{delimited, preceded, tuple},
};
use crate::{
core::{atom, number64},
decode::IMAPResult,
};
pub(crate) fn mod_sequence_valzer(input: &[u8]) -> IMAPResult<&[u8], u64> {
number64(input)
}
pub(crate) fn mod_sequence_value(input: &[u8]) -> IMAPResult<&[u8], NonZeroU64> {
map_res(number64, NonZeroU64::try_from)(input)
}
pub(crate) fn search_sort_mod_seq(input: &[u8]) -> IMAPResult<&[u8], NonZeroU64> {
delimited(
char('('),
preceded(tag_no_case("MODSEQ "), mod_sequence_value),
char(')'),
)(input)
}
#[allow(clippy::type_complexity)]
pub(crate) fn search_modsequence(
input: &[u8],
) -> IMAPResult<&[u8], (Option<(AttributeFlag, EntryTypeReq)>, u64)> {
preceded(
tag_no_case("MODSEQ"),
tuple((opt(search_modseq_ext), preceded(sp, mod_sequence_valzer))),
)(input)
}
pub(crate) fn search_modseq_ext(input: &[u8]) -> IMAPResult<&[u8], (AttributeFlag, EntryTypeReq)> {
tuple((preceded(sp, entry_name), preceded(sp, entry_type_req)))(input)
}
#[inline]
pub(crate) fn entry_name(input: &[u8]) -> IMAPResult<&[u8], AttributeFlag> {
entry_flag_name(input)
}
pub(crate) fn entry_flag_name(input: &[u8]) -> IMAPResult<&[u8], AttributeFlag> {
delimited(tag_no_case("\"/flags/"), attr_flag, char('"'))(input)
}
pub(crate) fn attr_flag(input: &[u8]) -> IMAPResult<&[u8], AttributeFlag> {
alt((
map(preceded(tag("\\\\"), atom), AttributeFlag::system),
map(atom, AttributeFlag::Keyword),
))(input)
}
pub(crate) fn entry_type_req(input: &[u8]) -> IMAPResult<&[u8], EntryTypeReq> {
alt((
value(EntryTypeReq::Private, tag_no_case("priv")),
value(EntryTypeReq::Shared, tag_no_case("shared")),
value(EntryTypeReq::All, tag_no_case("all")),
))(input)
}
#[cfg(test)]
mod tests {
use crate::response::resp_text;
#[test]
fn test_condstore_qresync_codes() {
assert!(resp_text(b"[MODIFIED 7,9] Conditional STORE failed\r\n").is_ok());
assert!(
resp_text(b"[NOMODSEQ] Sorry, this mailbox format doesn't support modsequences\r\n")
.is_ok()
);
assert!(resp_text(b"[HIGHESTMODSEQ 715194045007] Highest\r\n").is_ok());
}
}