1use serde::de::DeserializeOwned;
2use serde_json::Value;
3
4pub type Result<T> = std::result::Result<T, ConfigError>;
6
7#[derive(Debug, thiserror::Error)]
9pub enum ConfigError {
10 #[error("configuration JSON parse error: {0}")]
12 Parse(#[source] serde_json::Error),
13
14 #[error("configuration root must be a JSON object")]
16 RootNotObject,
17
18 #[error("configuration file `{path}` read error: {source}")]
20 ReadFile {
21 path: String,
23 #[source]
25 source: std::io::Error,
26 },
27
28 #[error("configuration file `{path}` JSON parse error: {source}")]
30 ParseFile {
31 path: String,
33 #[source]
35 source: serde_json::Error,
36 },
37
38 #[error("configuration file `{path}` root must be a JSON object")]
40 FileRootNotObject {
41 path: String,
43 },
44
45 #[error("configuration deserialize error: {0}")]
47 Deserialize(#[from] serde_json::Error),
48
49 #[error("configuration deserialize error at `{path}`: {source}")]
51 ValueDeserialize {
52 path: String,
54 #[source]
56 source: serde_json::Error,
57 },
58
59 #[error("missing required configuration value `{path}`")]
61 MissingValue {
62 path: String,
64 },
65}
66
67pub(crate) fn deserialize_value<T>(path: String, value: &Value) -> Result<T>
68where
69 T: DeserializeOwned,
70{
71 T::deserialize(value).map_err(|source| ConfigError::ValueDeserialize { path, source })
72}