lib_humus_configuration/
error.rs

1// SPDX-FileCopyrightText: 2025 Slatian
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5use std::error::Error;
6use std::fmt;
7use std::path::PathBuf;
8
9use crate::ConfigFormat;
10
11/// Error type returned when reading a configuration file fails.
12#[derive(Debug)]
13pub struct HumusConfigError {
14	/// The path of the file that caused the error
15	pub path: PathBuf,
16	/// What caused the error
17	pub cause: ErrorCause,
18}
19
20/// Cause of a [HumusConfigError].
21///
22/// **⚠️ Warning:** Available variants depend on the enabled feature flags, don't do exhaustive matching on them in libraries.
23#[derive(Debug)]
24pub enum ErrorCause {
25	/// There was a problem with reading the file itself
26	FileRead(std::io::Error),
27
28	/// There was a problem while parsing the file as JSON
29	#[cfg(feature="json")]
30	Json(serde_json::Error),
31
32	/// There was a problem while parsing the file as JSON5
33	#[cfg(feature="json5")]
34	Json5(json5::Error),
35
36	/// There was a problem parsing the file as TOML
37	#[cfg(feature="toml")]
38	Toml(toml::de::Error),
39
40	/// The file format was recognized, but isn't allowed by the settings
41	FormatNotAllowed {
42		/// The detected format
43		format: ConfigFormat,
44		/// The format you should prefer instead
45		prefer: ConfigFormat,
46	},
47}
48
49impl ErrorCause {
50	/// Return the format that caused the error
51	pub fn get_format(&self) -> Option<ConfigFormat> {
52		match self {
53			Self::FileRead(_) => None,
54			#[cfg(feature="json")]
55			Self::Json(_) => Some(ConfigFormat::Json),
56			#[cfg(feature="json5")]
57			Self::Json5(_) => Some(ConfigFormat::Json5),
58			#[cfg(feature="toml")]
59			Self::Toml(_) => Some(ConfigFormat::Toml),
60			Self::FormatNotAllowed { format, .. } => Some(*format),
61		}
62	}
63}
64
65impl fmt::Display for HumusConfigError {
66	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67		let path = &self.path;
68		match &self.cause {
69			ErrorCause::FileRead(io_error) => {
70				write!(f, "Error while reading file {path:?}: {io_error}")
71			}
72			#[cfg(feature="json")]
73			ErrorCause::Json(error) => write!(f, "Unable to parse file as json {path:?}:\n{error}"),
74			#[cfg(feature="json5")]
75			ErrorCause::Json5(error) => {
76				write!(f, "Unable to parse file as json5 {path:?}:\n{error}")
77			}
78			#[cfg(feature="toml")]
79			ErrorCause::Toml(error) => write!(f, "Unable to parse file as toml {path:?}:\n{error}"),
80			ErrorCause::FormatNotAllowed { format, prefer } => write!(
81				f,
82				"Unable to parse file {path:?}: Using {format} here is not allowed, please prefer {prefer}. "
83			),
84		}
85	}
86}
87
88impl Error for HumusConfigError {
89	fn source(&self) -> Option<&(dyn Error + 'static)> {
90		match &self.cause {
91			ErrorCause::FileRead(error) => Some(error),
92			#[cfg(feature="json")]
93			ErrorCause::Json(error) => Some(error),
94			#[cfg(feature="json5")]
95			ErrorCause::Json5(error) => Some(error),
96			#[cfg(feature="toml")]
97			ErrorCause::Toml(error) => Some(error),
98			ErrorCause::FormatNotAllowed { .. } => None,
99		}
100	}
101}