win_open/
error.rs

1/// Enum representing various types of errors that may occur in a shell operation.
2#[derive(Debug, PartialEq)]
3#[allow(non_camel_case_types)] // To allow the use of all-uppercase error kind variants
4pub enum ErrorKind {
5    /// Error indicating that a shell type was not found or recognized.
6    SHELL_NOT_FOUND,
7
8    /// Error indicating that a command execution failed.
9    COMMAND_FAILED,
10
11    /// Error indicating that no valid launcher was found.
12    NO_LAUNCHER,
13
14    /// Error indicating an I/O operation failure.
15    IO,
16}
17
18/// A struct representing an error in shell operations.
19/// It includes the type of the error (`ErrorKind`) and an optional message.
20pub struct Error {
21    kind: ErrorKind, // The type of the error (e.g., I/O, command failure)
22    message: String, // An optional message describing the error
23}
24
25impl PartialEq for Error {
26    /// Compares two `Error` instances for equality based on their kind.
27    ///
28    /// # Parameters
29    /// - `self`: The first `Error` instance.
30    /// - `other`: The second `Error` instance.
31    ///
32    /// # Returns
33    /// `true` if both errors have the same kind, `false` otherwise.
34    fn eq(&self, other: &Self) -> bool {
35        self.kind == other.kind
36    }
37}
38
39impl Eq for Error {} // `Error` instances can be compared for equality using the `==` operator.
40
41impl Error {
42    /// Creates a new `Error` instance with a specified kind and an optional message.
43    /// If the message is empty, it will use an empty message for the error.
44    ///
45    /// # Parameters
46    /// - `kind`: The type of error (e.g., `IO`, `SHELL_NOT_FOUND`).
47    /// - `message`: A message describing the error. This can be an empty string.
48    ///
49    /// # Returns
50    /// A new `Error` instance with the specified error kind and message.
51    pub fn new<T: AsRef<str>>(kind: ErrorKind, message: T) -> Self {
52        let message: &str = message.as_ref();
53        if message.is_empty() {
54            Self::empty_message(kind)
55        } else {
56            Self {
57                kind,
58                message: message.to_string(),
59            }
60        }
61    }
62
63    /// Creates a new `Error` instance with the specified error kind and an empty message.
64    ///
65    /// # Parameters
66    /// - `kind`: The type of error (e.g., `IO`, `SHELL_NOT_FOUND`).
67    ///
68    /// # Returns
69    /// A new `Error` instance with an empty message for the specified error kind.
70    fn empty_message(kind: ErrorKind) -> Self {
71        Self {
72            kind,
73            message: "".to_string(),
74        }
75    }
76
77    /// Retrieves the kind of the error.
78    ///
79    /// # Returns
80    /// A reference to the `ErrorKind` variant that represents the type of error.
81    pub const fn kind(&self) -> &ErrorKind {
82        &self.kind
83    }
84
85    /// Retrieves the error message, if provided.
86    ///
87    /// # Returns
88    /// The error message as a string slice. If no message is provided, an empty string is returned.
89    pub fn message(&self) -> &str {
90        self.message.as_str()
91    }
92}
93
94impl core::fmt::Display for ErrorKind {
95    /// Formats the `ErrorKind` enum into a human-readable string for display purposes.
96    ///
97    /// This is used when the error kind is displayed directly (e.g., in an error message).
98    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
99        match self {
100            ErrorKind::SHELL_NOT_FOUND => {
101                write!(f, "Unrecognized shell type")
102            }
103            ErrorKind::COMMAND_FAILED => {
104                write!(f, "Command failed")
105            }
106            ErrorKind::NO_LAUNCHER => {
107                write!(f, "No launcher worked")
108            }
109            ErrorKind::IO => {
110                write!(f, "IO Error")
111            }
112        }
113    }
114}
115
116impl core::fmt::Debug for Error {
117    /// Formats the `Error` struct for debugging.
118    ///
119    /// This method provides a detailed output of the error kind and the associated message,
120    /// which is useful for debugging purposes.
121    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
122        let mut debug = fmt.debug_struct("Error");
123        debug
124            .field("kind", &self.kind())
125            .field("message", &self.message())
126            .finish()
127    }
128}
129
130impl core::fmt::Display for Error {
131    /// Formats the `Error` struct for user-facing display.
132    ///
133    /// If a message is provided, it includes the message along with the error kind.
134    /// If no message is provided, only the error kind is displayed.
135    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
136        if self.message().is_empty() {
137            write!(f, "{}", self.kind)
138        } else {
139            write!(f, "{} ({})", self.kind, self.message)
140        }
141    }
142}
143
144impl From<std::io::Error> for Error {
145    /// Converts a `std::io::Error` into an `Error` with the `IO` error kind and the error message.
146    ///
147    /// This allows for easy conversion from I/O errors (e.g., file or network errors) to our custom `Error` type.
148    ///
149    /// # Parameters
150    /// - `err`: A `std::io::Error` instance that we want to convert.
151    ///
152    /// # Returns
153    /// A new `Error` instance with the `IO` error kind and the I/O error message.
154    fn from(err: std::io::Error) -> Self {
155        Self::new(ErrorKind::IO, err.to_string().as_str())
156    }
157}
158
159impl std::error::Error for Error {} // Implements the standard error trait for compatibility with other error handling mechanisms.
160
161/// A custom `Result` type that returns `Error` in case of failure.
162///
163/// This type is used for handling errors related to shell operations. It wraps the standard `Result` type but replaces the error type with our custom `Error` type.
164pub type Result<T> = core::result::Result<T, Error>;