This commit is contained in:
Michael Zhang 2021-08-07 22:26:42 -05:00
parent f5b076d54c
commit b2c96c9f46
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
3 changed files with 37 additions and 8 deletions

View file

@ -23,11 +23,12 @@ pub enum Status {
}
pub enum ResponseCode<'a> {
Alert,
Capabilities(Vec<Capability<'a>>),
}
pub enum Capability<'a> {
Imap4rev1,
Auth(Cow<'a, str>),
Atom(Cow<'a, str>),
Auth(Cow<'a, [u8]>),
Atom(Cow<'a, [u8]>),
}

View file

@ -11,7 +11,8 @@ rule!(pub BIT : u8 => satisfy(|c| c == b'0' || c == b'1'));
pub fn is_char(c: u8) -> bool { c != b'\0' }
rule!(pub CHAR : u8 => satisfy(is_char));
rule!(pub CR : u8 => byte(b'\x0d'));
pub fn is_cr(c: u8) -> bool { c == b'\x0d' }
rule!(pub CR : u8 => satisfy(is_cr));
rule!(pub CRLF : (u8, u8) => pair(CR, LF));
@ -27,7 +28,8 @@ rule!(pub HEXDIG : u8 => alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F'))));
rule!(pub HTAB : u8 => byte(b'\x09'));
rule!(pub LF : u8 => byte(b'\x0a'));
pub fn is_lf(c: u8) -> bool { c == b'\x0a' }
rule!(pub LF : u8 => satisfy(is_lf));
rule!(pub LWSP : () => skip(many0(alt((skip(WSP), skip(pair(CRLF, WSP)))))));

View file

@ -1,17 +1,20 @@
//! Grammar from https://datatracker.ietf.org/doc/html/rfc3501#section-9
use std::borrow::Cow;
use nom::{
branch::alt,
bytes::streaming::{tag_no_case, take},
bytes::streaming::{tag_no_case, take_while1, take},
character::streaming::char,
combinator::{map, map_res},
multi::{many0, many1},
sequence::{delimited, terminated},
sequence::{delimited, pair, preceded, separated_pair, terminated},
IResult,
};
use super::parsers::satisfy;
use super::rfc2234::{is_char, is_ctl, is_dquote, is_sp, CRLF, DIGIT, DQUOTE};
use super::response::{Capability, ResponseCode};
use super::rfc2234::{is_char, is_cr, is_ctl, is_dquote, is_lf, is_sp, CRLF, DIGIT, DQUOTE, SP};
rule!(pub astring : Vec<u8> => alt((many1(ASTRING_CHAR), string)));
@ -37,6 +40,21 @@ pub fn is_atom_specials(c: u8) -> bool {
}
rule!(pub atom_specials : u8 => satisfy(is_atom_specials));
rule!(pub auth_type : Vec<u8> => atom);
rule!(pub capability : Capability => alt((
map(preceded(tag_no_case("AUTH="), auth_type), |s| Capability::Auth(Cow::from(s))),
map(atom, |s| Capability::Atom(Cow::from(s))),
)));
rule!(pub capability_data : Vec<Capability> => preceded(tag_no_case("CAPABILITY"), {
map(separated_pair(
many0(preceded(SP, capability)),
pair(SP, tag_no_case("IMAP4rev1")),
many0(preceded(SP, capability))
), |(mut a, b)| { a.extend(b); a })
}));
pub fn is_list_wildcards(c: u8) -> bool { c == b'%' || c == b'*' }
rule!(pub list_wildcards : u8 => satisfy(is_list_wildcards));
@ -77,6 +95,14 @@ rule!(pub quoted_specials : u8 => satisfy(is_quoted_specials));
pub fn is_resp_specials(c: u8) -> bool { c == b']' }
rule!(pub resp_specials : u8 => satisfy(is_resp_specials));
rule!(pub resp_text_code : ResponseCode => alt((
map(tag_no_case("ALERT"), |_| ResponseCode::Alert),
map(capability_data, ResponseCode::Capabilities),
)));
rule!(pub string : Vec<u8> => alt((quoted, literal)));
pub fn TEXT_CHAR(i: &[u8]) -> IResult<&[u8], u8> { todo!() }
rule!(pub text : &[u8] => take_while1(is_text_char));
pub fn is_text_char(c: u8) -> bool { is_char(c) && !is_cr(c) && !is_lf(c) }
rule!(pub TEXT_CHAR : u8 => satisfy(is_text_char));