Skip to content

Commit

Permalink
Use failure::Error for ConfigError instead of a String.
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuss committed May 24, 2018
1 parent 154c787 commit b3db164
Showing 1 changed file with 22 additions and 19 deletions.
41 changes: 22 additions & 19 deletions src/cargo/util/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,21 +847,21 @@ impl fmt::Display for ConfigKey {
/// Internal error for serde errors.
#[derive(Debug)]
pub struct ConfigError {
message: String,
error: failure::Error,
definition: Option<Definition>,
}

impl ConfigError {
fn new(message: String, definition: Definition) -> ConfigError {
ConfigError {
message,
error: failure::err_msg(message),
definition: Some(definition),
}
}

fn expected(key: &str, expected: &str, found: &ConfigValue) -> ConfigError {
ConfigError {
message: format!(
error: format_err!(
"`{}` expected {}, but found a {}",
key,
expected,
Expand All @@ -873,56 +873,59 @@ impl ConfigError {

fn missing(key: String) -> ConfigError {
ConfigError {
message: format!("missing config key `{}`", key),
error: format_err!("missing config key `{}`", key),
definition: None,
}
}

fn with_key_context(self, key: String, definition: Definition) -> ConfigError {
ConfigError {
message: format!("could not load config key `{}`: {}", key, self),
error: format_err!("could not load config key `{}`: {}", key, self),
definition: Some(definition),
}
}
}

impl std::error::Error for ConfigError {
// This can be removed once 1.27 is stable.
fn description(&self) -> &str {
self.message.as_str()
"An error has occurred."
}
}

// Future Note: Currently we cannot override Fail::cause (due to
// specialization) so we have no way to return the underlying causes. In the
// future, once this limitation is lifted, this should instead implement
// `cause` and avoid doing the cause formatting here.
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let message = self
.error
.causes()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join("\nCaused by:\n ");
if let Some(ref definition) = self.definition {
write!(f, "error in {}: {}", definition, self.message)
write!(f, "error in {}: {}", definition, message)
} else {
self.message.fmt(f)
message.fmt(f)
}
}
}

impl de::Error for ConfigError {
fn custom<T: fmt::Display>(msg: T) -> Self {
ConfigError {
message: msg.to_string(),
error: failure::err_msg(msg.to_string()),
definition: None,
}
}
}

// TODO: AFAIK, you cannot override Fail::cause (due to specialization), so we
// have no way to bubble up the underlying error. For now, it just formats
// the underlying cause as a string.
impl From<failure::Error> for ConfigError {
fn from(e: failure::Error) -> Self {
let message = e
.causes()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join("\nCaused by:\n ");
fn from(error: failure::Error) -> Self {
ConfigError {
message,
error,
definition: None,
}
}
Expand Down

0 comments on commit b3db164

Please sign in to comment.