This commit is contained in:
Michael Zhang 2021-08-07 20:48:21 -05:00
parent e212f048ef
commit 04a6d45802
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
4 changed files with 116 additions and 38 deletions

View file

@ -1,3 +1,5 @@
#![allow(non_snake_case, dead_code)] #![allow(non_snake_case, dead_code)]
mod prelude;
mod rfc2234; mod rfc2234;
mod rfc3501;

37
imap/src/proto/prelude.rs Normal file
View file

@ -0,0 +1,37 @@
use std::ops::RangeFrom;
use nom::{
error::{ErrorKind, ParseError},
Err, IResult, InputIter, Needed, Parser, Slice,
};
pub fn skip<E, F, I: Clone, O>(mut f: F) -> impl FnMut(I) -> IResult<I, (), E>
where
F: Parser<I, O, E>,
{
move |i: I| match f.parse(i.clone()) {
Ok(_) => Ok((i, ())),
Err(err) => Err(err),
}
}
pub fn satisfy<F, I, E, T>(f: F) -> impl Fn(I) -> IResult<I, T, E>
where
I: Slice<RangeFrom<usize>> + InputIter<Item = T>,
F: Fn(T) -> bool,
E: ParseError<I>,
T: Copy,
{
move |i: I| match i.iter_elements().next().map(|t| (f(t), t)) {
Some((true, ft)) => Ok((i.slice(1..), ft)),
Some((false, _)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Satisfy))),
None => Err(Err::Incomplete(Needed::Unknown)),
}
}
pub fn byte<I, E: ParseError<I>>(b: u8) -> impl Fn(I) -> IResult<I, u8, E>
where
I: Slice<RangeFrom<usize>> + InputIter<Item = u8>,
{
satisfy(move |c| c == b)
}

View file

