1 | use std::error::Error as StdError;
|
2 | use std::fmt;
|
3 | use std::io;
|
4 | use std::path::PathBuf;
|
5 |
|
6 | #[derive (Debug, Clone, Copy)]
|
7 | pub(crate) enum ErrorKind {
|
8 | OpenFile,
|
9 | CreateFile,
|
10 | CreateDir,
|
11 | SyncFile,
|
12 | SetLen,
|
13 | Metadata,
|
14 | Clone,
|
15 | SetPermissions,
|
16 | Read,
|
17 | Seek,
|
18 | Write,
|
19 | Flush,
|
20 | ReadDir,
|
21 | RemoveFile,
|
22 | RemoveDir,
|
23 | Canonicalize,
|
24 | ReadLink,
|
25 | SymlinkMetadata,
|
26 | #[allow (dead_code)]
|
27 | FileExists,
|
28 |
|
29 | #[cfg (windows)]
|
30 | SeekRead,
|
31 | #[cfg (windows)]
|
32 | SeekWrite,
|
33 |
|
34 | #[cfg (unix)]
|
35 | ReadAt,
|
36 | #[cfg (unix)]
|
37 | WriteAt,
|
38 | }
|
39 |
|
40 | /// Contains an IO error that has a file path attached.
|
41 | ///
|
42 | /// This type is never returned directly, but is instead wrapped inside yet
|
43 | /// another IO error.
|
44 | #[derive (Debug)]
|
45 | pub(crate) struct Error {
|
46 | kind: ErrorKind,
|
47 | source: io::Error,
|
48 | path: PathBuf,
|
49 | }
|
50 |
|
51 | impl Error {
|
52 | pub fn build(source: io::Error, kind: ErrorKind, path: impl Into<PathBuf>) -> io::Error {
|
53 | io::Error::new(
|
54 | source.kind(),
|
55 | Self {
|
56 | kind,
|
57 | source,
|
58 | path: path.into(),
|
59 | },
|
60 | )
|
61 | }
|
62 | }
|
63 |
|
64 | impl fmt::Display for Error {
|
65 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
66 | use ErrorKind::*;
|
67 |
|
68 | let path = self.path.display();
|
69 |
|
70 | match self.kind {
|
71 | OpenFile => write!(formatter, "failed to open file ` {}`" , path),
|
72 | CreateFile => write!(formatter, "failed to create file ` {}`" , path),
|
73 | CreateDir => write!(formatter, "failed to create directory ` {}`" , path),
|
74 | SyncFile => write!(formatter, "failed to sync file ` {}`" , path),
|
75 | SetLen => write!(formatter, "failed to set length of file ` {}`" , path),
|
76 | Metadata => write!(formatter, "failed to query metadata of file ` {}`" , path),
|
77 | Clone => write!(formatter, "failed to clone handle for file ` {}`" , path),
|
78 | SetPermissions => write!(formatter, "failed to set permissions for file ` {}`" , path),
|
79 | Read => write!(formatter, "failed to read from file ` {}`" , path),
|
80 | Seek => write!(formatter, "failed to seek in file ` {}`" , path),
|
81 | Write => write!(formatter, "failed to write to file ` {}`" , path),
|
82 | Flush => write!(formatter, "failed to flush file ` {}`" , path),
|
83 | ReadDir => write!(formatter, "failed to read directory ` {}`" , path),
|
84 | RemoveFile => write!(formatter, "failed to remove file ` {}`" , path),
|
85 | RemoveDir => write!(formatter, "failed to remove directory ` {}`" , path),
|
86 | Canonicalize => write!(formatter, "failed to canonicalize path ` {}`" , path),
|
87 | ReadLink => write!(formatter, "failed to read symbolic link ` {}`" , path),
|
88 | SymlinkMetadata => write!(formatter, "failed to query metadata of symlink ` {}`" , path),
|
89 | FileExists => write!(formatter, "failed to check file existance ` {}`" , path),
|
90 |
|
91 | #[cfg (windows)]
|
92 | SeekRead => write!(formatter, "failed to seek and read from `{}`" , path),
|
93 | #[cfg (windows)]
|
94 | SeekWrite => write!(formatter, "failed to seek and write to `{}`" , path),
|
95 |
|
96 | #[cfg (unix)]
|
97 | ReadAt => write!(formatter, "failed to read with offset from ` {}`" , path),
|
98 | #[cfg (unix)]
|
99 | WriteAt => write!(formatter, "failed to write with offset to ` {}`" , path),
|
100 | }
|
101 | }
|
102 | }
|
103 |
|
104 | impl StdError for Error {
|
105 | fn cause(&self) -> Option<&dyn StdError> {
|
106 | self.source()
|
107 | }
|
108 |
|
109 | fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
110 | Some(&self.source)
|
111 | }
|
112 | }
|
113 |
|
114 | #[derive (Debug, Clone, Copy)]
|
115 | pub(crate) enum SourceDestErrorKind {
|
116 | Copy,
|
117 | HardLink,
|
118 | Rename,
|
119 | SoftLink,
|
120 |
|
121 | #[cfg (unix)]
|
122 | Symlink,
|
123 |
|
124 | #[cfg (windows)]
|
125 | SymlinkDir,
|
126 | #[cfg (windows)]
|
127 | SymlinkFile,
|
128 | }
|
129 |
|
130 | /// Error type used by functions like `fs::copy` that holds two paths.
|
131 | #[derive (Debug)]
|
132 | pub(crate) struct SourceDestError {
|
133 | kind: SourceDestErrorKind,
|
134 | source: io::Error,
|
135 | from_path: PathBuf,
|
136 | to_path: PathBuf,
|
137 | }
|
138 |
|
139 | impl SourceDestError {
|
140 | pub fn build(
|
141 | source: io::Error,
|
142 | kind: SourceDestErrorKind,
|
143 | from_path: impl Into<PathBuf>,
|
144 | to_path: impl Into<PathBuf>,
|
145 | ) -> io::Error {
|
146 | io::Error::new(
|
147 | source.kind(),
|
148 | Self {
|
149 | kind,
|
150 | source,
|
151 | from_path: from_path.into(),
|
152 | to_path: to_path.into(),
|
153 | },
|
154 | )
|
155 | }
|
156 | }
|
157 |
|
158 | impl fmt::Display for SourceDestError {
|
159 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
160 | let from = self.from_path.display();
|
161 | let to = self.to_path.display();
|
162 | match self.kind {
|
163 | SourceDestErrorKind::Copy => {
|
164 | write!(formatter, "failed to copy file from {} to {}" , from, to)
|
165 | }
|
166 | SourceDestErrorKind::HardLink => {
|
167 | write!(formatter, "failed to hardlink file from {} to {}" , from, to)
|
168 | }
|
169 | SourceDestErrorKind::Rename => {
|
170 | write!(formatter, "failed to rename file from {} to {}" , from, to)
|
171 | }
|
172 | SourceDestErrorKind::SoftLink => {
|
173 | write!(formatter, "failed to softlink file from {} to {}" , from, to)
|
174 | }
|
175 |
|
176 | #[cfg (unix)]
|
177 | SourceDestErrorKind::Symlink => {
|
178 | write!(formatter, "failed to symlink file from {} to {}" , from, to)
|
179 | }
|
180 |
|
181 | #[cfg (windows)]
|
182 | SourceDestErrorKind::SymlinkFile => {
|
183 | write!(formatter, "failed to symlink file from {} to {}" , from, to)
|
184 | }
|
185 | #[cfg (windows)]
|
186 | SourceDestErrorKind::SymlinkDir => {
|
187 | write!(formatter, "failed to symlink dir from {} to {}" , from, to)
|
188 | }
|
189 | }
|
190 | }
|
191 | }
|
192 |
|
193 | impl StdError for SourceDestError {
|
194 | fn cause(&self) -> Option<&dyn StdError> {
|
195 | self.source()
|
196 | }
|
197 |
|
198 | fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
199 | Some(&self.source)
|
200 | }
|
201 | }
|
202 | |