diff --git a/imap/src/proto/macros.rs b/imap/src/proto/macros.rs new file mode 100644 index 0000000..308beaf --- /dev/null +++ b/imap/src/proto/macros.rs @@ -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) + } + }; +} diff --git a/imap/src/proto/mod.rs b/imap/src/proto/mod.rs index 7f172d0..ceabbbf 100644 --- a/imap/src/proto/mod.rs +++ b/imap/src/proto/mod.rs @@ -1,5 +1,8 @@ #![allow(non_snake_case, dead_code)] +#[macro_use] +mod macros; + // data types pub mod response; diff --git a/imap/src/proto/rfc2234.rs b/imap/src/proto/rfc2234.rs index eb91c3d..4ab3de1 100644 --- a/imap/src/proto/rfc2234.rs +++ b/imap/src/proto/rfc2234.rs @@ -1,69 +1,37 @@ //! 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}; -pub fn ALPHA(i: &[u8]) -> IResult<&[u8], u8> { - satisfy(|c| (c >= b'a' && c <= b'z') || (c >= b'A' && c <= b'Z'))(i) -} +rule!(pub ALPHA : u8 => satisfy(|c| (c >= b'a' && c <= b'z') || (c >= b'A' && c <= b'Z'))); -pub fn BIT(i: &[u8]) -> IResult<&[u8], u8> { - satisfy(|c| c == b'0' || c == b'1')(i) -} +rule!(pub BIT : u8 => satisfy(|c| c == b'0' || c == b'1')); -pub fn CHAR(i: &[u8]) -> IResult<&[u8], u8> { - satisfy(|c| c != b'\0')(i) -} +rule!(pub CHAR : u8 => satisfy(|c| c != b'\0')); -pub fn CR(i: &[u8]) -> IResult<&[u8], u8> { - byte(b'\x0d')(i) -} +rule!(pub CR : u8 => byte(b'\x0d')); -pub fn CRLF(i: &[u8]) -> IResult<&[u8], (u8, u8)> { - pair(CR, LF)(i) -} +rule!(pub CRLF : (u8, u8) => pair(CR, LF)); -pub fn CTL(i: &[u8]) -> IResult<&[u8], u8> { - satisfy(|c| c <= b'\x1f' || c == b'\x7f')(i) -} +rule!(pub CTL : u8 => satisfy(|c| c <= b'\x1f' || c == b'\x7f')); -pub fn DIGIT(i: &[u8]) -> IResult<&[u8], u8> { - satisfy(|c| c >= b'\x30' && c <= b'\x39')(i) -} +rule!(pub DIGIT : u8 => satisfy(|c| c >= b'\x30' && c <= b'\x39')); -pub fn DQUOTE(i: &[u8]) -> IResult<&[u8], u8> { - byte(b'\x22')(i) -} +rule!(pub DQUOTE : u8 => byte(b'\x22')); -pub fn HEXDIG(i: &[u8]) -> IResult<&[u8], u8> { - alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F')))(i) -} +rule!(pub HEXDIG : u8 => alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F')))); -pub fn HTAB(i: &[u8]) -> IResult<&[u8], u8> { - byte(b'\x09')(i) -} +rule!(pub HTAB : u8 => byte(b'\x09')); -pub fn LF(i: &[u8]) -> IResult<&[u8], u8> { - byte(b'\x0a')(i) -} +rule!(pub LF : u8 => byte(b'\x0a')); -pub fn LWSP(i: &[u8]) -> IResult<&[u8], ()> { - skip(many0(alt((skip(WSP), skip(pair(CRLF, WSP))))))(i) -} +rule!(pub LWSP : () => skip(many0(alt((skip(WSP), skip(pair(CRLF, WSP))))))); -pub fn OCTET(i: &[u8]) -> IResult<&[u8], char> { - anychar(i) -} +rule!(pub OCTET : char => anychar); -pub fn SP(i: &[u8]) -> IResult<&[u8], u8> { - byte(b'\x20')(i) -} +rule!(pub SP : u8 => byte(b'\x20')); -pub fn VCHAR(i: &[u8]) -> IResult<&[u8], u8> { - satisfy(|c| c >= b'\x21' && c <= b'\x7e')(i) -} +rule!(pub VCHAR : u8 => satisfy(|c| c >= b'\x21' && c <= b'\x7e')); -pub fn WSP(i: &[u8]) -> IResult<&[u8], u8> { - alt((SP, HTAB))(i) -} +rule!(pub WSP : u8 => alt((SP, HTAB))); diff --git a/imap/src/proto/rfc3501.rs b/imap/src/proto/rfc3501.rs index 5237f42..8191e4e 100644 --- a/imap/src/proto/rfc3501.rs +++ b/imap/src/proto/rfc3501.rs @@ -11,6 +11,17 @@ use nom::{ }; use super::rfc2234::{CRLF, DIGIT, DQUOTE}; +use super::parsers::byte; + +rule!(pub astring : Vec => alt((many1(ASTRING_CHAR), string))); + +rule!(pub ASTRING_CHAR : u8 => alt((ATOM_CHAR, resp_specials))); + +rule!(pub atom : Vec => many1(ATOM_CHAR)); + +pub fn ATOM_CHAR(i: &[u8]) -> IResult<&[u8], u8> { + todo!() +} /// literal = "{" number "}" CRLF *CHAR8 /// ; Number represents the number of CHAR8s @@ -29,13 +40,9 @@ fn test_literal() { ); } -pub fn nil(i: &[u8]) -> IResult<&[u8], &[u8]> { - tag_no_case("NIL")(i) -} +rule!(pub nil : &[u8] => tag_no_case("NIL")); -pub fn nstring(i: &[u8]) -> IResult<&[u8], Option>> { - alt((map(string, Some), map(nil, |_| None)))(i) -} +rule!(pub nstring : Option> => alt((map(string, Some), map(nil, |_| None)))); pub fn number(i: &[u8]) -> IResult<&[u8], u32> { map_res(map_res(many1(DIGIT), String::from_utf8), |s| { @@ -43,17 +50,15 @@ pub fn number(i: &[u8]) -> IResult<&[u8], u32> { })(i) } -pub fn quoted(i: &[u8]) -> IResult<&[u8], Vec> { - delimited(DQUOTE, many0(QUOTED_CHAR), DQUOTE)(i) -} +rule!(pub quoted : Vec => delimited(DQUOTE, many0(QUOTED_CHAR), DQUOTE)); pub fn QUOTED_CHAR(i: &[u8]) -> IResult<&[u8], u8> { todo!() } -pub fn string(i: &[u8]) -> IResult<&[u8], Vec> { - alt((quoted, literal))(i) -} +rule!(pub resp_specials : u8 => byte(b']')); + +rule!(pub string : Vec => alt((quoted, literal))); pub fn TEXT_CHAR(i: &[u8]) -> IResult<&[u8], u8> { todo!()