starchart_backends/fs/
error.rs

1use std::{
2	error::Error,
3	fmt::{Display, Formatter, Result as FmtResult},
4	io::Error as IoError,
5	path::PathBuf,
6};
7
8/// An error occurred from the [`FsBackend`] or one of it's [`Transcoders`].
9///
10/// [`FsBackend`]: super::FsBackend
11/// [`Transcoders`]: super::Transcoder
12#[derive(Debug)]
13#[cfg(feature = "fs")]
14pub struct FsError {
15	pub(super) source: Option<Box<dyn Error + Send + Sync>>,
16	pub(super) kind: FsErrorType,
17}
18
19impl FsError {
20	/// Creates an error from a [`Transcoder`].
21	///
22	/// [`Transcoder`]: super::Transcoder
23	#[must_use]
24	pub fn serde(err: Option<Box<dyn Error + Send + Sync>>) -> Self {
25		Self {
26			source: err,
27			kind: FsErrorType::Serde,
28		}
29	}
30
31	/// Immutable reference to the type of error that occurred.
32	#[must_use = "retrieving the type has no effect if left unused"]
33	pub const fn kind(&self) -> &FsErrorType {
34		&self.kind
35	}
36
37	/// Consume the error, returning the source error if there is any.
38	#[must_use = "consuming the error and retrieving the source has no effect if left unused"]
39	pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
40		self.source
41	}
42
43	/// Consume the error, returning the owned error type and the source error.
44	#[must_use = "consuming the error into it's parts has no effect if left unused"]
45	pub fn into_parts(self) -> (FsErrorType, Option<Box<dyn Error + Send + Sync>>) {
46		(self.kind, self.source)
47	}
48}
49
50impl Display for FsError {
51	fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
52		match &self.kind {
53			FsErrorType::Io => f.write_str("an IO error occurred"),
54			FsErrorType::PathNotDirectory(p) => {
55				f.write_str("path ")?;
56				Display::fmt(&p.display(), f)?;
57				f.write_str(" is not a directory")
58			}
59			FsErrorType::Serde => f.write_str("a (de)serialization error occurred"),
60			FsErrorType::InvalidFile(p) => {
61				f.write_str("file ")?;
62				Display::fmt(&p.display(), f)?;
63				f.write_str(" is invalid")
64			}
65		}
66	}
67}
68
69impl Error for FsError {
70	fn source(&self) -> Option<&(dyn Error + 'static)> {
71		self.source
72			.as_ref()
73			.map(|err| &**err as &(dyn Error + 'static))
74	}
75}
76
77impl From<IoError> for FsError {
78	fn from(e: IoError) -> Self {
79		Self {
80			source: Some(Box::new(e)),
81			kind: FsErrorType::Io,
82		}
83	}
84}
85
86impl From<FsError> for starchart::Error {
87	fn from(e: FsError) -> Self {
88		Self::backend(Some(Box::new(e)))
89	}
90}
91
92#[cfg(feature = "binary")]
93impl From<serde_bincode::Error> for FsError {
94	fn from(e: serde_bincode::Error) -> Self {
95		Self::serde(Some(e))
96	}
97}
98
99#[cfg(feature = "binary")]
100impl From<serde_bincode::ErrorKind> for FsError {
101	fn from(e: serde_bincode::ErrorKind) -> Self {
102		Self::serde(Some(Box::new(e)))
103	}
104}
105
106#[cfg(feature = "binary")]
107impl From<serde_cbor::Error> for FsError {
108	fn from(e: serde_cbor::Error) -> Self {
109		Self::serde(Some(Box::new(e)))
110	}
111}
112
113#[cfg(feature = "json")]
114impl From<serde_json::Error> for FsError {
115	fn from(e: serde_json::Error) -> Self {
116		Self::serde(Some(Box::new(e)))
117	}
118}
119
120#[cfg(feature = "toml")]
121impl From<serde_toml::de::Error> for FsError {
122	fn from(e: serde_toml::de::Error) -> Self {
123		Self::serde(Some(Box::new(e)))
124	}
125}
126
127#[cfg(feature = "toml")]
128impl From<serde_toml::ser::Error> for FsError {
129	fn from(e: serde_toml::ser::Error) -> Self {
130		Self::serde(Some(Box::new(e)))
131	}
132}
133
134#[cfg(feature = "yaml")]
135impl From<serde_yaml::Error> for FsError {
136	fn from(e: serde_yaml::Error) -> Self {
137		Self::serde(Some(Box::new(e)))
138	}
139}
140
141/// The type of [`FsError`] that occurred.
142#[derive(Debug)]
143#[cfg(feature = "fs")]
144#[non_exhaustive]
145pub enum FsErrorType {
146	/// An IO error occurred.
147	Io,
148	/// The path provided was not a directory.
149	PathNotDirectory(PathBuf),
150	/// An error occurred during (de)serialization.
151	Serde,
152	/// The given file was invalid in some way.
153	InvalidFile(PathBuf),
154}