1use std::fs;
2use std::io::{self, Read, Seek, Write};
3use std::path::{Path, PathBuf};
4
5use crate::errors::{Error, ErrorKind};
6use crate::OpenOptions;
7
8#[derive(Debug)]
13pub struct File {
14 file: fs::File,
15 path: PathBuf,
16}
17
18pub(crate) fn open(path: &Path) -> Result<std::fs::File, impl FnOnce(PathBuf) -> io::Error> {
21 fs::File::open(path).map_err(|err| |path| Error::build(err, ErrorKind::OpenFile, path))
22}
23
24pub(crate) fn create(path: &Path) -> Result<std::fs::File, impl FnOnce(PathBuf) -> io::Error> {
26 fs::File::create(path).map_err(|err| |path| Error::build(err, ErrorKind::CreateFile, path))
27}
28
29impl File {
33 pub fn open<P>(path: P) -> Result<Self, io::Error>
37 where
38 P: Into<PathBuf>,
39 {
40 let path = path.into();
41 match open(&path) {
42 Ok(file) => Ok(File::from_parts(file, path)),
43 Err(err_gen) => Err(err_gen(path)),
44 }
45 }
46
47 pub fn create<P>(path: P) -> Result<Self, io::Error>
51 where
52 P: Into<PathBuf>,
53 {
54 let path = path.into();
55 match create(&path) {
56 Ok(file) => Ok(File::from_parts(file, path)),
57 Err(err_gen) => Err(err_gen(path)),
58 }
59 }
60
61 pub fn create_new<P>(path: P) -> Result<Self, io::Error>
65 where
66 P: Into<PathBuf>,
67 {
68 let path = path.into();
69 match fs::OpenOptions::new()
71 .read(true)
72 .write(true)
73 .create_new(true)
74 .open(&path)
75 {
76 Ok(file) => Ok(File::from_parts(file, path)),
77 Err(err) => Err(Error::build(err, ErrorKind::CreateFile, path)),
78 }
79 }
80
81 pub fn options() -> OpenOptions {
85 OpenOptions::new()
86 }
87
88 pub fn sync_all(&self) -> Result<(), io::Error> {
92 self.file
93 .sync_all()
94 .map_err(|source| self.error(source, ErrorKind::SyncFile))
95 }
96
97 pub fn sync_data(&self) -> Result<(), io::Error> {
101 self.file
102 .sync_data()
103 .map_err(|source| self.error(source, ErrorKind::SyncFile))
104 }
105
106 pub fn set_len(&self, size: u64) -> Result<(), io::Error> {
110 self.file
111 .set_len(size)
112 .map_err(|source| self.error(source, ErrorKind::SetLen))
113 }
114
115 pub fn metadata(&self) -> Result<fs::Metadata, io::Error> {
119 self.file
120 .metadata()
121 .map_err(|source| self.error(source, ErrorKind::Metadata))
122 }
123
124 pub fn try_clone(&self) -> Result<Self, io::Error> {
130 self.file
131 .try_clone()
132 .map(|file| File {
133 file,
134 path: self.path.clone(),
135 })
136 .map_err(|source| self.error(source, ErrorKind::Clone))
137 }
138
139 pub fn set_permissions(&self, perm: fs::Permissions) -> Result<(), io::Error> {
143 self.file
144 .set_permissions(perm)
145 .map_err(|source| self.error(source, ErrorKind::SetPermissions))
146 }
147}
148
149impl File {
154 pub fn from_parts<P>(file: fs::File, path: P) -> Self
156 where
157 P: Into<PathBuf>,
158 {
159 File {
160 file,
161 path: path.into(),
162 }
163 }
164
165 pub fn into_parts(self) -> (fs::File, PathBuf) {
167 (self.file, self.path)
168 }
169
170 pub fn file(&self) -> &fs::File {
174 &self.file
175 }
176
177 pub fn file_mut(&mut self) -> &mut fs::File {
181 &mut self.file
182 }
183
184 pub fn path(&self) -> &Path {
186 &self.path
187 }
188
189 fn error(&self, source: io::Error, kind: ErrorKind) -> io::Error {
191 Error::build(source, kind, &self.path)
192 }
193}
194
195impl Read for File {
196 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
197 self.file
198 .read(buf)
199 .map_err(|source| self.error(source, ErrorKind::Read))
200 }
201
202 fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
203 self.file
204 .read_vectored(bufs)
205 .map_err(|source| self.error(source, ErrorKind::Read))
206 }
207}
208
209impl Read for &File {
210 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
211 (&self.file)
212 .read(buf)
213 .map_err(|source| self.error(source, ErrorKind::Read))
214 }
215
216 fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
217 (&self.file)
218 .read_vectored(bufs)
219 .map_err(|source| self.error(source, ErrorKind::Read))
220 }
221}
222
223impl From<File> for fs::File {
224 fn from(file: File) -> Self {
225 file.into_parts().0
226 }
227}
228
229impl Seek for File {
230 fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
231 self.file
232 .seek(pos)
233 .map_err(|source| self.error(source, ErrorKind::Seek))
234 }
235}
236
237impl Seek for &File {
238 fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
239 (&self.file)
240 .seek(pos)
241 .map_err(|source| self.error(source, ErrorKind::Seek))
242 }
243}
244
245impl Write for File {
246 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
247 self.file
248 .write(buf)
249 .map_err(|source| self.error(source, ErrorKind::Write))
250 }
251
252 fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
253 self.file
254 .write_vectored(bufs)
255 .map_err(|source| self.error(source, ErrorKind::Write))
256 }
257
258 fn flush(&mut self) -> std::io::Result<()> {
259 self.file
260 .flush()
261 .map_err(|source| self.error(source, ErrorKind::Flush))
262 }
263}
264
265impl Write for &File {
266 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
267 (&self.file)
268 .write(buf)
269 .map_err(|source| self.error(source, ErrorKind::Write))
270 }
271
272 fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
273 (&self.file)
274 .write_vectored(bufs)
275 .map_err(|source| self.error(source, ErrorKind::Write))
276 }
277
278 fn flush(&mut self) -> std::io::Result<()> {
279 (&self.file)
280 .flush()
281 .map_err(|source| self.error(source, ErrorKind::Flush))
282 }
283}
284
285#[cfg(unix)]
286mod unix {
287 use crate::os::unix::fs::FileExt;
288 use crate::ErrorKind;
289 use std::io;
290 use std::os::unix::fs::FileExt as _;
291 use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
292
293 impl AsRawFd for crate::File {
294 fn as_raw_fd(&self) -> RawFd {
295 self.file().as_raw_fd()
296 }
297 }
298
299 impl IntoRawFd for crate::File {
300 fn into_raw_fd(self) -> RawFd {
301 self.file.into_raw_fd()
302 }
303 }
304
305 impl FileExt for crate::File {
306 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
307 self.file()
308 .read_at(buf, offset)
309 .map_err(|err| self.error(err, ErrorKind::ReadAt))
310 }
311 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
312 self.file()
313 .write_at(buf, offset)
314 .map_err(|err| self.error(err, ErrorKind::WriteAt))
315 }
316 }
317
318 #[cfg(rustc_1_63)]
319 mod io_safety {
320 use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
321
322 impl AsFd for crate::File {
323 fn as_fd(&self) -> BorrowedFd<'_> {
324 self.file().as_fd()
325 }
326 }
327
328 impl From<crate::File> for OwnedFd {
329 fn from(file: crate::File) -> Self {
330 file.into_parts().0.into()
331 }
332 }
333 }
334}
335
336#[cfg(windows)]
337mod windows {
338 use crate::os::windows::fs::FileExt;
339 use crate::ErrorKind;
340 use std::io;
341 use std::os::windows::{
342 fs::FileExt as _,
343 io::{AsRawHandle, IntoRawHandle, RawHandle},
344 };
345
346 impl FileExt for crate::File {
347 fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
348 self.file()
349 .seek_read(buf, offset)
350 .map_err(|err| self.error(err, ErrorKind::SeekRead))
351 }
352
353 fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
354 self.file()
355 .seek_write(buf, offset)
356 .map_err(|err| self.error(err, ErrorKind::SeekWrite))
357 }
358 }
359
360 impl AsRawHandle for crate::File {
361 fn as_raw_handle(&self) -> RawHandle {
362 self.file().as_raw_handle()
363 }
364 }
365
366 impl IntoRawHandle for crate::File {
371 fn into_raw_handle(self) -> RawHandle {
372 self.file.into_raw_handle()
373 }
374 }
375
376 #[cfg(rustc_1_63)]
377 mod io_safety {
378 use std::os::windows::io::{AsHandle, BorrowedHandle, OwnedHandle};
379
380 impl AsHandle for crate::File {
381 fn as_handle(&self) -> BorrowedHandle<'_> {
382 self.file().as_handle()
383 }
384 }
385
386 impl From<crate::File> for OwnedHandle {
387 fn from(file: crate::File) -> Self {
388 file.into_parts().0.into()
389 }
390 }
391 }
392}