Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependencies and fixing some clippy warnings #1

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/target
Cargo.lock
11 changes: 9 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ authors = ["Andy Grover <[email protected]>"]
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Support for parsing ManageSieve protocol (RFC 5804)"
documentation = "https://docs.rs/managesieve/0.1.1/managesieve/"
readme = "README.md"
homepage = "https://github.com/agrover/managesieve"
repository = "https://github.com/agrover/managesieve"
keywords = ["email", "sieve", "managesieve", "filter", "parser"]
categories = ["parser-implementations", "parsing", "email", "api-bindings"]

[dependencies]
nom = "6.2.0"
either = "1.6.1"
nom = "7.1"
either = "1.6"
thiserror = "1.0"
33 changes: 18 additions & 15 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use nom::{
IResult,
};

use crate::types::{OkNoBye, QuotaVariant, Response, ResponseCode, SieveUrl};
use crate::types::{
MSResult, MSResultList, OkNoBye, QuotaVariant, Response, ResponseCode, SieveUrl,
};

pub(crate) fn ok(input: &str) -> IResult<&str, OkNoBye> {
value(OkNoBye::Ok, tag_no_case("OK"))(input)
Expand Down Expand Up @@ -71,7 +73,7 @@ fn atom(input: &str) -> IResult<&str, ResponseCode> {
#[test]
fn test_atom() {
assert!(matches!(atom("SASL"), Ok(("", ResponseCode::Sasl))));
assert!(matches!(atom("ABCDE"), Err(_)));
assert!(atom("ABCDE").is_err());
}

fn literal_s2c_len(input: &str) -> IResult<&str, usize> {
Expand All @@ -89,7 +91,7 @@ fn literal_s2c_len(input: &str) -> IResult<&str, usize> {
fn test_literal_s2c_len() {
assert!(matches!(literal_s2c_len("{3}\r\n"), Ok(("", 3))));
assert!(matches!(literal_s2c_len("{0}\r\n"), Ok(("", 0))));
assert!(matches!(literal_s2c_len("{3}"), Err(_)));
assert!(literal_s2c_len("{3}").is_err());
assert!(matches!(literal_s2c_len("{3}\r\nab"), Ok(("ab", 3))));
}

Expand Down Expand Up @@ -295,11 +297,11 @@ fn test_response() {
response("BYE\r\n").unwrap();
response("ok (QUOTA)\r\n").unwrap();
response("ok (QUOTA) \"hello\"\r\n").unwrap();
assert!(matches!(response("ok"), Err(_)));
assert!(matches!(response(" ok\r\n"), Err(_)));
assert!(matches!(response("ok (\r\n"), Err(_)));
assert!(matches!(response("ok (QUOTA\r\n"), Err(_)));
assert!(matches!(response("ok (QUOTA/)\r\n"), Err(_)));
assert!(response("ok").is_err());
assert!(response(" ok\r\n").is_err());
assert!(response("ok (\r\n").is_err());
assert!(response("ok (QUOTA\r\n").is_err());
assert!(response("ok (QUOTA/)\r\n").is_err());
}

pub fn response_getscript(input: &str) -> IResult<&str, (Option<String>, Response)> {
Expand All @@ -316,10 +318,10 @@ pub fn response_getscript(input: &str) -> IResult<&str, (Option<String>, Respons
fn test_response_getscript() {
response_getscript("\"hello\"\r\nOK\r\n").unwrap();
response_getscript("NO\r\n").unwrap();
assert!(matches!(response_getscript("\"hello\"\r\nBYE\r\n"), Err(_)));
assert!(response_getscript("\"hello\"\r\nBYE\r\n").is_err());
}

pub fn response_listscripts(input: &str) -> IResult<&str, (Vec<(String, bool)>, Response)> {
pub fn response_listscripts(input: &str) -> MSResultList<(String, bool)> {
pair(
many0(terminated(
pair(
Expand Down Expand Up @@ -357,7 +359,8 @@ fn test_single_capability() {

pub fn response_capability(
input: &str,
) -> IResult<&str, (Vec<(String, Option<String>)>, Response)> {
//) -> IResult<&str, (Vec<(String, Option<String>)>, Response)> {
) -> MSResultList<(String, Option<String>)> {
pair(many0(single_capability), response)(input)
}

Expand All @@ -372,7 +375,7 @@ fn test_response_capability_2() {
response_capability(inc1).unwrap();
}

pub fn response_starttls(input: &str) -> IResult<&str, (Vec<(String, Option<String>)>, Response)> {
pub fn response_starttls(input: &str) -> MSResultList<(String, Option<String>)> {
alt((
preceded(response_ok, response_capability),
map(response_nobye, |r| (Vec::new(), r)),
Expand All @@ -389,8 +392,8 @@ fn test_response_starttls() {
/// response.
pub fn response_authenticate_initial(input: &str) -> IResult<&str, Either<String, Response>> {
alt((
map(terminated(sievestring_s2c, crlf), |s| Either::Left(s)),
map(response_nobye, |r| Either::Right(r)),
map(terminated(sievestring_s2c, crlf), Either::Left),
map(response_nobye, Either::Right),
))(input)
}

Expand All @@ -404,7 +407,7 @@ fn test_response_authenticate_initial() {
/// capabilities if OK.
pub fn response_authenticate_complete(
input: &str,
) -> IResult<&str, (Option<Vec<(String, Option<String>)>>, Response)> {
) -> MSResult<Option<Vec<(String, Option<String>)>>> {
alt((
map(
pair(response_ok, opt(response_capability)),
Expand Down
42 changes: 27 additions & 15 deletions src/types.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
use std::convert::TryFrom;
use std::fmt::Display;
use std::io::{self, ErrorKind};
use std::string::ToString;

use nom;
use nom::IResult;

use crate::parser as p;

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, thiserror::Error)]
pub enum Error {
#[error("incomplete response")]
IncompleteResponse,
#[error("invalid response")]
InvalidResponse,
#[error("invalid input")]
InvalidInput,
}

#[derive(Debug, PartialEq)]
impl<T> From<nom::Err<T>> for Error {
fn from(value: nom::Err<T>) -> Self {
match value {
nom::Err::Incomplete(_) => Self::IncompleteResponse,
nom::Err::Error(_) => Self::InvalidInput,
nom::Err::Failure(_) => Self::InvalidInput,
}
}
}

#[derive(Debug, PartialEq, Clone)]
pub enum Capability {
Implementation(String),
Sasl(Vec<String>),
Expand All @@ -34,10 +48,10 @@ impl TryFrom<(&str, Option<&str>)> for Capability {
let (cap, rest) = s;

let err = || io::Error::new(ErrorKind::InvalidInput, "Invalid Capability");
let unwrap_rest = || rest.map(|o| o.to_owned()).ok_or_else(|| err());
let unwrap_rest = || rest.map(|o| o.to_owned()).ok_or_else(err);
let unwrap_rest_vec = || {
rest.map(|r| r.split(' ').map(|x| x.to_string()).collect())
.ok_or_else(|| err())
.ok_or_else(err)
};

Ok(match cap {
Expand Down Expand Up @@ -129,7 +143,7 @@ impl Command {
}

fn to_sieve_name(s: &str) -> Result<String, Error> {
if s.chars().find(|c| p::is_bad_sieve_name_char(*c)).is_some() {
if s.chars().any(p::is_bad_sieve_name_char) {
return Err(Error::InvalidInput);
}

Expand Down Expand Up @@ -225,14 +239,7 @@ pub enum ResponseCode {
}

fn response_oknobye(input: &str) -> Result<(&str, Response), Error> {
match p::response(input) {
Ok((left, response)) => Ok((left, response)),
Err(e) => match e {
nom::Err::Incomplete(_) => Err(Error::IncompleteResponse),
nom::Err::Error(_) => Err(Error::InvalidResponse),
nom::Err::Failure(_) => Err(Error::InvalidResponse),
},
}
p::response(input).map_err(Error::from)
}

pub fn response_authenticate(_input: &str) -> Result<OkNoBye, Error> {
Expand All @@ -258,10 +265,12 @@ pub fn response_setactive(input: &str) -> Result<(&str, Response), Error> {
response_oknobye(input)
}

pub type ScriptList = Vec<(String, bool)>;

/// Parses text returned from the server in response to the LISTSCRIPTS command.
/// Returns list of scripts and a bool indicating if that script is the active
/// script.
pub fn response_listscripts(input: &str) -> Result<(&str, Vec<(String, bool)>, Response), Error> {
pub fn response_listscripts(input: &str) -> Result<(&str, ScriptList, Response), Error> {
match p::response_listscripts(input) {
Ok((left, (s, resp))) => {
if s.iter().filter(|(_, is_active)| *is_active).count() > 1 {
Expand Down Expand Up @@ -350,3 +359,6 @@ pub fn response_noop(input: &str) -> Result<(&str, Response), Error> {
pub fn response_unauthenticate(input: &str) -> Result<(&str, Response), Error> {
response_oknobye(input)
}

pub type MSResult<'a, T> = IResult<&'a str, (T, Response)>;
pub type MSResultList<'a, T> = IResult<&'a str, (Vec<T>, Response)>;