rust_config_tree/
error.rs1use std::{
9 error::Error,
10 fmt, io,
11 path::{Path, PathBuf},
12};
13
14pub type BoxError = Box<dyn Error + Send + Sync + 'static>;
19
20pub type Result<T> = std::result::Result<T, ConfigTreeError>;
24
25#[derive(Debug)]
27pub enum ConfigTreeError {
28 CurrentDir {
30 source: io::Error,
32 },
33 Load {
35 path: PathBuf,
37 source: BoxError,
39 },
40 EmptyIncludePath {
42 path: PathBuf,
44 index: usize,
46 },
47 IncludeCycle {
49 chain: Vec<PathBuf>,
51 },
52}
53
54impl ConfigTreeError {
55 pub(crate) fn load<E>(path: &Path, source: E) -> Self
70 where
71 E: Into<BoxError>,
72 {
73 Self::Load {
74 path: path.to_path_buf(),
75 source: source.into(),
76 }
77 }
78}
79
80impl fmt::Display for ConfigTreeError {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 match self {
83 Self::CurrentDir { .. } => write!(f, "failed to resolve current directory"),
84 Self::Load { path, source } => {
85 write!(f, "failed to load config {}: {source}", path.display())
86 }
87 Self::EmptyIncludePath { path, index } => write!(
88 f,
89 "include path at index {index} in {} must not be empty",
90 path.display()
91 ),
92 Self::IncludeCycle { chain } => {
93 let chain = chain
94 .iter()
95 .map(|path| path.display().to_string())
96 .collect::<Vec<_>>()
97 .join(" -> ");
98 write!(f, "recursive config include cycle: {chain}")
99 }
100 }
101 }
102}
103
104impl Error for ConfigTreeError {
105 fn source(&self) -> Option<&(dyn Error + 'static)> {
106 match self {
107 Self::CurrentDir { source } => Some(source),
108 Self::Load { source, .. } => Some(source.as_ref()),
109 Self::EmptyIncludePath { .. } | Self::IncludeCycle { .. } => None,
110 }
111 }
112}
113
114#[derive(Debug)]
116pub enum ConfigError {
117 Tree(ConfigTreeError),
119 Dotenv(dotenvy::Error),
121 Figment(figment::Error),
123 Config(confique::Error),
125 Json(serde_json::Error),
127 Io(io::Error),
129}
130
131impl fmt::Display for ConfigError {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 match self {
134 Self::Tree(err) => err.fmt(f),
135 Self::Dotenv(err) => err.fmt(f),
136 Self::Figment(err) => err.fmt(f),
137 Self::Config(err) => err.fmt(f),
138 Self::Json(err) => err.fmt(f),
139 Self::Io(err) => err.fmt(f),
140 }
141 }
142}
143
144impl Error for ConfigError {
145 fn source(&self) -> Option<&(dyn Error + 'static)> {
146 match self {
147 Self::Tree(err) => Some(err),
148 Self::Dotenv(err) => Some(err),
149 Self::Figment(err) => Some(err),
150 Self::Config(err) => Some(err),
151 Self::Json(err) => Some(err),
152 Self::Io(err) => Some(err),
153 }
154 }
155}
156
157impl From<ConfigTreeError> for ConfigError {
158 fn from(err: ConfigTreeError) -> Self {
159 Self::Tree(err)
160 }
161}
162
163impl From<dotenvy::Error> for ConfigError {
164 fn from(err: dotenvy::Error) -> Self {
165 Self::Dotenv(err)
166 }
167}
168
169impl From<figment::Error> for ConfigError {
170 fn from(err: figment::Error) -> Self {
171 Self::Figment(err)
172 }
173}
174
175impl From<confique::Error> for ConfigError {
176 fn from(err: confique::Error) -> Self {
177 Self::Config(err)
178 }
179}
180
181impl From<serde_json::Error> for ConfigError {
182 fn from(err: serde_json::Error) -> Self {
183 Self::Json(err)
184 }
185}
186
187impl From<io::Error> for ConfigError {
188 fn from(err: io::Error) -> Self {
189 Self::Io(err)
190 }
191}