From 3d0724e342f9f4c846e924d7a4e763ba4ab6194e Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Mon, 22 Feb 2021 17:51:59 -0600 Subject: [PATCH] asdf --- imap/.ignore | 2 +- imap/src/parser/mod.rs | 45 +++++++++++++++++++++++++++++++++++- imap/src/parser/rfc3501.pest | 8 ++++--- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/imap/.ignore b/imap/.ignore index 54d47a5..a5a0c0b 100644 --- a/imap/.ignore +++ b/imap/.ignore @@ -1,2 +1,2 @@ src/builders -src/parser +src/oldparser diff --git a/imap/src/parser/mod.rs b/imap/src/parser/mod.rs index 1a92245..f79de63 100644 --- a/imap/src/parser/mod.rs +++ b/imap/src/parser/mod.rs @@ -97,15 +97,38 @@ fn build_resp_cond_state(pair: Pair) -> (Status, Option, Opt let mut code = None; let mut information = None; + println!("pairs: {:#?}", pairs); + let pair = pairs.next().unwrap(); + let mut pairs = pair.into_inner(); for pair in pairs { match pair.as_rule() { - Rule::resp_text => information = Some(pair.as_str().to_owned()), + Rule::resp_text_code => code = Some(build_resp_code(pair)), + Rule::text => information = Some(pair.as_str().to_owned()), _ => unreachable!("{:#?}", pair), } } + (status, code, information) } +fn build_resp_code(pair: Pair) -> ResponseCode { + if !matches!(pair.as_rule(), Rule::resp_text_code) { + unreachable!("{:#?}", pair); + } + + let mut pairs = pair.into_inner(); + let pair = pairs.next().unwrap(); + match pair.as_rule() { + Rule::resp_text_code_unseen => { + let mut pairs = pair.into_inner(); + let pair = pairs.next().unwrap(); + let number = pair.as_str().parse::().unwrap(); + ResponseCode::Unseen(number) + } + _ => unreachable!("{:#?}", pair), + } +} + fn build_status(pair: Pair) -> Status { match pair.as_rule() { Rule::resp_status => match pair.as_str().to_uppercase().as_str() { @@ -162,6 +185,12 @@ fn build_mailbox_data(pair: Pair) -> MailboxData { let flags = build_flag_list(pair); MailboxData::Flags(flags) } + Rule::mailbox_data_recent => { + let mut pairs = pair.into_inner(); + let pair = pairs.next().unwrap(); + let number = pair.as_str().parse::().unwrap(); + MailboxData::Recent(number) + } _ => unreachable!("{:#?}", pair), } } @@ -230,5 +259,19 @@ mod tests { Flag::Draft, ]))) ); + + assert_eq!( + parse_response("* 2 RECENT\r\n"), + Ok(Response::MailboxData(MailboxData::Recent(2))) + ); + + assert_eq!( + parse_response("* OK [UNSEEN 17] Message 17 is the first unseen message\r\n"), + Ok(Response::Data { + status: Status::Ok, + code: Some(ResponseCode::Unseen(17)), + information: Some("Message 17 is the first unseen message".to_owned()), + }) + ); } } diff --git a/imap/src/parser/rfc3501.pest b/imap/src/parser/rfc3501.pest index 44929fa..8fb67b9 100644 --- a/imap/src/parser/rfc3501.pest +++ b/imap/src/parser/rfc3501.pest @@ -64,9 +64,10 @@ header_list = { "(" ~ header_fld_name ~ (sp ~ header_fld_name)* ~ ")" } list_wildcards = @{ "%" | "*" } literal = @{ "{" ~ number ~ "}" ~ crlf ~ char8* } mailbox = { ^"INBOX" | astring } -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 = { 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 | mailbox_data_recent } mailbox_data_exists = { number ~ sp ~ ^"EXISTS" } mailbox_data_flags = { ^"FLAGS" ~ sp ~ flag_list } +mailbox_data_recent = { number ~ sp ~ ^"RECENT" } 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_oflag = { "\\NoInferiors" | flag_extension } @@ -88,10 +89,11 @@ quoted_char = @{ (!quoted_specials ~ char) | ("\\" ~ quoted_specials) } quoted_specials = @{ dquote | "\\" } resp_cond_bye = { ^"BYE" ~ sp ~ resp_text } resp_cond_state = { resp_status ~ sp ~ resp_text } -resp_status = { (^"OK" | ^"NO" | ^"BAD") } resp_specials = @{ "]" } +resp_status = { (^"OK" | ^"NO" | ^"BAD") } resp_text = { ("[" ~ resp_text_code ~ "]" ~ sp)? ~ text } -resp_text_code = { ^"ALERT" | (^"BADCHARSET" ~ (sp ~ "(" ~ astring ~ (sp ~ astring)* ~ ")")?) | capability_data | ^"PARSE" | (^"PERMANENTFLAGS" ~ sp ~ "(" ~ (flag_perm ~ (sp ~ flag_perm)*)? ~ ")") | ^"READ-ONLY" | ^"READ-WRITE" | ^"TRYCREATE" | (^"UIDNEXT" ~ sp ~ nz_number) | (^"UIDVALIDITY" ~ sp ~ nz_number) | (^"UNSEEN" ~ sp ~ nz_number) | (atom ~ (sp ~ resp_text_code_atom)?) } +resp_text_code = { ^"ALERT" | (^"BADCHARSET" ~ (sp ~ "(" ~ astring ~ (sp ~ astring)* ~ ")")?) | capability_data | ^"PARSE" | (^"PERMANENTFLAGS" ~ sp ~ "(" ~ (flag_perm ~ (sp ~ flag_perm)*)? ~ ")") | ^"READ-ONLY" | ^"READ-WRITE" | ^"TRYCREATE" | (^"UIDNEXT" ~ sp ~ nz_number) | (^"UIDVALIDITY" ~ sp ~ nz_number) | resp_text_code_unseen | (atom ~ (sp ~ resp_text_code_atom)?) } +resp_text_code_unseen = { ^"UNSEEN" ~ sp ~ nz_number } resp_text_code_atom = @{ (!"]" ~ text_char){1,} } response = { continue_req | response_data | response_done } response_data = { "*" ~ sp ~ (resp_cond_state | resp_cond_bye | mailbox_data | message_data | capability_data) ~ crlf }