use abnf_core::streaming::sp;
use imap_types::{
core::NString,
envelope::{Address, Envelope},
};
use nom::{
branch::alt,
bytes::streaming::tag,
combinator::map,
multi::many1,
sequence::{delimited, tuple},
};
use crate::{
core::{nil, nstring},
decode::IMAPResult,
};
pub(crate) fn envelope(input: &[u8]) -> IMAPResult<&[u8], Envelope> {
let mut parser = delimited(
tag(b"("),
tuple((
env_date,
sp,
env_subject,
sp,
env_from,
sp,
env_sender,
sp,
env_reply_to,
sp,
env_to,
sp,
env_cc,
sp,
env_bcc,
sp,
env_in_reply_to,
sp,
env_message_id,
)),
tag(b")"),
);
let (
remaining,
(
date,
_,
subject,
_,
from,
_,
sender,
_,
reply_to,
_,
to,
_,
cc,
_,
bcc,
_,
in_reply_to,
_,
message_id,
),
) = parser(input)?;
Ok((
remaining,
Envelope {
date,
subject,
from,
sender,
reply_to,
to,
cc,
bcc,
in_reply_to,
message_id,
},
))
}
#[inline]
pub(crate) fn env_date(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
#[inline]
pub(crate) fn env_subject(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
pub(crate) fn env_from(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
alt((
delimited(tag(b"("), many1(address), tag(b")")),
map(nil, |_| Vec::new()),
))(input)
}
pub(crate) fn env_sender(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
alt((
delimited(tag(b"("), many1(address), tag(b")")),
map(nil, |_| Vec::new()),
))(input)
}
pub(crate) fn env_reply_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
alt((
delimited(tag(b"("), many1(address), tag(b")")),
map(nil, |_| Vec::new()),
))(input)
}
pub(crate) fn env_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
alt((
delimited(tag(b"("), many1(address), tag(b")")),
map(nil, |_| Vec::new()),
))(input)
}
pub(crate) fn env_cc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
alt((
delimited(tag(b"("), many1(address), tag(b")")),
map(nil, |_| Vec::new()),
))(input)
}
pub(crate) fn env_bcc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
alt((
delimited(tag(b"("), many1(address), tag(b")")),
map(nil, |_| Vec::new()),
))(input)
}
#[inline]
pub(crate) fn env_in_reply_to(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
#[inline]
pub(crate) fn env_message_id(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
pub(crate) fn address(input: &[u8]) -> IMAPResult<&[u8], Address> {
let mut parser = delimited(
tag(b"("),
tuple((addr_name, sp, addr_adl, sp, addr_mailbox, sp, addr_host)),
tag(b")"),
);
let (remaining, (name, _, adl, _, mailbox, _, host)) = parser(input)?;
Ok((
remaining,
Address {
name,
adl,
mailbox,
host,
},
))
}
#[inline]
pub(crate) fn addr_name(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
#[inline]
pub(crate) fn addr_adl(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
#[inline]
pub(crate) fn addr_mailbox(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
#[inline]
pub(crate) fn addr_host(input: &[u8]) -> IMAPResult<&[u8], NString> {
nstring(input)
}
#[cfg(test)]
mod tests {
use imap_types::core::{IString, NString};
use super::*;
#[test]
fn test_parse_address() {
let (rem, val) = address(b"(nil {3}\r\nxxx \"xxx\" nil)").unwrap();
assert_eq!(
val,
Address {
name: NString(None),
adl: NString(Some(IString::Literal(
b"xxx".as_slice().try_into().unwrap()
))),
mailbox: NString(Some(IString::Quoted("xxx".try_into().unwrap()))),
host: NString(None),
}
);
assert_eq!(rem, b"");
}
}