@ -2,64 +2,56 @@
use nom::{ use nom::{
branch::alt, branch::alt,
character::streaming::{anychar, char, satisfy}, character::streaming::{anychar},
multi::many0, multi::many0,
sequence::pair, sequence::pair,
IResult, Parser, IResult,
}; };
pub fn skip<E, F, I: Clone, O>(mut f: F) -> impl FnMut(I) -> IResult<I, (), E> use super::prelude::{satisfy, skip, byte};
where
F: Parser<I, O, E>, pub fn ALPHA(i: &[u8]) -> IResult<&[u8], u8> {
{ satisfy(|c| (c >= b'a' && c <= b'z') || (c >= b'A' && c <= b'Z'))(i)
move |i: I| match f.parse(i.clone()) {
Ok(_) => Ok((i, ())),
Err(err) => Err(err),
}
} }
pub fn ALPHA(i: &[u8]) -> IResult<&[u8], char> { pub fn BIT(i: &[u8]) -> IResult<&[u8], u8> {
satisfy(|c| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))(i) satisfy(|c| c == b'0' || c == b'1')(i)
} }
pub fn BIT(i: &[u8]) -> IResult<&[u8], char> { pub fn CHAR(i: &[u8]) -> IResult<&[u8], u8> {
satisfy(|c| c == '0' || c == '1')(i) satisfy(|c| c != b'\0')(i)
} }
pub fn CHAR(i: &[u8]) -> IResult<&[u8], char> { pub fn CR(i: &[u8]) -> IResult<&[u8], u8> {
satisfy(|c| c != '\0')(i) byte(b'\x0d')(i)
} }
pub fn CR(i: &[u8]) -> IResult<&[u8], char> { pub fn CRLF(i: &[u8]) -> IResult<&[u8], (u8, u8)> {
char('\x0d')(i)
}
pub fn CRLF(i: &[u8]) -> IResult<&[u8], (char, char)> {
pair(CR, LF)(i) pair(CR, LF)(i)
} }
pub fn CTL(i: &[u8]) -> IResult<&[u8], char> { pub fn CTL(i: &[u8]) -> IResult<&[u8], u8> {
satisfy(|c| c <= '\x1f' || c == '\x7f')(i) satisfy(|c| c <= b'\x1f' || c == b'\x7f')(i)
} }
pub fn DIGIT(i: &[u8]) -> IResult<&[u8], char> { pub fn DIGIT(i: &[u8]) -> IResult<&[u8], u8> {
satisfy(|c| c >= '\x30' && c <= '\x39')(i) satisfy(|c| c >= b'\x30' && c <= b'\x39')(i)
} }
pub fn DQUOTE(i: &[u8]) -> IResult<&[u8], char> { pub fn DQUOTE(i: &[u8]) -> IResult<&[u8], u8> {
char('\x22')(i) byte(b'\x22')(i)
} }
pub fn HEXDIG(i: &[u8]) -> IResult<&[u8], char> { pub fn HEXDIG(i: &[u8]) -> IResult<&[u8], u8> {
alt((DIGIT, satisfy(|c| c >= 'A' && c <= 'F')))(i) alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F')))(i)
} }
pub fn HTAB(i: &[u8]) -> IResult<&[u8], char> { pub fn HTAB(i: &[u8]) -> IResult<&[u8], u8> {
char('\x09')(i) byte(b'\x09')(i)
} }
pub fn LF(i: &[u8]) -> IResult<&[u8], char> { pub fn LF(i: &[u8]) -> IResult<&[u8], u8> {
char('\x0a')(i) byte(b'\x0a')(i)
} }
pub fn LWSP(i: &[u8]) -> IResult<&[u8], ()> { pub fn LWSP(i: &[u8]) -> IResult<&[u8], ()> {
@ -70,14 +62,14 @@ pub fn OCTET(i: &[u8]) -> IResult<&[u8], char> {
anychar(i) anychar(i)
} }
pub fn SP(i: &[u8]) -> IResult<&[u8], char> { pub fn SP(i: &[u8]) -> IResult<&[u8], u8> {
char('\x20')(i) byte(b'\x20')(i)
} }
pub fn VCHAR(i: &[u8]) -> IResult<&[u8], char> { pub fn VCHAR(i: &[u8]) -> IResult<&[u8], u8> {
satisfy(|c| c >= '\x21' && c <= '\x7e')(i) satisfy(|c| c >= b'\x21' && c <= b'\x7e')(i)
} }
pub fn WSP(i: &[u8]) -> IResult<&[u8], char> { pub fn WSP(i: &[u8]) -> IResult<&[u8], u8> {
alt((SP, HTAB))(i) alt((SP, HTAB))(i)
} }

View file

@ -1,2 +1,49 @@
//! Grammar from https://datatracker.ietf.org/doc/html/rfc3501#section-9 //! Grammar from https://datatracker.ietf.org/doc/html/rfc3501#section-9
use nom::{
branch::alt,
bytes::streaming::{tag_no_case, take},
character::streaming::char,
combinator::{map, map_res},
multi::{many0, many1},
sequence::delimited,
IResult,
};
use super::rfc2234::{DIGIT, DQUOTE};
/// literal = "{" number "}" CRLF *CHAR8
/// ; Number represents the number of CHAR8s
pub fn literal(i: &[u8]) -> IResult<&[u8], Vec<u8>> {
let mut length_of = delimited(char('{'), number, char('}'));
let (i, length) = length_of(i)?;
map(take(length), |s: &[u8]| s.to_vec())(i)
}
pub fn nil(i: &[u8]) -> IResult<&[u8], &[u8]> {
tag_no_case("NIL")(i)
}
pub fn nstring(i: &[u8]) -> IResult<&[u8], Option<Vec<u8>>> {
alt((map(string, Some), map(nil, |_| None)))(i)
}
pub fn number(i: &[u8]) -> IResult<&[u8], u32> {
map_res(map_res(many1(DIGIT), String::from_utf8), |s| s.parse::<u32>())(i)
}
pub fn quoted(i: &[u8]) -> IResult<&[u8], Vec<u8>> {
delimited(DQUOTE, many0(QUOTED_CHAR), DQUOTE)(i)
}
pub fn QUOTED_CHAR(i: &[u8]) -> IResult<&[u8], u8> {
todo!()
}
pub fn string(i: &[u8]) -> IResult<&[u8], Vec<u8>> {
alt((quoted, literal))(i)
}
pub fn TEXT_CHAR(i: &[u8]) -> IResult<&[u8], u8> {
todo!()
}