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