Mountain/Error/
FileSystemError.rs1use std::{error::Error as StdError, fmt, path::PathBuf};
7
8use serde::{Deserialize, Serialize};
9
10use super::CoreError::{ErrorContext, ErrorKind, ErrorSeverity, MountainError, Result};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub enum FileSystemError {
15 FileNotFound { context:ErrorContext, path:PathBuf },
17 PermissionDenied { context:ErrorContext, path:PathBuf },
19 IOError { context:ErrorContext, path:Option<PathBuf>, operation:String },
21 InvalidPath { context:ErrorContext, path:PathBuf },
23 DirectoryNotEmpty { context:ErrorContext, path:PathBuf },
25 FileAlreadyExists { context:ErrorContext, path:PathBuf },
27 NotADirectory { context:ErrorContext, path:PathBuf },
29 NotAFile { context:ErrorContext, path:PathBuf },
31}
32
33impl FileSystemError {
34 pub fn context(&self) -> &ErrorContext {
36 match self {
37 FileSystemError::FileNotFound { context, .. } => context,
38 FileSystemError::PermissionDenied { context, .. } => context,
39 FileSystemError::IOError { context, .. } => context,
40 FileSystemError::InvalidPath { context, .. } => context,
41 FileSystemError::DirectoryNotEmpty { context, .. } => context,
42 FileSystemError::FileAlreadyExists { context, .. } => context,
43 FileSystemError::NotADirectory { context, .. } => context,
44 FileSystemError::NotAFile { context, .. } => context,
45 }
46 }
47
48 pub fn file_not_found(path:impl Into<PathBuf>) -> Self {
50 let path = path.into();
51 Self::FileNotFound {
52 context:ErrorContext::new(format!("File not found: {}", path.display()))
53 .with_kind(ErrorKind::FileSystem)
54 .with_severity(ErrorSeverity::Error),
55 path,
56 }
57 }
58
59 pub fn permission_denied(path:impl Into<PathBuf>) -> Self {
61 let path = path.into();
62 Self::PermissionDenied {
63 context:ErrorContext::new(format!("Permission denied: {}", path.display()))
64 .with_kind(ErrorKind::FileSystem)
65 .with_severity(ErrorSeverity::Error),
66 path,
67 }
68 }
69
70 pub fn io_error(operation:impl Into<String>, path:Option<PathBuf>, message:impl Into<String>) -> Self {
72 let operation_str = operation.into();
73 Self::IOError {
74 context:ErrorContext::new(message)
75 .with_kind(ErrorKind::FileSystem)
76 .with_severity(ErrorSeverity::Error)
77 .with_operation(operation_str.clone()),
78 path,
79 operation:operation_str,
80 }
81 }
82
83 pub fn invalid_path(path:impl Into<PathBuf>) -> Self {
85 let path = path.into();
86 Self::InvalidPath {
87 context:ErrorContext::new(format!("Invalid path: {}", path.display()))
88 .with_kind(ErrorKind::FileSystem)
89 .with_severity(ErrorSeverity::Error),
90 path,
91 }
92 }
93
94 pub fn path(&self) -> Option<&PathBuf> {
96 match self {
97 FileSystemError::FileNotFound { path, .. } => Some(path),
98 FileSystemError::PermissionDenied { path, .. } => Some(path),
99 FileSystemError::IOError { path, .. } => path.as_ref(),
100 FileSystemError::InvalidPath { path, .. } => Some(path),
101 FileSystemError::DirectoryNotEmpty { path, .. } => Some(path),
102 FileSystemError::FileAlreadyExists { path, .. } => Some(path),
103 FileSystemError::NotADirectory { path, .. } => Some(path),
104 FileSystemError::NotAFile { path, .. } => Some(path),
105 }
106 }
107}
108
109impl fmt::Display for FileSystemError {
110 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
111 write!(f, "{}", self.context())?;
112 if let Some(path) = self.path() {
113 write!(f, " (path: {})", path.display())?;
114 }
115 Ok(())
116 }
117}
118
119impl StdError for FileSystemError {}
120
121impl From<FileSystemError> for MountainError {
122 fn from(err:FileSystemError) -> Self { MountainError::new(err.context().clone()).with_source(err.to_string()) }
123}
124
125impl From<std::io::Error> for FileSystemError {
126 fn from(err:std::io::Error) -> Self { Self::io_error("I/O operation", None, err.to_string()) }
127}