#
cargo/util/context/
error.rs

    1use std::fmt;
    2
    3use crate::util::ConfigValue;
    4use crate::util::context::ConfigKey;
    5use crate::util::context::Definition;
    6
    7/// Internal error for serde errors.
    8#[derive(Debug)]
    9pub struct ConfigError {
    10    error: anyhow::Error,
    11    definition: Option<Definition>,
    12}
    13
    14impl ConfigError {
    15    pub(super) fn new(message: String, definition: Definition) -> ConfigError {
    16        ConfigError {
    17            error: anyhow::Error::msg(message),
    18            definition: Some(definition),
    19        }
    20    }
    21
    22    pub(super) fn expected(key: &ConfigKey, expected: &str, found: &ConfigValue) -> ConfigError {
    23        ConfigError {
    24            error: anyhow::anyhow!(
    25                "`{}` expected {}, but found a {}",
    26                key,
    27                expected,
    28                found.desc()
    29            ),
    30            definition: Some(found.definition().clone()),
    31        }
    32    }
    33
    34    pub(super) fn is_missing_field(&self) -> bool {
    35        self.error.downcast_ref::<MissingFieldError>().is_some()
    36    }
    37
    38    pub(super) fn missing(key: &ConfigKey) -> ConfigError {
    39        ConfigError {
    40            error: anyhow::anyhow!("missing config key `{}`", key),
    41            definition: None,
    42        }
    43    }
    44
    45    pub(super) fn with_key_context(
    46        self,
    47        key: &ConfigKey,
    48        definition: Option<Definition>,
    49    ) -> ConfigError {
    50        ConfigError {
    51            error: anyhow::Error::from(self)
    52                .context(format!("could not load config key `{}`", key)),
    53            definition: definition,
    54        }
    55    }
    56}
    57
    58impl std::error::Error for ConfigError {
    59    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
    60        self.error.source()
    61    }
    62}
    63
    64impl fmt::Display for ConfigError {
    65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    66        if let Some(definition) = &self.definition {
    67            write!(f, "error in {}: {}", definition, self.error)
    68        } else {
    69            self.error.fmt(f)
    70        }
    71    }
    72}
    73
    74#[derive(Debug)]
    75struct MissingFieldError(String);
    76
    77impl fmt::Display for MissingFieldError {
    78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    79        write!(f, "missing field `{}`", self.0)
    80    }
    81}
    82
    83impl std::error::Error for MissingFieldError {}
    84
    85impl serde::de::Error for ConfigError {
    86    fn custom<T: fmt::Display>(msg: T) -> Self {
    87        ConfigError {
    88            error: anyhow::Error::msg(msg.to_string()),
    89            definition: None,
    90        }
    91    }
    92
    93    fn missing_field(field: &'static str) -> Self {
    94        ConfigError {
    95            error: anyhow::Error::new(MissingFieldError(field.to_string())),
    96            definition: None,
    97        }
    98    }
    99}
    100
    101impl From<anyhow::Error> for ConfigError {
    102    fn from(error: anyhow::Error) -> Self {
    103        ConfigError {
    104            error,
    105            definition: None,
    106        }
    107    }
    108}