This commit is contained in:
Michael Zhang 2021-02-22 17:39:50 -06:00
parent 1276ead25f
commit 0dac4f4e96
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
3 changed files with 77 additions and 15 deletions

View file

@ -118,6 +118,30 @@ fn build_status(pair: Pair<Rule>) -> Status {
} }
} }
fn build_flag_list(pair: Pair<Rule>) -> Vec<Flag> {
if !matches!(pair.as_rule(), Rule::flag_list) {
unreachable!("{:#?}", pair);
}
pair.into_inner().map(build_flag).collect()
}
fn build_flag(pair: Pair<Rule>) -> Flag {
if !matches!(pair.as_rule(), Rule::flag) {
unreachable!("{:#?}", pair);
}
match pair.as_str() {
"\\Answered" => Flag::Answered,
"\\Flagged" => Flag::Flagged,
"\\Deleted" => Flag::Deleted,
"\\Seen" => Flag::Seen,
"\\Draft" => Flag::Draft,
s if s.starts_with("\\") => Flag::Ext(s.to_owned()),
_ => unreachable!("{:#?}", pair.as_str()),
}
}
fn build_mailbox_data(pair: Pair<Rule>) -> MailboxData { fn build_mailbox_data(pair: Pair<Rule>) -> MailboxData {
if !matches!(pair.as_rule(), Rule::mailbox_data) { if !matches!(pair.as_rule(), Rule::mailbox_data) {
unreachable!("{:#?}", pair); unreachable!("{:#?}", pair);
@ -132,18 +156,24 @@ fn build_mailbox_data(pair: Pair<Rule>) -> MailboxData {
let number = pair.as_str().parse::<u32>().unwrap(); let number = pair.as_str().parse::<u32>().unwrap();
MailboxData::Exists(number) MailboxData::Exists(number)
} }
Rule::mailbox_data_flags => {
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
let flags = build_flag_list(pair);
MailboxData::Flags(flags)
}
_ => unreachable!("{:#?}", pair), _ => unreachable!("{:#?}", pair),
} }
} }
#[cfg(test)] #[cfg(test)]
#[rustfmt::skip]
mod tests { mod tests {
use super::*; use super::*;
use crate::response::*; use crate::response::*;
use pest::Parser; use pest::Parser;
#[test] #[test]
#[rustfmt::skip]
fn test_capability() { fn test_capability() {
assert_eq!(parse_capability("IMAP4rev1"), Ok(Capability::Imap4rev1)); assert_eq!(parse_capability("IMAP4rev1"), Ok(Capability::Imap4rev1));
assert_eq!(parse_capability("LOGINDISABLED"), Ok(Capability::Atom("LOGINDISABLED".to_owned()))); assert_eq!(parse_capability("LOGINDISABLED"), Ok(Capability::Atom("LOGINDISABLED".to_owned())));
@ -155,6 +185,7 @@ mod tests {
} }
#[test] #[test]
#[rustfmt::skip]
fn test_nil() { fn test_nil() {
assert!(Rfc3501::parse(Rule::nil, "NIL").is_ok()); assert!(Rfc3501::parse(Rule::nil, "NIL").is_ok());
assert!(Rfc3501::parse(Rule::nil, "anything else").is_err()); assert!(Rfc3501::parse(Rule::nil, "anything else").is_err());
@ -165,19 +196,39 @@ mod tests {
// this little exchange is from section 8 of rfc3501 // this little exchange is from section 8 of rfc3501
// https://tools.ietf.org/html/rfc3501#section-8 // https://tools.ietf.org/html/rfc3501#section-8
assert_eq!(parse_response("* OK IMAP4rev1 Service Ready\r\n"), Ok(Response::Data { assert_eq!(
status: Status::Ok, parse_response("* OK IMAP4rev1 Service Ready\r\n"),
code: None, Ok(Response::Data {
information: Some("IMAP4rev1 Service Ready".to_owned()), status: Status::Ok,
})); code: None,
information: Some("IMAP4rev1 Service Ready".to_owned()),
})
);
assert_eq!(parse_response("a001 OK LOGIN completed\r\n"), Ok(Response::Done { assert_eq!(
tag: "a001".to_owned(), parse_response("a001 OK LOGIN completed\r\n"),
status: Status::Ok, Ok(Response::Done {
code: None, tag: "a001".to_owned(),
information: Some("LOGIN completed".to_owned()), status: Status::Ok,
})); code: None,
information: Some("LOGIN completed".to_owned()),
})
);
assert_eq!(parse_response("* 18 EXISTS\r\n"), Ok(Response::MailboxData(MailboxData::Exists(18)))); assert_eq!(
parse_response("* 18 EXISTS\r\n"),
Ok(Response::MailboxData(MailboxData::Exists(18)))
);
assert_eq!(
parse_response("* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n"),
Ok(Response::MailboxData(MailboxData::Flags(vec![
Flag::Answered,
Flag::Flagged,
Flag::Deleted,
Flag::Seen,
Flag::Draft,
])))
);
} }
} }

View file

@ -64,8 +64,9 @@ header_list = { "(" ~ header_fld_name ~ (sp ~ header_fld_name)* ~ ")" }
list_wildcards = @{ "%" | "*" } list_wildcards = @{ "%" | "*" }
literal = @{ "{" ~ number ~ "}" ~ crlf ~ char8* } literal = @{ "{" ~ number ~ "}" ~ crlf ~ char8* }
mailbox = { ^"INBOX" | astring } mailbox = { ^"INBOX" | astring }
mailbox_data = { (^"FLAGS" ~ sp ~ flag_list) | (^"LIST" ~ sp ~ mailbox_list) | (^"LSUB" ~ sp ~ mailbox_list) | (^"SEARCH" ~ (sp ~ nz_number)*) | (^"STATUS" ~ sp ~ mailbox ~ sp ~ ^"(" ~ status_att_list? ~ ^")") | mailbox_data_exists | (number ~ sp ~ ^"RECENT") } mailbox_data = { mailbox_data_flags | (^"LIST" ~ sp ~ mailbox_list) | (^"LSUB" ~ sp ~ mailbox_list) | (^"SEARCH" ~ (sp ~ nz_number)*) | (^"STATUS" ~ sp ~ mailbox ~ sp ~ ^"(" ~ status_att_list? ~ ^")") | mailbox_data_exists | (number ~ sp ~ ^"RECENT") }
mailbox_data_exists = { number ~ sp ~ ^"EXISTS" } mailbox_data_exists = { number ~ sp ~ ^"EXISTS" }
mailbox_data_flags = { ^"FLAGS" ~ sp ~ flag_list }
mailbox_list = { "(" ~ mbx_list_flags* ~ ")" ~ sp ~ (dquote ~ quoted_char ~ dquote | nil) ~ sp ~ mailbox } mailbox_list = { "(" ~ mbx_list_flags* ~ ")" ~ sp ~ (dquote ~ quoted_char ~ dquote | nil) ~ sp ~ mailbox }
mbx_list_flags = { (mbx_list_oflag ~ sp)* ~ mbx_list_sflag ~ (sp ~ mbx_list_oflag)* | mbx_list_oflag ~ (sp ~ mbx_list_oflag)* } mbx_list_flags = { (mbx_list_oflag ~ sp)* ~ mbx_list_sflag ~ (sp ~ mbx_list_oflag)* | mbx_list_oflag ~ (sp ~ mbx_list_oflag)* }
mbx_list_oflag = { "\\NoInferiors" | flag_extension } mbx_list_oflag = { "\\NoInferiors" | flag_extension }

View file

@ -65,7 +65,7 @@ pub enum AttributeValue {}
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum MailboxData { pub enum MailboxData {
Exists(u32), Exists(u32),
Flags(Vec<String>), Flags(Vec<Flag>),
List { List {
flags: Vec<String>, flags: Vec<String>,
delimiter: Option<String>, delimiter: Option<String>,
@ -87,6 +87,16 @@ pub enum MailboxData {
}, },
} }
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Flag {
Answered,
Flagged,
Deleted,
Seen,
Draft,
Ext(String),
}
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata { pub struct Metadata {
pub entry: String, pub entry: String,