bytes
This commit is contained in:
parent
e212f048ef
commit
04a6d45802
4 changed files with 116 additions and 38 deletions
|
@ -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
37
imap/src/proto/prelude.rs
Normal 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)
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue