1use std::os;
2
3#[cfg(target_family = "unix")]
4pub use os::unix::fs::FileExt;
5
6#[cfg(target_family = "wasm")]
7pub use os::wasi::fs::FileExt;
8
9#[cfg(target_family = "windows")]
10pub trait FileExt {
11 fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
12 fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;
13
14 fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> Result<()> {
15 while !buf.is_empty() {
16 match self.read_at(buf, offset) {
17 Ok(0) => break,
18 Ok(n) => {
19 let tmp = buf;
20 buf = &mut tmp[n..];
21 offset += n as u64;
22 }
23 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
24 Err(e) => return Err(e),
25 }
26 }
27 if !buf.is_empty() {
28 Err(Error::new(
29 ErrorKind::UnexpectedEof,
30 "failed to fill whole buffer",
31 ))
32 } else {
33 Ok(())
34 }
35 }
36
37 fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> Result<()> {
38 while !buf.is_empty() {
39 match self.write_at(buf, offset) {
40 Ok(0) => {
41 return Err(Error::new(
42 ErrorKind::WriteZero,
43 "failed to write whole buffer",
44 ));
45 }
46 Ok(n) => {
47 buf = &buf[n..];
48 offset += n as u64
49 }
50 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
51 Err(e) => return Err(e),
52 }
53 }
54 Ok(())
55 }
56}
57
58#[cfg(target_family = "windows")]
59use std::{
60 fs::File,
61 io::{Error, ErrorKind, Result},
62};
63
64#[cfg(target_family = "windows")]
65impl FileExt for File {
66 #[inline]
67 fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
68 os::windows::fs::FileExt::seek_read(self, buf, offset)
69 }
70
71 #[inline]
72 fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
73 os::windows::fs::FileExt::seek_write(self, buf, offset)
74 }
75}