Skip to content

Commit

Permalink
feat: prepend error with path
Browse files Browse the repository at this point in the history
  • Loading branch information
allevo committed Jan 10, 2025
1 parent f558cbf commit 1fe75f0
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 14 deletions.
31 changes: 21 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ indexmap = { version = "2.2", features = ["serde"], optional = true }
convert_case = { version = "0.6", optional = true }
pathdiff = "0.2"
winnow = "0.6.20"
serde_path_to_error = "0.1"

[dev-dependencies]
serde_derive = "1.0"
Expand Down
16 changes: 15 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::fmt::Debug;

use serde::de::Deserialize;
use serde::ser::Serialize;
use serde_path_to_error::{Deserializer, Track};

use crate::builder::{ConfigBuilder, DefaultState};
use crate::error::{ConfigError, Result};
Expand Down Expand Up @@ -142,7 +143,20 @@ impl Config {

/// Attempt to deserialize the entire configuration into the requested type.
pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
T::deserialize(self)
let mut track = Track::new();
match T::deserialize(Deserializer::new(self, &mut track)) {
Ok(t) => Ok(t),
Err(ConfigError::Message(e)) => {
let path = track.path();
if path.iter().count() == 0 {
return Err(ConfigError::Message(e));
}
Err(ConfigError::Message(format!(
"failed reading field `{path}`: {e}"
)))
}
Err(err) => Err(err),
}
}

/// Attempt to serialize the entire configuration from the given type.
Expand Down
4 changes: 2 additions & 2 deletions tests/testsuite/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,14 @@ fn test_json_error_with_path() {
"inner": { "value": 42 }
}
"#,
FileFormat::Json,
FileFormat::Json5,
))
.build()
.unwrap();

let with_path = c.clone().try_deserialize::<Settings>();
assert_data_eq!(
with_path.unwrap_err().to_string(),
str!["missing field `value2`"]
str!["failed reading field `inner`: missing field `value2`"]
);
}
2 changes: 1 addition & 1 deletion tests/testsuite/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ fn test_load_level_lowercase() {
assert!(s.is_err());
assert_data_eq!(
s.unwrap_err().to_string(),
str!["enum Level does not have variant constructor error"]
str!["failed reading field `log`: enum Level does not have variant constructor error"]
);
}

0 comments on commit 1fe75f0

Please sign in to comment.