Skip to main content

nidus_config/
error.rs

1use serde::de::DeserializeOwned;
2use serde_json::Value;
3
4/// Result type for configuration operations.
5pub type Result<T> = std::result::Result<T, ConfigError>;
6
7/// Errors emitted by typed configuration loading.
8#[derive(Debug, thiserror::Error)]
9pub enum ConfigError {
10    /// Parsing a JSON configuration source failed.
11    #[error("configuration JSON parse error: {0}")]
12    Parse(#[source] serde_json::Error),
13
14    /// The configuration root was not a JSON object.
15    #[error("configuration root must be a JSON object")]
16    RootNotObject,
17
18    /// Reading a JSON configuration file failed.
19    #[error("configuration file `{path}` read error: {source}")]
20    ReadFile {
21        /// Configuration file path.
22        path: String,
23        /// Underlying IO error.
24        #[source]
25        source: std::io::Error,
26    },
27
28    /// Parsing a JSON configuration file failed.
29    #[error("configuration file `{path}` JSON parse error: {source}")]
30    ParseFile {
31        /// Configuration file path.
32        path: String,
33        /// Underlying serde error.
34        #[source]
35        source: serde_json::Error,
36    },
37
38    /// A JSON configuration file root was not an object.
39    #[error("configuration file `{path}` root must be a JSON object")]
40    FileRootNotObject {
41        /// Configuration file path.
42        path: String,
43    },
44
45    /// Deserialization into the requested type failed.
46    #[error("configuration deserialize error: {0}")]
47    Deserialize(#[from] serde_json::Error),
48
49    /// Deserialization of one configuration value failed.
50    #[error("configuration deserialize error at `{path}`: {source}")]
51    ValueDeserialize {
52        /// Configuration key or dot-separated path that failed.
53        path: String,
54        /// Underlying serde error.
55        #[source]
56        source: serde_json::Error,
57    },
58
59    /// A required configuration value was missing.
60    #[error("missing required configuration value `{path}`")]
61    MissingValue {
62        /// Missing configuration key or dot-separated path.
63        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}