use macros

This commit is contained in:
Michael Zhang 2021-08-07 21:37:45 -05:00
parent 043feadd71
commit f6b193f69e
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
4 changed files with 44 additions and 61 deletions

7
imap/src/proto/macros.rs Normal file
View file

@ -0,0 +1,7 @@
macro_rules! rule {
($vis:vis $name:ident : $ret:ty => $expr:expr) => {
$vis fn $name(i: &[u8]) -> nom::IResult<&[u8], $ret> {
$expr(i)
}
};
}

View file

@ -1,5 +1,8 @@
#![allow(non_snake_case, dead_code)] #![allow(non_snake_case, dead_code)]
#[macro_use]
mod macros;
// data types // data types
pub mod response; pub mod response;

View file

@ -1,69 +1,37 @@
//! Grammar from https://tools.ietf.org/html/rfc2234#section-6.1 //! Grammar from https://tools.ietf.org/html/rfc2234#section-6.1
use nom::{branch::alt, character::streaming::anychar, multi::many0, sequence::pair, IResult}; use nom::{branch::alt, character::streaming::anychar, multi::many0, sequence::pair};
use super::parsers::{byte, satisfy, skip}; use super::parsers::{byte, satisfy, skip};
pub fn ALPHA(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub ALPHA : u8 => satisfy(|c| (c >= b'a' && c <= b'z') || (c >= b'A' && c <= b'Z')));
satisfy(|c| (c >= b'a' && c <= b'z') || (c >= b'A' && c <= b'Z'))(i)
}
pub fn BIT(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub BIT : u8 => satisfy(|c| c == b'0' || c == b'1'));
satisfy(|c| c == b'0' || c == b'1')(i)
}
pub fn CHAR(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub CHAR : u8 => satisfy(|c| c != b'\0'));
satisfy(|c| c != b'\0')(i)
}
pub fn CR(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub CR : u8 => byte(b'\x0d'));
byte(b'\x0d')(i)
}
pub fn CRLF(i: &[u8]) -> IResult<&[u8], (u8, u8)> { rule!(pub CRLF : (u8, u8) => pair(CR, LF));
pair(CR, LF)(i)
}
pub fn CTL(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub CTL : u8 => satisfy(|c| c <= b'\x1f' || c == b'\x7f'));
satisfy(|c| c <= b'\x1f' || c == b'\x7f')(i)
}
pub fn DIGIT(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub DIGIT : u8 => satisfy(|c| c >= b'\x30' && c <= b'\x39'));
satisfy(|c| c >= b'\x30' && c <= b'\x39')(i)
}
pub fn DQUOTE(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub DQUOTE : u8 => byte(b'\x22'));
byte(b'\x22')(i)
}
pub fn HEXDIG(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub HEXDIG : u8 => alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F'))));
alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F')))(i)
}
pub fn HTAB(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub HTAB : u8 => byte(b'\x09'));
byte(b'\x09')(i)
}
pub fn LF(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub LF : u8 => byte(b'\x0a'));
byte(b'\x0a')(i)
}
pub fn LWSP(i: &[u8]) -> IResult<&[u8], ()> { rule!(pub LWSP : () => skip(many0(alt((skip(WSP), skip(pair(CRLF, WSP)))))));
skip(many0(alt((skip(WSP), skip(pair(CRLF, WSP))))))(i)
}
pub fn OCTET(i: &[u8]) -> IResult<&[u8], char> { rule!(pub OCTET : char => anychar);
anychar(i)
}
pub fn SP(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub SP : u8 => byte(b'\x20'));
byte(b'\x20')(i)
}
pub fn VCHAR(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub VCHAR : u8 => satisfy(|c| c >= b'\x21' && c <= b'\x7e'));
satisfy(|c| c >= b'\x21' && c <= b'\x7e')(i)
}
pub fn WSP(i: &[u8]) -> IResult<&[u8], u8> { rule!(pub WSP : u8 => alt((SP, HTAB)));
alt((SP, HTAB))(i)
}

View file

@ -11,6 +11,17 @@ use nom::{
}; };
use super::rfc2234::{CRLF, DIGIT, DQUOTE}; use super::rfc2234::{CRLF, DIGIT, DQUOTE};
use super::parsers::byte;
rule!(pub astring : Vec<u8> => alt((many1(ASTRING_CHAR), string)));
rule!(pub ASTRING_CHAR : u8 => alt((ATOM_CHAR, resp_specials)));
rule!(pub atom : Vec<u8> => many1(ATOM_CHAR));
pub fn ATOM_CHAR(i: &[u8]) -> IResult<&[u8], u8> {
todo!()
}
/// literal = "{" number "}" CRLF *CHAR8 /// literal = "{" number "}" CRLF *CHAR8
/// ; Number represents the number of CHAR8s /// ; Number represents the number of CHAR8s
@ -29,13 +40,9 @@ fn test_literal() {
); );
} }
pub fn nil(i: &[u8]) -> IResult<&[u8], &[u8]> { rule!(pub nil : &[u8] => tag_no_case("NIL"));
tag_no_case("NIL")(i)
}
pub fn nstring(i: &[u8]) -> IResult<&[u8], Option<Vec<u8>>> { rule!(pub nstring : Option<Vec<u8>> => alt((map(string, Some), map(nil, |_| None))));
alt((map(string, Some), map(nil, |_| None)))(i)
}
pub fn number(i: &[u8]) -> IResult<&[u8], u32> { pub fn number(i: &[u8]) -> IResult<&[u8], u32> {
map_res(map_res(many1(DIGIT), String::from_utf8), |s| { map_res(map_res(many1(DIGIT), String::from_utf8), |s| {
@ -43,17 +50,15 @@ pub fn number(i: &[u8]) -> IResult<&[u8], u32> {
})(i) })(i)
} }
pub fn quoted(i: &[u8]) -> IResult<&[u8], Vec<u8>> { rule!(pub quoted : Vec<u8> => delimited(DQUOTE, many0(QUOTED_CHAR), DQUOTE));
delimited(DQUOTE, many0(QUOTED_CHAR), DQUOTE)(i)
}
pub fn QUOTED_CHAR(i: &[u8]) -> IResult<&[u8], u8> { pub fn QUOTED_CHAR(i: &[u8]) -> IResult<&[u8], u8> {
todo!() todo!()
} }
pub fn string(i: &[u8]) -> IResult<&[u8], Vec<u8>> { rule!(pub resp_specials : u8 => byte(b']'));
alt((quoted, literal))(i)
} rule!(pub string : Vec<u8> => alt((quoted, literal)));
pub fn TEXT_CHAR(i: &[u8]) -> IResult<&[u8], u8> { pub fn TEXT_CHAR(i: &[u8]) -> IResult<&[u8], u8> {
todo!() todo!()