use std::os;
#[cfg(target_family = "unix")]
pub use os::unix::fs::FileExt;
#[cfg(target_family = "wasm")]
pub use os::wasi::fs::FileExt;
#[cfg(target_family = "windows")]
pub trait FileExt {
fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> Result<()> {
while !buf.is_empty() {
match self.read_at(buf, offset) {
Ok(0) => break,
Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
offset += n as u64;
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(Error::new(
ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
} else {
Ok(())
}
}
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> Result<()> {
while !buf.is_empty() {
match self.write_at(buf, offset) {
Ok(0) => {
return Err(Error::new(
ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => {
buf = &buf[n..];
offset += n as u64
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
#[cfg(target_family = "windows")]
use std::{
fs::File,
io::{Error, ErrorKind, Result},
};
#[cfg(target_family = "windows")]
impl FileExt for File {
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
os::windows::fs::FileExt::seek_read(self, buf, offset)
}
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
os::windows::fs::FileExt::seek_write(self, buf, offset)
}
}