use std::io;
#[cfg(unix)]
pub trait FileExt {
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
#[cfg(feature = "unix_file_vectored_at")]
fn read_vectored_at(
&self,
bufs: &mut [std::io::IoSliceMut<'_>],
offset: u64,
) -> io::Result<usize> {
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
}
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::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() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
} else {
Ok(())
}
}
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
#[cfg(feature = "unix_file_vectored_at")]
fn write_vectored_at(&self, bufs: &[std::io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
}
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.write_at(buf, offset) {
Ok(0) => {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => {
buf = &buf[n..];
offset += n as u64
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
#[cfg(target_os = "wasi")]
pub trait FileExt {
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
let bufs = &mut [std::io::IoSliceMut::new(buf)];
self.read_vectored_at(bufs, offset)
}
fn read_vectored_at(
&self,
bufs: &mut [std::io::IoSliceMut<'_>],
offset: u64,
) -> io::Result<usize>;
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::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() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
} else {
Ok(())
}
}
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
let bufs = &[std::io::IoSlice::new(buf)];
self.write_vectored_at(bufs, offset)
}
fn write_vectored_at(&self, bufs: &[std::io::IoSlice<'_>], offset: u64) -> io::Result<usize>;
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.write_at(buf, offset) {
Ok(0) => {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => {
buf = &buf[n..];
offset += n as u64
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
fn tell(&self) -> io::Result<u64>;
fn fdstat_set_flags(&self, flags: u16) -> std::io::Result<()>;
fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> std::io::Result<()>;
fn advise(&self, offset: u64, len: u64, advice: u8) -> std::io::Result<()>;
fn allocate(&self, offset: u64, len: u64) -> std::io::Result<()>;
fn create_directory<P: AsRef<std::path::Path>>(&self, dir: P) -> std::io::Result<()>;
fn read_link<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<std::path::PathBuf>;
fn metadata_at<P: AsRef<std::path::Path>>(
&self,
lookup_flags: u32,
path: P,
) -> io::Result<std::fs::Metadata>;
fn remove_file<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<()>;
fn remove_directory<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<()>;
}
#[cfg(windows)]
pub trait FileExt {
fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
}