Skip to content

Commit f22aa83

Browse files
Merge pull request #413 from yuja/push-cc7b939efbd0
Attach key to type error generated from Config::get_<type>()
2 parents c71ad9c + b24ea68 commit f22aa83

File tree

2 files changed

+74
-14
lines changed

2 files changed

+74
-14
lines changed

src/config.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl Config {
150150
Ok(())
151151
}
152152

153-
pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
153+
fn get_value(&self, key: &str) -> Result<Value> {
154154
let k = key.to_lowercase();
155155
let key = k.as_str();
156156
// Parse the key into a path expression
@@ -159,38 +159,44 @@ impl Config {
159159
// Traverse the cache using the path to (possibly) retrieve a value
160160
let value = expr.get(&self.cache).cloned();
161161

162-
match value {
163-
Some(value) => {
164-
// Deserialize the received value into the requested type
165-
T::deserialize(value).map_err(|e| e.extend_with_key(key))
166-
}
162+
value.ok_or_else(|| ConfigError::NotFound(key.into()))
163+
}
167164

168-
None => Err(ConfigError::NotFound(key.into())),
169-
}
165+
pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
166+
self.get_value(key).and_then(|value| {
167+
// Deserialize the received value into the requested type
168+
T::deserialize(value).map_err(|e| e.extend_with_key(key))
169+
})
170170
}
171171

172172
pub fn get_string(&self, key: &str) -> Result<String> {
173-
self.get(key).and_then(Value::into_string)
173+
self.get_value(key)
174+
.and_then(|value| value.into_string().map_err(|e| e.extend_with_key(key)))
174175
}
175176

176177
pub fn get_int(&self, key: &str) -> Result<i64> {
177-
self.get(key).and_then(Value::into_int)
178+
self.get_value(key)
179+
.and_then(|value| value.into_int().map_err(|e| e.extend_with_key(key)))
178180
}
179181

180182
pub fn get_float(&self, key: &str) -> Result<f64> {
181-
self.get(key).and_then(Value::into_float)
183+
self.get_value(key)
184+
.and_then(|value| value.into_float().map_err(|e| e.extend_with_key(key)))
182185
}
183186

184187
pub fn get_bool(&self, key: &str) -> Result<bool> {
185-
self.get(key).and_then(Value::into_bool)
188+
self.get_value(key)
189+
.and_then(|value| value.into_bool().map_err(|e| e.extend_with_key(key)))
186190
}
187191

188192
pub fn get_table(&self, key: &str) -> Result<Map<String, Value>> {
189-
self.get(key).and_then(Value::into_table)
193+
self.get_value(key)
194+
.and_then(|value| value.into_table().map_err(|e| e.extend_with_key(key)))
190195
}
191196

192197
pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
193-
self.get(key).and_then(Value::into_array)
198+
self.get_value(key)
199+
.and_then(|value| value.into_array().map_err(|e| e.extend_with_key(key)))
194200
}
195201

196202
/// Attempt to deserialize the entire configuration into the requested type.

tests/errors.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,60 @@ fn test_error_type_detached() {
5858
);
5959
}
6060

61+
#[test]
62+
fn test_error_type_get_bool() {
63+
let c = make();
64+
65+
let res = c.get_bool("boolean_s_parse");
66+
67+
let path: PathBuf = ["tests", "Settings.toml"].iter().collect();
68+
69+
assert!(res.is_err());
70+
assert_eq!(
71+
res.unwrap_err().to_string(),
72+
format!(
73+
"invalid type: string \"fals\", expected a boolean for key `boolean_s_parse` in {}",
74+
path.display()
75+
)
76+
);
77+
}
78+
79+
#[test]
80+
fn test_error_type_get_table() {
81+
let c = make();
82+
83+
let res = c.get_table("debug");
84+
85+
let path: PathBuf = ["tests", "Settings.toml"].iter().collect();
86+
87+
assert!(res.is_err());
88+
assert_eq!(
89+
res.unwrap_err().to_string(),
90+
format!(
91+
"invalid type: boolean `true`, expected a map for key `debug` in {}",
92+
path.display()
93+
)
94+
);
95+
}
96+
97+
#[test]
98+
fn test_error_type_get_array() {
99+
let c = make();
100+
101+
let res = c.get_array("debug");
102+
103+
let path: PathBuf = ["tests", "Settings.toml"].iter().collect();
104+
105+
assert!(res.is_err());
106+
assert_eq!(
107+
res.unwrap_err().to_string(),
108+
format!(
109+
"invalid type: boolean `true`, expected an array for key `debug` in {}",
110+
path.display()
111+
)
112+
);
113+
}
114+
61115
#[test]
62116
fn test_error_enum_de() {
63117
#[derive(Debug, Deserialize, PartialEq, Eq)]

0 commit comments

Comments
 (0)