Mountain/Error/
FileSystemError.rs1use std::{error::Error as StdError, fmt, path::PathBuf};
9
10use serde::{Deserialize, Serialize};
11
12use super::CoreError::{ErrorContext, ErrorKind, ErrorSeverity, MountainError};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub enum FileSystemError {
17 FileNotFound { context:ErrorContext, path:PathBuf },
19
20 PermissionDenied { context:ErrorContext, path:PathBuf },
22
23 IOError { context:ErrorContext, path:Option<PathBuf>, operation:String },
25
26 InvalidPath { context:ErrorContext, path:PathBuf },
28
29 DirectoryNotEmpty { context:ErrorContext, path:PathBuf },
31
32 FileAlreadyExists { context:ErrorContext, path:PathBuf },
34
35 NotADirectory { context:ErrorContext, path:PathBuf },
37
38 NotAFile { context:ErrorContext, path:PathBuf },
40}
41
42impl FileSystemError {
43 pub fn context(&self) -> &ErrorContext {
45 match self {
46 FileSystemError::FileNotFound { context, .. } => context,
47
48 FileSystemError::PermissionDenied { context, .. } => context,
49
50 FileSystemError::IOError { context, .. } => context,
51
52 FileSystemError::InvalidPath { context, .. } => context,
53
54 FileSystemError::DirectoryNotEmpty { context, .. } => context,
55
56 FileSystemError::FileAlreadyExists { context, .. } => context,
57
58 FileSystemError::NotADirectory { context, .. } => context,
59
60 FileSystemError::NotAFile { context, .. } => context,
61 }
62 }
63
64 pub fn file_not_found(path:impl Into<PathBuf>) -> Self {
66 let path = path.into();
67
68 Self::FileNotFound {
69 context:ErrorContext::new(format!("File not found: {}", path.display()))
70 .with_kind(ErrorKind::FileSystem)
71 .with_severity(ErrorSeverity::Error),
72
73 path,
74 }
75 }
76
77 pub fn permission_denied(path:impl Into<PathBuf>) -> Self {
79 let path = path.into();
80
81 Self::PermissionDenied {
82 context:ErrorContext::new(format!("Permission denied: {}", path.display()))
83 .with_kind(ErrorKind::FileSystem)
84 .with_severity(ErrorSeverity::Error),
85
86 path,
87 }
88 }
89
90 pub fn io_error(operation:impl Into<String>, path:Option<PathBuf>, message:impl Into<String>) -> Self {
92 let operation_str = operation.into();
93
94 Self::IOError {
95 context:ErrorContext::new(message)
96 .with_kind(ErrorKind::FileSystem)
97 .with_severity(ErrorSeverity::Error)
98 .with_operation(operation_str.clone()),
99
100 path,
101
102 operation:operation_str,
103 }
104 }
105
106 pub fn invalid_path(path:impl Into<PathBuf>) -> Self {
108 let path = path.into();
109
110 Self::InvalidPath {
111 context:ErrorContext::new(format!("Invalid path: {}", path.display()))
112 .with_kind(ErrorKind::FileSystem)
113 .with_severity(ErrorSeverity::Error),
114
115 path,
116 }
117 }
118
119 pub fn path(&self) -> Option<&PathBuf> {
121 match self {
122 FileSystemError::FileNotFound { path, .. } => Some(path),
123
124 FileSystemError::PermissionDenied { path, .. } => Some(path),
125
126 FileSystemError::IOError { path, .. } => path.as_ref(),
127
128 FileSystemError::InvalidPath { path, .. } => Some(path),
129
130 FileSystemError::DirectoryNotEmpty { path, .. } => Some(path),
131
132 FileSystemError::FileAlreadyExists { path, .. } => Some(path),
133
134 FileSystemError::NotADirectory { path, .. } => Some(path),
135
136 FileSystemError::NotAFile { path, .. } => Some(path),
137 }
138 }
139}
140
141impl fmt::Display for FileSystemError {
142 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
143 write!(f, "{}", self.context())?;
144
145 if let Some(path) = self.path() {
146 write!(f, " (path: {})", path.display())?;
147 }
148
149 Ok(())
150 }
151}
152
153impl StdError for FileSystemError {}
154
155impl From<FileSystemError> for MountainError {
156 fn from(err:FileSystemError) -> Self { MountainError::new(err.context().clone()).with_source(err.to_string()) }
157}
158
159impl From<std::io::Error> for FileSystemError {
160 fn from(err:std::io::Error) -> Self { Self::io_error("I/O operation", None, err.to_string()) }
161}