Skip to main content

file_storage/error/
error.rs

1use crate::StoragePath;
2use crate::{Operation, Reason};
3use std::fmt::{Display, Formatter};
4use std::io;
5use std::io::ErrorKind;
6use std::path::Path;
7
8/// A storage path operation error.
9#[derive(Debug)]
10pub struct Error {
11    path: StoragePath,
12    operation: Operation,
13    reason: Reason,
14    source: Option<io::Error>,
15}
16
17impl Error {
18    //! Construction
19
20    /// Creates an error from the `reason`.
21    ///
22    /// The `source` will be `None`.
23    pub fn new<P>(path: P, operation: Operation, reason: Reason) -> Self
24    where
25        P: Into<StoragePath>,
26    {
27        let path: StoragePath = path.into();
28        Self {
29            path,
30            operation,
31            reason,
32            source: None,
33        }
34    }
35
36    /// Creates an error from the `source`.
37    ///
38    /// The `reason` will be `Other`.
39    pub fn from_source<P, E>(path: P, operation: Operation, source: E) -> Self
40    where
41        P: Into<StoragePath>,
42        E: Into<io::Error>,
43    {
44        let path: StoragePath = path.into();
45        Self {
46            path,
47            operation,
48            reason: Reason::Other,
49            source: Some(source.into()),
50        }
51    }
52
53    /// Creates an error from the `message`.
54    ///
55    /// The `source` will be a `std::io::Error` with the `message`.
56    /// The `reason` will be `Other`.
57    pub fn from_message<P, S>(path: P, operation: Operation, message: S) -> Self
58    where
59        P: Into<StoragePath>,
60        S: Into<String>,
61    {
62        Error::from_source(path, operation, io::Error::other(message.into()))
63    }
64}
65
66impl Error {
67    //! Common IO Errors
68
69    /// Creates the `unknown file system` error.
70    pub fn unknown_file_system(path: &str) -> io::Error {
71        io::Error::other(format!("unknown file system for path: {}", path))
72    }
73
74    /// Creates the `path not utf-8` error.
75    pub fn path_not_utf8(path: &Path) -> io::Error {
76        io::Error::new(
77            ErrorKind::InvalidInput,
78            format!("path not utf-8: {:?}", path),
79        )
80    }
81}
82
83impl Error {
84    //! Properties
85
86    /// Gets the path.
87    pub fn path(&self) -> &StoragePath {
88        &self.path
89    }
90
91    /// Exports the path.
92    pub fn export_path(self) -> StoragePath {
93        self.path
94    }
95
96    /// Gets the operation.
97    pub fn operation(&self) -> Operation {
98        self.operation
99    }
100
101    /// Gets the reason.
102    pub fn reason(&self) -> Reason {
103        self.reason
104    }
105
106    /// Gets the optional source.
107    pub fn source(&self) -> Option<&io::Error> {
108        self.source.as_ref()
109    }
110}
111
112impl From<Error> for io::Error {
113    fn from(error: Error) -> Self {
114        let kind: ErrorKind = match error.reason() {
115            Reason::UnknownFileSystem => ErrorKind::Unsupported,
116            Reason::UnsupportedOperation => ErrorKind::Unsupported,
117            Reason::FileNotFound => ErrorKind::NotFound,
118            Reason::FileAlreadyExists => ErrorKind::AlreadyExists,
119            Reason::FileContentNotUTF8 => ErrorKind::InvalidData,
120            Reason::Other => ErrorKind::Other,
121        };
122        Self::new(kind, error)
123    }
124}
125
126impl Display for Error {
127    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
128        let file_or_folder: &str = if self.path.is_file() {
129            "file"
130        } else {
131            "folder"
132        };
133        write!(
134            f,
135            "{} error: op={} path={} ",
136            file_or_folder, self.operation, self.path
137        )?;
138        if let Some(source) = self.source() {
139            write!(f, "source={}", source)?;
140        } else {
141            write!(f, "reason={}", self.reason)?;
142        }
143        Ok(())
144    }
145}
146
147impl std::error::Error for Error {}