1use std::fmt;
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum VfsError {
7 NotFound(PathBuf),
8 AlreadyExists(PathBuf),
9 NotADirectory(PathBuf),
10 NotAFile(PathBuf),
11 IsADirectory(PathBuf),
12 PermissionDenied(PathBuf),
13 DirectoryNotEmpty(PathBuf),
14 SymlinkLoop(PathBuf),
15 InvalidPath(String),
16 IoError(String),
17}
18
19impl fmt::Display for VfsError {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 match self {
22 VfsError::NotFound(p) => write!(f, "No such file or directory: {}", p.display()),
23 VfsError::AlreadyExists(p) => write!(f, "Already exists: {}", p.display()),
24 VfsError::NotADirectory(p) => write!(f, "Not a directory: {}", p.display()),
25 VfsError::NotAFile(p) => write!(f, "Not a file: {}", p.display()),
26 VfsError::IsADirectory(p) => write!(f, "Is a directory: {}", p.display()),
27 VfsError::PermissionDenied(p) => write!(f, "Permission denied: {}", p.display()),
28 VfsError::DirectoryNotEmpty(p) => write!(f, "Directory not empty: {}", p.display()),
29 VfsError::SymlinkLoop(p) => {
30 write!(f, "Too many levels of symbolic links: {}", p.display())
31 }
32 VfsError::InvalidPath(msg) => write!(f, "Invalid path: {msg}"),
33 VfsError::IoError(msg) => write!(f, "I/O error: {msg}"),
34 }
35 }
36}
37
38impl std::error::Error for VfsError {}
39
40#[derive(Debug)]
42pub enum RustBashError {
43 Parse(String),
44 Execution(String),
45 ExpansionError {
50 message: String,
51 exit_code: i32,
52 should_exit: bool,
53 },
54 FailGlob {
57 pattern: String,
58 },
59 RedirectFailed(String),
63 LimitExceeded {
64 limit_name: &'static str,
65 limit_value: usize,
66 actual_value: usize,
67 },
68 Network(String),
69 Vfs(VfsError),
70 Timeout,
71}
72
73impl fmt::Display for RustBashError {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 RustBashError::Parse(msg) => write!(f, "parse error: {msg}"),
77 RustBashError::Execution(msg) => write!(f, "execution error: {msg}"),
78 RustBashError::ExpansionError { message, .. } => {
79 write!(f, "expansion error: {message}")
80 }
81 RustBashError::FailGlob { pattern } => {
82 write!(f, "no match: {pattern}")
83 }
84 RustBashError::RedirectFailed(msg) => write!(f, "rust-bash: {msg}"),
85 RustBashError::LimitExceeded {
86 limit_name,
87 limit_value,
88 actual_value,
89 } => write!(
90 f,
91 "limit exceeded: {limit_name} ({actual_value}) exceeded limit ({limit_value})"
92 ),
93 RustBashError::Network(msg) => write!(f, "network error: {msg}"),
94 RustBashError::Vfs(e) => write!(f, "vfs error: {e}"),
95 RustBashError::Timeout => write!(f, "execution timed out"),
96 }
97 }
98}
99
100impl std::error::Error for RustBashError {
101 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
102 match self {
103 RustBashError::Vfs(e) => Some(e),
104 _ => None,
105 }
106 }
107}
108
109impl From<VfsError> for RustBashError {
110 fn from(e: VfsError) -> Self {
111 RustBashError::Vfs(e)
112 }
113}