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(Box<ConfigTreeError>),
119 Dotenv(Box<dotenvy::Error>),
121 Figment(Box<figment::Error>),
123 Config(Box<confique::Error>),
125 Json(Box<serde_json::Error>),
127 Io(Box<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.as_ref()),
148 Self::Dotenv(err) => Some(err.as_ref()),
149 Self::Figment(err) => Some(err.as_ref()),
150 Self::Config(err) => Some(err.as_ref()),
151 Self::Json(err) => Some(err.as_ref()),
152 Self::Io(err) => Some(err.as_ref()),
153 }
154 }
155}
156
157impl From<ConfigTreeError> for ConfigError {
158 fn from(err: ConfigTreeError) -> Self {
159 Self::Tree(Box::new(err))
160 }
161}
162
163impl From<dotenvy::Error> for ConfigError {
164 fn from(err: dotenvy::Error) -> Self {
165 Self::Dotenv(Box::new(err))
166 }
167}
168
169impl From<figment::Error> for ConfigError {
170 fn from(err: figment::Error) -> Self {
171 Self::Figment(Box::new(err))
172 }
173}
174
175impl From<confique::Error> for ConfigError {
176 fn from(err: confique::Error) -> Self {
177 Self::Config(Box::new(err))
178 }
179}
180
181impl From<serde_json::Error> for ConfigError {
182 fn from(err: serde_json::Error) -> Self {
183 Self::Json(Box::new(err))
184 }
185}
186
187impl From<io::Error> for ConfigError {
188 fn from(err: io::Error) -> Self {
189 Self::Io(Box::new(err))
190 }
191}