more work on response parser
This commit is contained in:
parent
875041edfd
commit
fed8031f5c
3 changed files with 74 additions and 11 deletions
|
@ -1,4 +1,4 @@
|
|||
use pest::{error::Error, Parser};
|
||||
use pest::{error::Error, Parser, iterators::{Pair, Pairs}};
|
||||
|
||||
use crate::response::*;
|
||||
|
||||
|
@ -11,8 +11,8 @@ pub fn parse_capability(s: &str) -> Result<Capability, Error<Rule>> {
|
|||
let pair = pairs.next().unwrap();
|
||||
let cap = match pair.as_rule() {
|
||||
Rule::capability => {
|
||||
let mut inner = pair.into_inner();
|
||||
let pair = inner.next().unwrap();
|
||||
let mut pairs = pair.into_inner();
|
||||
let pair = pairs.next().unwrap();
|
||||
match pair.as_rule() {
|
||||
Rule::auth_type => Capability::Auth(pair.as_str().to_uppercase().to_owned()),
|
||||
Rule::atom => match pair.as_str() {
|
||||
|
@ -28,7 +28,57 @@ pub fn parse_capability(s: &str) -> Result<Capability, Error<Rule>> {
|
|||
}
|
||||
|
||||
pub fn parse_response(s: &str) -> Result<Response, Error<Rule>> {
|
||||
todo!()
|
||||
let mut pairs = Rfc3501::parse(Rule::response, s)?;
|
||||
let pair = pairs.next().unwrap();
|
||||
Ok(build_response(pair))
|
||||
}
|
||||
|
||||
fn build_response(pair: Pair<Rule>) -> Response {
|
||||
match pair.as_rule() {
|
||||
Rule::response => {
|
||||
let mut pairs = pair.into_inner();
|
||||
let pair = pairs.next().unwrap();
|
||||
match pair.as_rule() {
|
||||
Rule::response_data => {
|
||||
let mut pairs = pair.into_inner();
|
||||
let pair = pairs.next().unwrap();
|
||||
match pair.as_rule() {
|
||||
Rule::resp_cond_state => {
|
||||
let mut pairs = pair.into_inner();
|
||||
let pair = pairs.next().unwrap();
|
||||
let status = build_status(pair);
|
||||
let mut code = None;
|
||||
let mut information = None;
|
||||
|
||||
for pair in pairs {
|
||||
if let resp_text = pair.as_rule() {
|
||||
information = Some(pair.as_str().to_owned());
|
||||
}
|
||||
}
|
||||
Response::Data { status, code, information }
|
||||
}
|
||||
_ => unreachable!("{:?}", pair),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("{:?}", pair),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("{:?}", pair),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_status(pair: Pair<Rule>) -> Status {
|
||||
match pair.as_rule() {
|
||||
Rule::resp_status => {
|
||||
match pair.as_str().to_uppercase().as_str() {
|
||||
"OK" => Status::Ok,
|
||||
"NO" => Status::No,
|
||||
"BAD" => Status::Bad,
|
||||
s => unreachable!("invalid status {:?}", s),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("{:?}", pair),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -54,4 +104,16 @@ mod tests {
|
|||
assert!(Rfc3501::parse(Rule::nil, "NIL").is_ok());
|
||||
assert!(Rfc3501::parse(Rule::nil, "anything else").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_section_8() {
|
||||
// this little exchange is from section 8 of rfc3501
|
||||
// https://tools.ietf.org/html/rfc3501#section-8
|
||||
|
||||
assert_eq!(parse_response("* OK IMAP4rev1 Service Ready\r\n"), Ok(Response::Data {
|
||||
status: Status::Ok,
|
||||
code: None,
|
||||
information: Some("IMAP4rev1 Service Ready".to_owned()),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,8 @@ quoted = @{ dquote ~ quoted_char* ~ dquote }
|
|||
quoted_char = @{ (!quoted_specials ~ char) | ("\\" ~ quoted_specials) }
|
||||
quoted_specials = @{ dquote | "\\" }
|
||||
resp_cond_bye = { ^"BYE" ~ sp ~ resp_text }
|
||||
resp_cond_state = { (^"OK" | ^"NO" | ^"BAD") ~ resp_text }
|
||||
resp_cond_state = { resp_status ~ sp ~ resp_text }
|
||||
resp_status = { (^"OK" | ^"NO" | ^"BAD") }
|
||||
resp_specials = @{ "]" }
|
||||
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)?) }
|
||||
|
@ -120,5 +121,5 @@ ctl = @{ '\x00'..'\x1f' | "\x7f" }
|
|||
digit = @{ '\x30'..'\x39' }
|
||||
dquote = @{ "\"" }
|
||||
lf = @{ "\x0a" }
|
||||
sp = @{ " " }
|
||||
sp = _{ " " }
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::RangeInclusive;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Response {
|
||||
Capabilities(Vec<Capability>),
|
||||
Continue {
|
||||
|
@ -34,7 +34,7 @@ pub enum Capability {
|
|||
Atom(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ResponseCode {
|
||||
Alert,
|
||||
BadCharset(Option<Vec<String>>),
|
||||
|
@ -53,16 +53,16 @@ pub enum ResponseCode {
|
|||
UidNotSticky,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum UidSetMember {
|
||||
UidRange(RangeInclusive<u32>),
|
||||
Uid(u32),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum AttributeValue {}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum MailboxDatum {}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
|
|
Loading…
Reference in a new issue