melib/imap: turn ImapResponse From to TryFrom

memfd
Manos Pitsidianakis 2020-08-24 11:46:07 +03:00
parent 94433cfc40
commit 876e1bc510
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
3 changed files with 47 additions and 27 deletions

View File

@ -49,6 +49,7 @@ use futures::lock::Mutex as FutureMutex;
use futures::stream::Stream;
use std::collections::{hash_map::DefaultHasher, BTreeMap};
use std::collections::{BTreeSet, HashMap, HashSet};
use std::convert::TryFrom;
use std::hash::Hasher;
use std::pin::Pin;
use std::str::FromStr;
@ -788,7 +789,7 @@ impl MailBackend for ImapType {
.read_response(&mut response, RequiredResponses::empty())
.await?;
}
let ret: Result<()> = ImapResponse::from(&response).into();
let ret: Result<()> = ImapResponse::try_from(response.as_str())?.into();
ret?;
let new_hash = get_path_hash!(path.as_str());
uid_store.mailboxes.lock().await.clear();
@ -845,7 +846,7 @@ impl MailBackend for ImapType {
.read_response(&mut response, RequiredResponses::empty())
.await?;
}
let ret: Result<()> = ImapResponse::from(&response).into();
let ret: Result<()> = ImapResponse::try_from(response.as_str())?.into();
ret?;
uid_store.mailboxes.lock().await.clear();
new_mailbox_fut?.await.map_err(|err| format!("Mailbox delete was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", response, err).into())
@ -884,7 +885,7 @@ impl MailBackend for ImapType {
.await?;
}
let ret: Result<()> = ImapResponse::from(&response).into();
let ret: Result<()> = ImapResponse::try_from(response.as_str())?.into();
if ret.is_ok() {
uid_store
.mailboxes
@ -936,7 +937,7 @@ impl MailBackend for ImapType {
.await?;
}
let new_hash = get_path_hash!(new_path.as_str());
let ret: Result<()> = ImapResponse::from(&response).into();
let ret: Result<()> = ImapResponse::try_from(response.as_str())?.into();
ret?;
uid_store.mailboxes.lock().await.clear();
new_mailbox_fut?.await.map_err(|err| format!("Mailbox rename was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", response, err))?;

View File

@ -29,6 +29,7 @@ use futures::io::{AsyncReadExt, AsyncWriteExt};
use native_tls::TlsConnector;
pub use smol::Async as AsyncWrapper;
use std::collections::HashSet;
use std::convert::TryFrom;
use std::future::Future;
use std::iter::FromIterator;
use std::pin::Pin;
@ -534,7 +535,7 @@ impl ImapConnection {
self.send_command(b"COMPRESS DEFLATE").await?;
self.read_response(&mut ret, RequiredResponses::empty())
.await?;
match ImapResponse::from(&ret) {
match ImapResponse::try_from(ret.as_str())? {
ImapResponse::No(code)
| ImapResponse::Bad(code)
| ImapResponse::Preauth(code)
@ -578,7 +579,7 @@ impl ImapConnection {
match self.server_conf.protocol {
ImapProtocol::IMAP { .. } => {
let r: ImapResponse = ImapResponse::from(&response);
let r: ImapResponse = ImapResponse::try_from(response.as_str())?;
match r {
ImapResponse::Bye(ref response_code) => {
self.stream = Err(MeliError::new(format!(
@ -586,31 +587,33 @@ impl ImapConnection {
response_code
)));
ret.push_str(&response);
return r.into();
}
ImapResponse::No(ref response_code) => {
//FIXME return error
debug!("Received NO response: {:?} {:?}", response_code, response);
ret.push_str(&response);
return r.into();
}
ImapResponse::Bad(ref response_code) => {
//FIXME return error
debug!("Received BAD response: {:?} {:?}", response_code, response);
ret.push_str(&response);
return r.into();
}
_ => {
/*debug!(
"check every line for required_responses: {:#?}",
&required_responses
);*/
for l in response.split_rn() {
/*debug!("check line: {}", &l);*/
if required_responses.check(l) || !self.process_untagged(l).await? {
ret.push_str(l);
}
}
_ => {}
}
/*debug!(
"check every line for required_responses: {:#?}",
&required_responses
);*/
for l in response.split_rn() {
/*debug!("check line: {}", &l);*/
if required_responses.check(l) || !self.process_untagged(l).await? {
ret.push_str(l);
}
}
r.into()
Ok(())
}
ImapProtocol::ManageSieve => {
ret.push_str(&response);

View File

@ -32,6 +32,7 @@ use nom::{
multi::{fold_many1, length_data, many0, separated_list, separated_nonempty_list},
sequence::{delimited, preceded},
};
use std::convert::TryFrom;
use std::str::FromStr;
bitflags! {
@ -252,17 +253,29 @@ pub enum ImapResponse {
Bye(ResponseCode),
}
impl<T: AsRef<str>> From<T> for ImapResponse {
fn from(val: T) -> ImapResponse {
let val: &str = val.as_ref().split_rn().last().unwrap_or(val.as_ref());
impl TryFrom<&'_ str> for ImapResponse {
type Error = MeliError;
fn try_from(val: &'_ str) -> Result<ImapResponse> {
let val: &str = val.split_rn().last().unwrap_or(val.as_ref());
debug!(&val);
let mut val = val[val.as_bytes().find(b" ").unwrap() + 1..].trim();
let mut val = val[val.as_bytes().find(b" ").ok_or_else(|| {
MeliError::new(format!(
"Expected tagged IMAP response (OK,NO,BAD, etc) but found {:?}",
val
))
})? + 1..]
.trim();
// M12 NO [CANNOT] Invalid mailbox name: Name must not have \'/\' characters (0.000 + 0.098 + 0.097 secs).\r\n
if val.ends_with(" secs).") {
val = &val[..val.as_bytes().rfind(b"(").unwrap()];
val = &val[..val.as_bytes().rfind(b"(").ok_or_else(|| {
MeliError::new(format!(
"Expected tagged IMAP response (OK,NO,BAD, etc) but found {:?}",
val
))
})?];
}
if val.starts_with("OK") {
Ok(if val.starts_with("OK") {
Self::Ok(ResponseCode::from(&val["OK ".len()..]))
} else if val.starts_with("NO") {
Self::No(ResponseCode::from(&val["NO ".len()..]))
@ -273,8 +286,11 @@ impl<T: AsRef<str>> From<T> for ImapResponse {
} else if val.starts_with("BYE") {
Self::Bye(ResponseCode::from(&val["BYE ".len()..]))
} else {
panic!("Unknown IMAP response: `{}`", val);
}
return Err(MeliError::new(format!(
"Expected tagged IMAP response (OK,NO,BAD, etc) but found {:?}",
val
)));
})
}
}
@ -295,7 +311,7 @@ impl Into<Result<()>> for ImapResponse {
#[test]
fn test_imap_response() {
assert_eq!(ImapResponse::from("M12 NO [CANNOT] Invalid mailbox name: Name must not have \'/\' characters (0.000 + 0.098 + 0.097 secs).\r\n"), ImapResponse::No(ResponseCode::Alert("Invalid mailbox name: Name must not have '/' characters".to_string())));
assert_eq!(ImapResponse::try_from("M12 NO [CANNOT] Invalid mailbox name: Name must not have \'/\' characters (0.000 + 0.098 + 0.097 secs).\r\n").unwrap(), ImapResponse::No(ResponseCode::Alert("Invalid mailbox name: Name must not have '/' characters".to_string())));
}
impl<'a> std::iter::DoubleEndedIterator for ImapLineIterator<'a> {