1use std::fmt::Display;
2
3#[cfg(doc)]
4use std::process::Child;
5#[cfg(doc)]
6use std::process::Command;
7#[cfg(doc)]
8use std::process::Output;
9
10use crate::output_conversion_error::OutputConversionError;
11use crate::ExecError;
12use crate::OutputError;
13use crate::WaitError;
14
15#[cfg(doc)]
16use crate::CommandExt;
17#[cfg(feature = "miette")]
18use miette::Diagnostic;
19
20#[derive(Debug)]
22#[non_exhaustive]
23pub enum Error {
24 Exec(ExecError),
26 Wait(WaitError),
30 Output(OutputError),
37 Conversion(OutputConversionError),
40}
41
42impl Error {
43 #[cfg(feature = "miette")]
44 fn as_inner_diagnostic(&self) -> &(dyn Diagnostic + Send + Sync + 'static) {
45 match self {
46 Error::Exec(inner) => inner,
47 Error::Wait(inner) => inner,
48 Error::Output(inner) => inner,
49 Error::Conversion(inner) => inner,
50 }
51 }
52}
53
54impl Display for Error {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 match self {
57 Error::Exec(error) => write!(f, "{}", error),
58 Error::Wait(error) => write!(f, "{}", error),
59 Error::Output(error) => write!(f, "{}", error),
60 Error::Conversion(error) => write!(f, "{}", error),
61 }
62 }
63}
64
65impl From<ExecError> for Error {
66 fn from(error: ExecError) -> Self {
67 Self::Exec(error)
68 }
69}
70
71impl From<WaitError> for Error {
72 fn from(error: WaitError) -> Self {
73 Self::Wait(error)
74 }
75}
76
77impl From<OutputError> for Error {
78 fn from(error: OutputError) -> Self {
79 Self::Output(error)
80 }
81}
82
83impl From<OutputConversionError> for Error {
84 fn from(error: OutputConversionError) -> Self {
85 Self::Conversion(error)
86 }
87}
88
89impl std::error::Error for Error {}
90
91#[cfg(feature = "miette")]
92impl Diagnostic for Error {
93 fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
94 self.as_inner_diagnostic().code()
95 }
96
97 fn severity(&self) -> Option<miette::Severity> {
98 self.as_inner_diagnostic().severity()
99 }
100
101 fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
102 self.as_inner_diagnostic().help()
103 }
104
105 fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
106 self.as_inner_diagnostic().url()
107 }
108
109 fn source_code(&self) -> Option<&dyn miette::SourceCode> {
110 self.as_inner_diagnostic().source_code()
111 }
112
113 fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
114 self.as_inner_diagnostic().labels()
115 }
116
117 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
118 self.as_inner_diagnostic().related()
119 }
120
121 fn diagnostic_source(&self) -> Option<&dyn Diagnostic> {
122 self.as_inner_diagnostic().diagnostic_source()
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use static_assertions::assert_impl_all;
130
131 assert_impl_all!(Error: Send, Sync);
132}