melib/error.rs: switch summary<->details identifiers

They are more intuitive like this.
This commit is contained in:
Manos Pitsidianakis 2022-09-02 12:12:12 +03:00
parent aa99b0d787
commit eb5949dc9b
6 changed files with 73 additions and 46 deletions

View File

@ -222,8 +222,8 @@ impl Backends {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum BackendEvent { pub enum BackendEvent {
Notice { Notice {
description: Option<String>, description: String,
content: String, content: Option<String>,
level: crate::LoggingLevel, level: crate::LoggingLevel,
}, },
Refresh(RefreshEvent), Refresh(RefreshEvent),
@ -233,8 +233,8 @@ pub enum BackendEvent {
impl From<MeliError> for BackendEvent { impl From<MeliError> for BackendEvent {
fn from(val: MeliError) -> BackendEvent { fn from(val: MeliError) -> BackendEvent {
BackendEvent::Notice { BackendEvent::Notice {
description: val.summary.as_ref().map(|s| s.to_string()), description: val.summary.to_string(),
content: val.to_string(), content: Some(val.to_string()),
level: crate::LoggingLevel::ERROR, level: crate::LoggingLevel::ERROR,
} }
} }

View File

@ -746,8 +746,8 @@ impl ImapConnection {
(self.uid_store.event_consumer)( (self.uid_store.event_consumer)(
self.uid_store.account_hash, self.uid_store.account_hash,
crate::backends::BackendEvent::Notice { crate::backends::BackendEvent::Notice {
description: None, description: response_code.to_string(),
content: response_code.to_string(), content: None,
level: crate::logging::LoggingLevel::ERROR, level: crate::logging::LoggingLevel::ERROR,
}, },
); );
@ -763,8 +763,8 @@ impl ImapConnection {
(self.uid_store.event_consumer)( (self.uid_store.event_consumer)(
self.uid_store.account_hash, self.uid_store.account_hash,
crate::backends::BackendEvent::Notice { crate::backends::BackendEvent::Notice {
description: None, description: response_code.to_string(),
content: response_code.to_string(), content: None,
level: crate::logging::LoggingLevel::ERROR, level: crate::logging::LoggingLevel::ERROR,
}, },
); );

View File

@ -85,14 +85,18 @@ impl ErrorKind {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MeliError { pub struct MeliError {
pub summary: Option<Cow<'static, str>>, pub summary: Cow<'static, str>,
pub details: Cow<'static, str>, pub details: Option<Cow<'static, str>>,
pub source: Option<std::sync::Arc<dyn Error + Send + Sync + 'static>>, pub source: Option<std::sync::Arc<dyn Error + Send + Sync + 'static>>,
pub kind: ErrorKind, pub kind: ErrorKind,
} }
pub trait IntoMeliError { pub trait IntoMeliError {
fn set_err_summary<M>(self, msg: M) -> MeliError fn set_err_summary<M>(self, msg: M) -> MeliError
where
M: Into<Cow<'static, str>>;
fn set_err_details<M>(self, msg: M) -> MeliError
where where
M: Into<Cow<'static, str>>; M: Into<Cow<'static, str>>;
fn set_err_kind(self, kind: ErrorKind) -> MeliError; fn set_err_kind(self, kind: ErrorKind) -> MeliError;
@ -117,6 +121,15 @@ impl<I: Into<MeliError>> IntoMeliError for I {
err.set_summary(msg) err.set_summary(msg)
} }
#[inline]
fn set_err_details<M>(self, msg: M) -> MeliError
where
M: Into<Cow<'static, str>>,
{
let err: MeliError = self.into();
err.set_details(msg)
}
#[inline] #[inline]
fn set_err_kind(self, kind: ErrorKind) -> MeliError { fn set_err_kind(self, kind: ErrorKind) -> MeliError {
let err: MeliError = self.into(); let err: MeliError = self.into();
@ -146,21 +159,33 @@ impl MeliError {
M: Into<Cow<'static, str>>, M: Into<Cow<'static, str>>,
{ {
MeliError { MeliError {
summary: None, summary: msg.into(),
details: msg.into(), details: None,
source: None, source: None,
kind: ErrorKind::None, kind: ErrorKind::None,
} }
} }
pub fn set_details<M>(mut self, details: M) -> MeliError
where
M: Into<Cow<'static, str>>,
{
if let Some(old_details) = self.details.as_ref() {
self.details = Some(format!("{}. {}", old_details, details.into()).into());
} else {
self.details = Some(details.into());
}
self
}
pub fn set_summary<M>(mut self, summary: M) -> MeliError pub fn set_summary<M>(mut self, summary: M) -> MeliError
where where
M: Into<Cow<'static, str>>, M: Into<Cow<'static, str>>,
{ {
if let Some(old_summary) = self.summary.take() { if self.summary.is_empty() {
self.summary = Some(format!("{}. {}", old_summary, summary.into()).into()); self.summary = summary.into();
} else { } else {
self.summary = Some(summary.into()); self.summary = format!("{}. {}", self.summary, summary.into()).into();
} }
self self
} }
@ -181,10 +206,10 @@ impl MeliError {
impl fmt::Display for MeliError { impl fmt::Display for MeliError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(summary) = self.summary.as_ref() { writeln!(f, "Summary: {}", self.summary)?;
writeln!(f, "Summary: {}", summary)?; if let Some(details) = self.details.as_ref() {
write!(f, "{}", details)?;
} }
write!(f, "{}", self.details)?;
if let Some(source) = self.source.as_ref() { if let Some(source) = self.source.as_ref() {
write!(f, "\nCaused by: {}", source)?; write!(f, "\nCaused by: {}", source)?;
} }
@ -205,7 +230,7 @@ impl From<io::Error> for MeliError {
#[inline] #[inline]
fn from(kind: io::Error) -> MeliError { fn from(kind: io::Error) -> MeliError {
MeliError::new(kind.to_string()) MeliError::new(kind.to_string())
.set_summary(format!("{:?}", kind.kind())) .set_details(kind.kind().to_string())
.set_source(Some(Arc::new(kind))) .set_source(Some(Arc::new(kind)))
.set_kind(ErrorKind::OSError) .set_kind(ErrorKind::OSError)
} }
@ -214,21 +239,21 @@ impl From<io::Error> for MeliError {
impl<'a> From<Cow<'a, str>> for MeliError { impl<'a> From<Cow<'a, str>> for MeliError {
#[inline] #[inline]
fn from(kind: Cow<'_, str>) -> MeliError { fn from(kind: Cow<'_, str>) -> MeliError {
MeliError::new(format!("{:?}", kind)) MeliError::new(kind.to_string())
} }
} }
impl From<string::FromUtf8Error> for MeliError { impl From<string::FromUtf8Error> for MeliError {
#[inline] #[inline]
fn from(kind: string::FromUtf8Error) -> MeliError { fn from(kind: string::FromUtf8Error) -> MeliError {
MeliError::new(format!("{:?}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
impl From<str::Utf8Error> for MeliError { impl From<str::Utf8Error> for MeliError {
#[inline] #[inline]
fn from(kind: str::Utf8Error) -> MeliError { fn from(kind: str::Utf8Error) -> MeliError {
MeliError::new(format!("{:?}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
//use std::option; //use std::option;
@ -242,7 +267,7 @@ impl From<str::Utf8Error> for MeliError {
impl<T> From<std::sync::PoisonError<T>> for MeliError { impl<T> From<std::sync::PoisonError<T>> for MeliError {
#[inline] #[inline]
fn from(kind: std::sync::PoisonError<T>) -> MeliError { fn from(kind: std::sync::PoisonError<T>) -> MeliError {
MeliError::new(format!("{}", kind)) MeliError::new(kind.to_string()).set_kind(ErrorKind::Bug)
} }
} }
@ -252,7 +277,9 @@ impl<T: Sync + Send + 'static + core::fmt::Debug> From<native_tls::HandshakeErro
{ {
#[inline] #[inline]
fn from(kind: native_tls::HandshakeError<T>) -> MeliError { fn from(kind: native_tls::HandshakeError<T>) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string())
.set_source(Some(Arc::new(kind)))
.set_kind(ErrorKind::Network)
} }
} }
@ -260,14 +287,16 @@ impl<T: Sync + Send + 'static + core::fmt::Debug> From<native_tls::HandshakeErro
impl From<native_tls::Error> for MeliError { impl From<native_tls::Error> for MeliError {
#[inline] #[inline]
fn from(kind: native_tls::Error) -> MeliError { fn from(kind: native_tls::Error) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string())
.set_source(Some(Arc::new(kind)))
.set_kind(ErrorKind::Network)
} }
} }
impl From<std::num::ParseIntError> for MeliError { impl From<std::num::ParseIntError> for MeliError {
#[inline] #[inline]
fn from(kind: std::num::ParseIntError) -> MeliError { fn from(kind: std::num::ParseIntError) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
@ -283,35 +312,35 @@ impl From<isahc::Error> for MeliError {
impl From<serde_json::error::Error> for MeliError { impl From<serde_json::error::Error> for MeliError {
#[inline] #[inline]
fn from(kind: serde_json::error::Error) -> MeliError { fn from(kind: serde_json::error::Error) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
impl From<Box<dyn Error + Sync + Send + 'static>> for MeliError { impl From<Box<dyn Error + Sync + Send + 'static>> for MeliError {
#[inline] #[inline]
fn from(kind: Box<dyn Error + Sync + Send + 'static>) -> MeliError { fn from(kind: Box<dyn Error + Sync + Send + 'static>) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(kind.into())) MeliError::new(kind.to_string()).set_source(Some(kind.into()))
} }
} }
impl From<std::ffi::NulError> for MeliError { impl From<std::ffi::NulError> for MeliError {
#[inline] #[inline]
fn from(kind: std::ffi::NulError) -> MeliError { fn from(kind: std::ffi::NulError) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
impl From<Box<bincode::ErrorKind>> for MeliError { impl From<Box<bincode::ErrorKind>> for MeliError {
#[inline] #[inline]
fn from(kind: Box<bincode::ErrorKind>) -> MeliError { fn from(kind: Box<bincode::ErrorKind>) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
impl From<nix::Error> for MeliError { impl From<nix::Error> for MeliError {
#[inline] #[inline]
fn from(kind: nix::Error) -> MeliError { fn from(kind: nix::Error) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
@ -319,14 +348,14 @@ impl From<nix::Error> for MeliError {
impl From<rusqlite::Error> for MeliError { impl From<rusqlite::Error> for MeliError {
#[inline] #[inline]
fn from(kind: rusqlite::Error) -> MeliError { fn from(kind: rusqlite::Error) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
impl From<libloading::Error> for MeliError { impl From<libloading::Error> for MeliError {
#[inline] #[inline]
fn from(kind: libloading::Error) -> MeliError { fn from(kind: libloading::Error) -> MeliError {
MeliError::new(format!("{}", kind)).set_source(Some(Arc::new(kind))) MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
} }
} }
@ -347,16 +376,14 @@ impl From<String> for MeliError {
impl From<nom::Err<(&[u8], nom::error::ErrorKind)>> for MeliError { impl From<nom::Err<(&[u8], nom::error::ErrorKind)>> for MeliError {
#[inline] #[inline]
fn from(kind: nom::Err<(&[u8], nom::error::ErrorKind)>) -> MeliError { fn from(kind: nom::Err<(&[u8], nom::error::ErrorKind)>) -> MeliError {
MeliError::new("Parsing error") MeliError::new("Parsing error").set_source(Some(Arc::new(MeliError::new(kind.to_string()))))
.set_source(Some(Arc::new(MeliError::new(format!("{}", kind)))))
} }
} }
impl From<nom::Err<(&str, nom::error::ErrorKind)>> for MeliError { impl From<nom::Err<(&str, nom::error::ErrorKind)>> for MeliError {
#[inline] #[inline]
fn from(kind: nom::Err<(&str, nom::error::ErrorKind)>) -> MeliError { fn from(kind: nom::Err<(&str, nom::error::ErrorKind)>) -> MeliError {
MeliError::new("Parsing error") MeliError::new("Parsing error").set_details(kind.to_string())
.set_source(Some(Arc::new(MeliError::new(format!("{}", kind)))))
} }
} }

View File

@ -2229,8 +2229,8 @@ pub fn save_draft(
.. ..
}) => { }) => {
context.replies.push_back(UIEvent::Notification( context.replies.push_back(UIEvent::Notification(
summary.map(|s| s.into()), details.map(|s| s.into()),
details.into(), summary.to_string(),
Some(NotificationType::Error(kind)), Some(NotificationType::Error(kind)),
)); ));
} }

View File

@ -1239,20 +1239,20 @@ send_mail = '/bin/false'
let mut new_file = ConfigFile::new(TEST_CONFIG).unwrap(); let mut new_file = ConfigFile::new(TEST_CONFIG).unwrap();
let err = FileSettings::validate(new_file.path.clone(), false, true).unwrap_err(); let err = FileSettings::validate(new_file.path.clone(), false, true).unwrap_err();
assert!(err.details.as_ref().starts_with("You must set a global `composing` option. If you override `composing` in each account, you can use a dummy global like follows")); assert!(err.summary.as_ref().starts_with("You must set a global `composing` option. If you override `composing` in each account, you can use a dummy global like follows"));
new_file new_file
.file .file
.write_all("[composing]\nsend_mail = '/bin/false'\n".as_bytes()) .write_all("[composing]\nsend_mail = '/bin/false'\n".as_bytes())
.unwrap(); .unwrap();
let err = FileSettings::validate(new_file.path.clone(), false, true).unwrap_err(); let err = FileSettings::validate(new_file.path.clone(), false, true).unwrap_err();
assert_eq!(err.details.as_ref(), "Configuration error (account-name): root_path `/path/to/root/mailbox` is not a valid directory."); assert_eq!(err.summary.as_ref(), "Configuration error (account-name): root_path `/path/to/root/mailbox` is not a valid directory.");
/* Test unrecognised configuration entries error */ /* Test unrecognised configuration entries error */
let new_file = ConfigFile::new(EXTRA_CONFIG).unwrap(); let new_file = ConfigFile::new(EXTRA_CONFIG).unwrap();
let err = FileSettings::validate(new_file.path.clone(), false, true).unwrap_err(); let err = FileSettings::validate(new_file.path.clone(), false, true).unwrap_err();
assert_eq!( assert_eq!(
err.details.as_ref(), err.summary.as_ref(),
"Unrecognised configuration values: {\"index_style\": \"Compact\"}" "Unrecognised configuration values: {\"index_style\": \"Compact\"}"
); );

View File

@ -1004,14 +1004,14 @@ impl State {
format!( format!(
"{}: {}{}{}", "{}: {}{}{}",
self.context.accounts[&account_hash].name(), self.context.accounts[&account_hash].name(),
description.as_ref().map(|s| s.as_str()).unwrap_or(""), description.as_str(),
if description.is_some() { ": " } else { "" }, if content.is_some() { ": " } else { "" },
content.as_str() content.as_ref().map(|s| s.as_str()).unwrap_or("")
), ),
level, level,
); );
self.rcv_event(UIEvent::StatusEvent(StatusEvent::DisplayMessage( self.rcv_event(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
content.to_string(), description.to_string(),
))); )));
return; return;
} }