cargo/util/context/
error.rs1use std::fmt;
2
3use crate::util::ConfigValue;
4use crate::util::context::ConfigKey;
5use crate::util::context::Definition;
6
7#[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}