starchart/
error.rs

1//! The different errors within the crate.
2
3use std::{
4	error::Error as StdError,
5	fmt::{Display, Formatter, Result as FmtResult},
6};
7
8#[doc(inline)]
9pub use crate::action::{
10	ActionError, ActionErrorType, ActionRunError, ActionRunErrorType, ActionValidationError,
11	ActionValidationErrorType,
12};
13
14// NOTE: This error shouldn't be used anywhere inside this crate, it's only meant for end users as an ease of use
15// error struct.
16
17/// An error that occurred within the crate.
18#[derive(Debug)]
19pub struct Error {
20	source: Option<Box<dyn StdError + Send + Sync>>,
21	kind: ErrorType,
22}
23
24impl Error {
25	/// Immutable reference to the type of error that occurred.
26	#[must_use = "retrieving the type has no effect if left unused"]
27	pub const fn kind(&self) -> &ErrorType {
28		&self.kind
29	}
30
31	/// Consume the error, returning the source error if there is any.
32	#[must_use = "consuming the error and retrieving the source has no effect if left unused"]
33	pub fn into_source(self) -> Option<Box<dyn StdError + Send + Sync>> {
34		self.source
35	}
36
37	/// Consume the error, returning the owned error type and the source error.
38	#[must_use = "consuming the error into it's parts has no effect if left unused"]
39	pub fn into_parts(self) -> (ErrorType, Option<Box<dyn StdError + Send + Sync>>) {
40		(self.kind, self.source)
41	}
42
43	/// Creates a new error from a backend.
44	#[must_use]
45	pub fn backend(e: Option<Box<dyn StdError + Send + Sync>>) -> Self {
46		Self {
47			source: e,
48			kind: ErrorType::Backend,
49		}
50	}
51}
52
53impl Display for Error {
54	fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
55		match &self.kind {
56			ErrorType::Backend => f.write_str("an error occurred within a backend"),
57			ErrorType::ActionRun => f.write_str("an error occurred running an action"),
58			ErrorType::ActionValidation => f.write_str("an action is invalid"),
59		}
60	}
61}
62
63impl StdError for Error {
64	fn source(&self) -> Option<&(dyn StdError + 'static)> {
65		self.source
66			.as_ref()
67			.map(|source| &**source as &(dyn StdError + 'static))
68	}
69}
70
71impl From<ActionError> for Error {
72	fn from(e: ActionError) -> Self {
73		let kind = match e.kind() {
74			ActionErrorType::Run => ErrorType::ActionRun,
75			ActionErrorType::Validation => ErrorType::ActionValidation,
76		};
77		Self {
78			// source will always be an ActionRunError or ActionValidationError
79			source: e.into_source(),
80			kind,
81		}
82	}
83}
84
85impl From<ActionValidationError> for Error {
86	fn from(e: ActionValidationError) -> Self {
87		Self {
88			source: Some(Box::new(e)),
89			kind: ErrorType::ActionValidation,
90		}
91	}
92}
93
94impl From<ActionRunError> for Error {
95	fn from(e: ActionRunError) -> Self {
96		Self {
97			source: Some(Box::new(e)),
98			kind: ErrorType::ActionRun,
99		}
100	}
101}
102
103/// The type of [`Error`] that occurred.
104#[derive(Debug)]
105#[allow(missing_copy_implementations)]
106#[non_exhaustive]
107pub enum ErrorType {
108	/// An error occurred within a backend.
109	Backend,
110	/// An [`ActionValidationError`] occurred.
111	ActionValidation,
112	/// An [`ActionRunError`] occurred.
113	ActionRun,
114}