capability parser

This commit is contained in:
Michael Zhang 2021-02-22 15:33:30 -06:00
parent 4f3af86211
commit e0ca51ef79
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
17 changed files with 224 additions and 83 deletions

189
Cargo.lock generated
View file

@ -77,15 +77,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitvec"
version = "0.19.4"
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
"block-padding",
"byte-tools",
"byteorder",
"generic-array",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
]
[[package]]
@ -100,6 +109,12 @@ version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.4.2"
@ -264,6 +279,21 @@ dependencies = [
"syn",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fast_chemail"
version = "0.9.6"
@ -326,12 +356,6 @@ dependencies = [
"syn",
]
[[package]]
name = "funty"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "futures"
version = "0.3.12"
@ -427,6 +451,15 @@ dependencies = [
"slab",
]
[[package]]
name = "generic-array"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
dependencies = [
"typenum",
]
[[package]]
name = "getrandom"
version = "0.2.2"
@ -536,7 +569,7 @@ dependencies = [
"hostname",
"log",
"native-tls",
"nom 4.2.3",
"nom",
"serde",
"serde_derive",
"serde_json",
@ -566,6 +599,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "memchr"
version = "2.3.4"
@ -623,18 +662,6 @@ dependencies = [
"version_check 0.1.5",
]
[[package]]
name = "nom"
version = "6.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
dependencies = [
"bitvec",
"funty",
"memchr",
"version_check 0.9.2",
]
[[package]]
name = "ntapi"
version = "0.3.6"
@ -679,6 +706,12 @@ version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "openssl"
version = "0.10.32"
@ -712,15 +745,6 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "owning_ref"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
dependencies = [
"stable_deref_trait",
]
[[package]]
name = "panorama"
version = "0.0.1"
@ -760,9 +784,9 @@ dependencies = [
"derive_builder",
"futures",
"log",
"nom 6.1.2",
"owning_ref",
"parking_lot",
"pest",
"pest_derive",
"tokio",
"tokio-rustls",
"webpki-roots",
@ -793,6 +817,49 @@ dependencies = [
"winapi",
]
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pest_meta"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
dependencies = [
"maplit",
"pest",
"sha-1",
]
[[package]]
name = "pin-project"
version = "1.0.5"
@ -891,12 +958,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rand"
version = "0.8.3"
@ -1093,6 +1154,18 @@ dependencies = [
"serde",
]
[[package]]
name = "sha-1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
dependencies = [
"block-buffer",
"digest",
"fake-simd",
"opaque-debug",
]
[[package]]
name = "signal-hook"
version = "0.1.17"
@ -1142,12 +1215,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.8.0"
@ -1195,12 +1262,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
version = "3.2.0"
@ -1314,6 +1375,18 @@ dependencies = [
"serde",
]
[[package]]
name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-segmentation"
version = "1.7.1"
@ -1482,12 +1555,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "wyz"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
[[package]]
name = "xdg"
version = "2.2.0"

View file

@ -16,9 +16,11 @@ anyhow = "1.0.38"
derive_builder = "0.9.0"
futures = "0.3.12"
log = "0.4.14"
nom = { version = "6.1.2", default-features = false, features = ["std"] }
owning_ref = "0.4.1"
# nom = { version = "6.1.2", default-features = false, features = ["std"] }
# owning_ref = "0.4.1"
parking_lot = "0.11.1"
pest = "2.1.3"
pest_derive = "2.1.0"
tokio = { version = "1.1.1", features = ["full"] }
tokio-rustls = "0.22.0"
webpki-roots = "0.21.0"

View file

@ -6,9 +6,12 @@ extern crate derive_builder;
extern crate futures;
#[macro_use]
extern crate log;
#[macro_use]
extern crate pest_derive;
pub mod client;
pub mod command;
pub mod parser;
pub mod response;
// pub mod builders;

25
imap/src/oldparser/mod.rs Normal file
View file

@ -0,0 +1,25 @@
use crate::types::Response;
use nom::{branch::alt, IResult};
pub mod core;
pub mod bodystructure;
pub mod rfc3501;
pub mod rfc4315;
pub mod rfc4551;
pub mod rfc5161;
pub mod rfc5464;
pub mod rfc7162;
#[cfg(test)]
mod tests;
pub fn parse_response(msg: &[u8]) -> ParseResult {
alt((
rfc3501::continue_req,
rfc3501::response_data,
rfc3501::response_tagged,
))(msg)
}
pub type ParseResult<'a> = IResult<&'a [u8], Response<'a>>;

View file

@ -1,25 +1,52 @@
use crate::types::Response;
use nom::{branch::alt, IResult};
use pest::{error::Error, Parser};
pub mod core;
use crate::response::*;
pub mod bodystructure;
pub mod rfc3501;
pub mod rfc4315;
pub mod rfc4551;
pub mod rfc5161;
pub mod rfc5464;
pub mod rfc7162;
#[derive(Parser)]
#[grammar = "parser/rfc3501.pest"]
struct Rfc3501;
#[cfg(test)]
mod tests;
pub fn parse_response(msg: &[u8]) -> ParseResult {
alt((
rfc3501::continue_req,
rfc3501::response_data,
rfc3501::response_tagged,
))(msg)
pub fn parse_capability(s: &str) -> Result<Capability, Error<Rule>> {
let mut pairs = Rfc3501::parse(Rule::capability, s)?;
let pair = pairs.next().unwrap();
let cap = match pair.as_rule() {
Rule::capability => {
let mut inner = pair.into_inner();
let pair = inner.next().unwrap();
match pair.as_rule() {
Rule::auth_type => Capability::Auth(pair.as_str().to_owned()),
Rule::atom => match pair.as_str() {
"IMAP4rev1" => Capability::Imap4rev1,
s => Capability::Atom(s.to_owned()),
},
_ => unreachable!("{:?}", pair),
}
}
_ => unreachable!("{:?}", pair),
};
Ok(cap)
}
pub type ParseResult<'a> = IResult<&'a [u8], Response<'a>>;
#[cfg(test)]
#[rustfmt::skip]
mod tests {
use super::*;
use crate::response::*;
use pest::Parser;
#[test]
fn test_capability() {
assert_eq!(parse_capability("IMAP4rev1"), Ok(Capability::Imap4rev1));
assert_eq!(parse_capability("LOGINDISABLED"), Ok(Capability::Atom("LOGINDISABLED".to_owned())));
assert_eq!(parse_capability("AUTH=PLAIN"), Ok(Capability::Auth("PLAIN".to_owned())));
assert!(parse_capability("(OSU)").is_err());
assert!(parse_capability("\x01HELLO").is_err());
}
#[test]
fn test_nil() {
assert!(Rfc3501::parse(Rule::nil, "NIL").is_ok());
assert!(Rfc3501::parse(Rule::nil, "anything else").is_err());
}
}

View file

@ -0,0 +1,17 @@
// formal syntax from https://tools.ietf.org/html/rfc3501#section-9
atom = @{ atom_char{1,} }
atom_char = @{ !atom_specials ~ char }
atom_specials = @{ "(" | ")" | "{" | sp | ctl | list_wildcards | quoted_specials | resp_specials }
auth_type = { atom }
capability = ${ "AUTH=" ~ auth_type | atom }
list_wildcards = @{ "%" | "*" }
quoted_specials = @{ dquote | "\\" }
resp_specials = @{ "]" }
nil = { "NIL" }
// core rules from https://tools.ietf.org/html/rfc2234#section-6.1
char = @{ '\x01'..'\x7f' }
ctl = @{ '\x00'..'\x1f' | "\x7f" }
dquote = @{ "\"" }
sp = @{ " " }