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::*;
|
use crate::response::*;
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ pub fn parse_capability(s: &str) -> Result<Capability, Error<Rule>> {
|
||||||
let pair = pairs.next().unwrap();
|
let pair = pairs.next().unwrap();
|
||||||
let cap = match pair.as_rule() {
|
let cap = match pair.as_rule() {
|
||||||
Rule::capability => {
|
Rule::capability => {
|
||||||
let mut inner = pair.into_inner();
|
let mut pairs = pair.into_inner();
|
||||||
let pair = inner.next().unwrap();
|
let pair = pairs.next().unwrap();
|
||||||
match pair.as_rule() {
|
match pair.as_rule() {
|
||||||
Rule::auth_type => Capability::Auth(pair.as_str().to_uppercase().to_owned()),
|
Rule::auth_type => Capability::Auth(pair.as_str().to_uppercase().to_owned()),
|
||||||
Rule::atom => match pair.as_str() {
|
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>> {
|
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)]
|
#[cfg(test)]
|
||||||
|
@ -54,4 +104,16 @@ mod tests {
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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_char = @{ (!quoted_specials ~ char) | ("\\" ~ quoted_specials) }
|
||||||
quoted_specials = @{ dquote | "\\" }
|
quoted_specials = @{ dquote | "\\" }
|
||||||
resp_cond_bye = { ^"BYE" ~ sp ~ resp_text }
|
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_specials = @{ "]" }
|
||||||
resp_text = { ("[" ~ resp_text_code ~ "]" ~ sp)? ~ text }
|
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) | (^"UNSEEN" ~ sp ~ nz_number) | (atom ~ (sp ~ resp_text_code_atom)?) }
|
||||||
|
@ -120,5 +121,5 @@ ctl = @{ '\x00'..'\x1f' | "\x7f" }
|
||||||
digit = @{ '\x30'..'\x39' }
|
digit = @{ '\x30'..'\x39' }
|
||||||
dquote = @{ "\"" }
|
dquote = @{ "\"" }
|
||||||
lf = @{ "\x0a" }
|
lf = @{ "\x0a" }
|
||||||
sp = @{ " " }
|
sp = _{ " " }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Response {
|
pub enum Response {
|
||||||
Capabilities(Vec<Capability>),
|
Capabilities(Vec<Capability>),
|
||||||
Continue {
|
Continue {
|
||||||
|
@ -34,7 +34,7 @@ pub enum Capability {
|
||||||
Atom(String),
|
Atom(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum ResponseCode {
|
pub enum ResponseCode {
|
||||||
Alert,
|
Alert,
|
||||||
BadCharset(Option<Vec<String>>),
|
BadCharset(Option<Vec<String>>),
|
||||||
|
@ -53,16 +53,16 @@ pub enum ResponseCode {
|
||||||
UidNotSticky,
|
UidNotSticky,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum UidSetMember {
|
pub enum UidSetMember {
|
||||||
UidRange(RangeInclusive<u32>),
|
UidRange(RangeInclusive<u32>),
|
||||||
Uid(u32),
|
Uid(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum AttributeValue {}
|
pub enum AttributeValue {}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum MailboxDatum {}
|
pub enum MailboxDatum {}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
|
Loading…
Reference in a new issue