brush_core/
error.rs

1use std::path::PathBuf;
2
3/// Monolithic error type for the shell
4#[derive(thiserror::Error, Debug)]
5pub enum Error {
6    /// A local variable was set outside of a function
7    #[error("can't set local variable outside of function")]
8    SetLocalVarOutsideFunction,
9
10    /// A tilde expression was used without a valid HOME variable
11    #[error("cannot expand tilde expression with HOME not set")]
12    TildeWithoutValidHome,
13
14    /// An attempt was made to assign a list to an array member
15    #[error("cannot assign list to array member")]
16    AssigningListToArrayMember,
17
18    /// An attempt was made to convert an associative array to an indexed array.
19    #[error("cannot convert associative array to indexed array")]
20    ConvertingAssociativeArrayToIndexedArray,
21
22    /// An attempt was made to convert an indexed array to an associative array.
23    #[error("cannot convert indexed array to associative array")]
24    ConvertingIndexedArrayToAssociativeArray,
25
26    /// An error occurred while sourcing the indicated script file.
27    #[error("failed to source file: {0}; {1}")]
28    FailedSourcingFile(PathBuf, Box<Error>),
29
30    /// The shell failed to send a signal to a process.
31    #[error("failed to send signal to process")]
32    FailedToSendSignal,
33
34    /// An attempt was made to assign a value to a special parameter.
35    #[error("cannot assign in this way")]
36    CannotAssignToSpecialParameter,
37
38    /// Checked expansion error.
39    #[error("expansion error: {0}")]
40    CheckedExpansionError(String),
41
42    /// A reference was made to an unknown shell function.
43    #[error("function not found: {0}")]
44    FunctionNotFound(String),
45
46    /// Command was not found.
47    #[error("command not found: {0}")]
48    CommandNotFound(String),
49
50    /// The requested functionality has not yet been implemented in this shell.
51    #[error("not yet implemented: {0}")]
52    Unimplemented(&'static str),
53
54    /// The requested functionality has not yet been implemented in this shell; it is tracked in a
55    /// GitHub issue.
56    #[error("not yet implemented: {0}; see https://github.com/reubeno/brush/issues/{1}")]
57    UnimplementedAndTracked(&'static str, u32),
58
59    /// An expected environment scope could not be found.
60    #[error("missing scope")]
61    MissingScope,
62
63    /// The given path is not a directory.
64    #[error("not a directory: {0}")]
65    NotADirectory(PathBuf),
66
67    /// The given path is a directory.
68    #[error("path is a directory")]
69    IsADirectory,
70
71    /// The given variable is not an array.
72    #[error("variable is not an array")]
73    NotArray,
74
75    /// The current user could not be determined.
76    #[error("no current user")]
77    NoCurrentUser,
78
79    /// The requested input or output redirection is invalid.
80    #[error("invalid redirection")]
81    InvalidRedirection,
82
83    /// An error occurred while redirecting input or output with the given file.
84    #[error("failed to redirect to {0}: {1}")]
85    RedirectionFailure(String, std::io::Error),
86
87    /// An error occurred evaluating an arithmetic expression.
88    #[error("arithmetic evaluation error: {0}")]
89    EvalError(#[from] crate::arithmetic::EvalError),
90
91    /// The given string could not be parsed as an integer.
92    #[error("failed to parse integer")]
93    IntParseError(#[from] std::num::ParseIntError),
94
95    /// The given string could not be parsed as an integer.
96    #[error("failed to parse integer")]
97    TryIntParseError(#[from] std::num::TryFromIntError),
98
99    /// A byte sequence could not be decoded as a valid UTF-8 string.
100    #[error("failed to decode utf-8")]
101    FromUtf8Error(#[from] std::string::FromUtf8Error),
102
103    /// A byte sequence could not be decoded as a valid UTF-8 string.
104    #[error("failed to decode utf-8")]
105    Utf8Error(#[from] std::str::Utf8Error),
106
107    /// An attempt was made to modify a readonly variable.
108    #[error("cannot mutate readonly variable")]
109    ReadonlyVariable,
110
111    /// The indicated pattern is invalid.
112    #[error("invalid pattern: '{0}'")]
113    InvalidPattern(String),
114
115    /// A regular expression error occurred
116    #[error("regex error: {0}")]
117    RegexError(#[from] fancy_regex::Error),
118
119    /// An invalid regular expression was provided.
120    #[error("invalid regex: {0}; expression: '{1}'")]
121    InvalidRegexError(fancy_regex::Error, String),
122
123    /// An I/O error occurred.
124    #[error("i/o error: {0}")]
125    IoError(#[from] std::io::Error),
126
127    /// Invalid substitution syntax.
128    #[error("bad substitution")]
129    BadSubstitution,
130
131    /// Invalid arguments were provided to the command.
132    #[error("invalid arguments")]
133    InvalidArguments,
134
135    /// An error occurred while creating a child process.
136    #[error("failed to create child process")]
137    ChildCreationFailure,
138
139    /// An error occurred while formatting a string.
140    #[error("{0}")]
141    FormattingError(#[from] std::fmt::Error),
142
143    /// An error occurred while parsing.
144    #[error("{0}")]
145    ParseError(#[from] brush_parser::ParseError),
146
147    /// An error occurred while parsing a word.
148    #[error("{0}")]
149    WordParseError(#[from] brush_parser::WordParseError),
150
151    /// Unable to parse a test command.
152    #[error("{0}")]
153    TestCommandParseError(#[from] brush_parser::TestCommandParseError),
154
155    /// Unable to parse a key binding specification.
156    #[error("{0}")]
157    BindingParseError(#[from] brush_parser::BindingParseError),
158
159    /// A threading error occurred.
160    #[error("threading error")]
161    ThreadingError(#[from] tokio::task::JoinError),
162
163    /// An invalid signal was referenced.
164    #[error("{0}: invalid signal specification")]
165    InvalidSignal(String),
166
167    /// A system error occurred.
168    #[cfg(unix)]
169    #[error("system error: {0}")]
170    ErrnoError(#[from] nix::errno::Errno),
171
172    /// An invalid umask was provided.
173    #[error("invalid umask value")]
174    InvalidUmask,
175
176    /// An error occurred reading from procfs.
177    #[cfg(target_os = "linux")]
178    #[error("procfs error: {0}")]
179    ProcfsError(#[from] procfs::ProcError),
180
181    /// The given open file cannot be read from.
182    #[error("cannot read from {0}")]
183    OpenFileNotReadable(&'static str),
184
185    /// The given open file cannot be written to.
186    #[error("cannot write to {0}")]
187    OpenFileNotWritable(&'static str),
188
189    /// Bad file descriptor.
190    #[error("bad file descriptor: {0}")]
191    BadFileDescriptor(u32),
192
193    /// Printf failure
194    #[error("printf failure: {0}")]
195    PrintfFailure(i32),
196
197    /// Printf invalid usage
198    #[error("printf: {0}")]
199    PrintfInvalidUsage(String),
200
201    /// Interrupted
202    #[error("interrupted")]
203    Interrupted,
204
205    /// Maximum function call depth was exceeded.
206    #[error("maximum function call depth exceeded")]
207    MaxFunctionCallDepthExceeded,
208
209    /// System time error.
210    #[error("system time error: {0}")]
211    TimeError(#[from] std::time::SystemTimeError),
212
213    /// Array index out of range.
214    #[error("array index out of range")]
215    ArrayIndexOutOfRange,
216
217    /// Unhandled key code.
218    #[error("unhandled key code: {0:?}")]
219    UnhandledKeyCode(Vec<u8>),
220}
221
222/// Convenience function for returning an error for unimplemented functionality.
223///
224/// # Arguments
225///
226/// * `msg` - The message to include in the error
227pub(crate) const fn unimp<T>(msg: &'static str) -> Result<T, Error> {
228    Err(Error::Unimplemented(msg))
229}
230
231/// Convenience function for returning an error for *tracked*, unimplemented functionality.
232///
233/// # Arguments
234///
235/// * `msg` - The message to include in the error
236pub(crate) const fn unimp_with_issue<T>(
237    msg: &'static str,
238    project_issue_id: u32,
239) -> Result<T, Error> {
240    Err(Error::UnimplementedAndTracked(msg, project_issue_id))
241}