use super::{as_file, into_file};
#[cfg(not(any(
windows,
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "redox",
)))]
use posish::fs::fadvise;
#[cfg(not(any(windows, target_os = "netbsd", target_os = "redox")))]
use posish::fs::posix_fallocate;
#[cfg(any(target_os = "ios", target_os = "macos"))]
use posish::fs::rdadvise;
#[cfg(not(windows))]
use posish::fs::tell;
#[cfg(not(any(windows, target_os = "ios", target_os = "macos", target_os = "redox")))]
use posish::fs::{preadv, pwritev};
#[cfg(unix)]
use std::os::unix::{fs::FileExt, io::AsRawFd};
#[cfg(target_os = "wasi")]
use std::os::wasi::{fs::FileExt, io::AsRawFd};
use std::{
convert::TryInto,
fmt::Arguments,
fs,
io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write},
slice,
};
#[cfg(windows)]
use {
std::os::windows::{
fs::FileExt,
io::{AsRawHandle, FromRawHandle, RawHandle},
},
winx::file::{reopen_file, AccessMode, Flags},
};
#[cfg(not(any(
windows,
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "redox"
)))]
#[derive(Debug, Eq, PartialEq, Hash)]
#[repr(i32)]
pub enum Advice {
Normal = posish::fs::Advice::Normal as i32,
Sequential = posish::fs::Advice::Sequential as i32,
Random = posish::fs::Advice::Random as i32,
WillNeed = posish::fs::Advice::WillNeed as i32,
DontNeed = posish::fs::Advice::DontNeed as i32,
NoReuse = posish::fs::Advice::NoReuse as i32,
}
#[cfg(any(
windows,
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "redox"
))]
#[derive(Debug, Eq, PartialEq, Hash)]
pub enum Advice {
Normal,
Sequential,
Random,
WillNeed,
DontNeed,
NoReuse,
}
pub trait FileIoExt {
fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()>;
fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
fn read(&self, buf: &mut [u8]) -> io::Result<usize>;
fn read_exact(&self, buf: &mut [u8]) -> io::Result<()>;
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()>;
fn read_vectored(&self, bufs: &mut [IoSliceMut]) -> io::Result<usize>;
fn read_exact_vectored(&self, mut bufs: &mut [IoSliceMut]) -> io::Result<()> {
while !bufs.is_empty() {
match self.read_vectored(bufs) {
Ok(0) => break,
Ok(nread) => bufs = advance_mut(bufs, nread),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => (),
Err(e) => return Err(e),
}
}
Ok(())
}
fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
let buf = bufs
.iter_mut()
.find(|b| !b.is_empty())
.map_or(&mut [][..], |b| &mut **b);
self.read_at(buf, offset)
}
fn read_exact_vectored_at(
&self,
mut bufs: &mut [IoSliceMut],
mut offset: u64,
) -> io::Result<()> {
while !bufs.is_empty() {
match self.read_vectored_at(bufs, offset) {
Ok(0) => break,
Ok(nread) => {
offset = offset
.checked_add(nread.try_into().unwrap())
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "offset overflow"))?;
bufs = advance_mut(bufs, nread);
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => (),
Err(e) => return Err(e),
}
}
Ok(())
}
#[inline]
fn is_read_vectored_at(&self) -> bool {
false
}
fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize>;
fn read_to_string(&self, buf: &mut String) -> io::Result<usize>;
fn bytes(self) -> io::Bytes<fs::File>;
fn take(self, limit: u64) -> io::Take<fs::File>;
fn write(&self, buf: &[u8]) -> io::Result<usize>;
fn write_all(&self, buf: &[u8]) -> io::Result<()>;
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()>;
fn write_vectored(&self, bufs: &[IoSlice]) -> io::Result<usize>;
fn write_all_vectored(&self, mut bufs: &mut [IoSlice]) -> io::Result<()> {
while !bufs.is_empty() {
match self.write_vectored(bufs) {
Ok(nwritten) => bufs = advance(bufs, nwritten),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => (),
Err(e) => return Err(e),
}
}
Ok(())
}
fn write_vectored_at(&self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
let buf = bufs
.iter()
.find(|b| !b.is_empty())
.map_or(&[][..], |b| &**b);
self.write_at(buf, offset)
}
fn write_all_vectored_at(&self, mut bufs: &mut [IoSlice], mut offset: u64) -> io::Result<()> {
while !bufs.is_empty() {
match self.write_vectored_at(bufs, offset) {
Ok(nwritten) => {
offset = offset
.checked_add(nwritten.try_into().unwrap())
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "offset overflow"))?;
bufs = advance(bufs, nwritten);
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => (),
Err(e) => return Err(e),
}
}
Ok(())
}
#[inline]
fn is_write_vectored_at(&self) -> bool {
false
}
fn write_fmt(&self, fmt: Arguments) -> io::Result<()>;
fn flush(&self) -> io::Result<()>;
fn seek(&self, pos: SeekFrom) -> io::Result<u64>;
fn stream_position(&self) -> io::Result<u64>;
}
fn advance<'a, 'b>(bufs: &'b mut [IoSlice<'a>], n: usize) -> &'b mut [IoSlice<'a>] {
let mut remove = 0;
let mut accumulated_len = 0;
for buf in bufs.iter() {
if accumulated_len + buf.len() > n {
break;
} else {
accumulated_len += buf.len();
remove += 1;
}
}
#[allow(clippy::indexing_slicing)]
let bufs = &mut bufs[remove..];
if let Some(first) = bufs.first_mut() {
let advance_by = n - accumulated_len;
let mut ptr = first.as_ptr();
let mut len = first.len();
unsafe {
ptr = ptr.add(advance_by);
len -= advance_by;
*first = IoSlice::<'a>::new(slice::from_raw_parts::<'a>(ptr, len));
}
}
bufs
}
fn advance_mut<'a, 'b>(bufs: &'b mut [IoSliceMut<'a>], n: usize) -> &'b mut [IoSliceMut<'a>] {
let mut remove = 0;
let mut accumulated_len = 0;
for buf in bufs.iter() {
if accumulated_len + buf.len() > n {
break;
} else {
accumulated_len += buf.len();
remove += 1;
}
}
#[allow(clippy::indexing_slicing)]
let bufs = &mut bufs[remove..];
if let Some(first) = bufs.first_mut() {
let advance_by = n - accumulated_len;
let mut ptr = first.as_mut_ptr();
let mut len = first.len();
unsafe {
ptr = ptr.add(advance_by);
len -= advance_by;
*first = IoSliceMut::<'a>::new(slice::from_raw_parts_mut::<'a>(ptr, len));
}
}
bufs
}
#[cfg(not(windows))]
impl<T> FileIoExt for T
where
T: AsRawFd,
{
#[cfg(not(any(
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "redox"
)))]
#[inline]
fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
let advice = match advice {
Advice::WillNeed => posish::fs::Advice::WillNeed,
Advice::Normal => posish::fs::Advice::Normal,
Advice::Sequential => posish::fs::Advice::Sequential,
Advice::NoReuse => posish::fs::Advice::NoReuse,
Advice::Random => posish::fs::Advice::Random,
Advice::DontNeed => posish::fs::Advice::DontNeed,
};
fadvise(self, offset, len, advice)
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[inline]
fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
match advice {
Advice::WillNeed => (),
Advice::Normal
| Advice::Sequential
| Advice::NoReuse
| Advice::Random
| Advice::DontNeed => return Ok(()),
}
rdadvise(self, offset, len)
}
#[cfg(any(target_os = "netbsd", target_os = "redox"))]
#[inline]
fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> io::Result<()> {
Ok(())
}
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
#[inline]
fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
posix_fallocate(self, offset, len)
}
#[cfg(target_os = "netbsd")]
fn allocate(&self, _offset: u64, _len: u64) -> io::Result<()> {
todo!("NetBSD 7.0 supports posix_fallocate; add bindings for it")
}
#[cfg(target_os = "redox")]
fn allocate(&self, _offset: u64, _len: u64) -> io::Result<()> {
todo!("figure out what to do on redox for posix_fallocate")
}
#[inline]
fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
Read::read(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_exact(&self, buf: &mut [u8]) -> io::Result<()> {
Read::read_exact(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
FileExt::read_at(&*unsafe { as_file(self) }, buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
FileExt::read_exact_at(&*unsafe { as_file(self) }, buf, offset)
}
#[inline]
fn read_vectored(&self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
Read::read_vectored(&mut *unsafe { as_file(self) }, bufs)
}
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
#[inline]
fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
preadv(self, bufs, offset)
}
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
#[inline]
fn is_read_vectored_at(&self) -> bool {
true
}
#[inline]
fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
Read::read_to_end(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_to_string(&self, buf: &mut String) -> io::Result<usize> {
Read::read_to_string(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn bytes(self) -> io::Bytes<fs::File> where {
Read::bytes(into_file(self))
}
#[inline]
fn take(self, limit: u64) -> io::Take<fs::File> where {
Read::take(into_file(self), limit)
}
#[inline]
fn write(&self, buf: &[u8]) -> io::Result<usize> {
Write::write(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn write_all(&self, buf: &[u8]) -> io::Result<()> {
Write::write_all(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
FileExt::write_at(&*unsafe { as_file(self) }, buf, offset)
}
#[inline]
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
FileExt::write_all_at(&*unsafe { as_file(self) }, buf, offset)
}
#[inline]
fn write_vectored(&self, bufs: &[IoSlice]) -> io::Result<usize> {
Write::write_vectored(&mut *unsafe { as_file(self) }, bufs)
}
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
#[inline]
fn write_vectored_at(&self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
pwritev(self, bufs, offset)
}
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
#[inline]
fn is_write_vectored_at(&self) -> bool {
true
}
#[inline]
fn flush(&self) -> io::Result<()> {
Write::flush(&mut *unsafe { as_file(self) })
}
#[inline]
fn write_fmt(&self, fmt: Arguments) -> io::Result<()> {
Write::write_fmt(&mut *unsafe { as_file(self) }, fmt)
}
#[inline]
fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
Seek::seek(&mut *unsafe { as_file(self) }, pos)
}
#[inline]
fn stream_position(&self) -> io::Result<u64> {
tell(self)
}
}
#[cfg(windows)]
impl FileIoExt for fs::File {
#[inline]
fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> io::Result<()> {
Ok(())
}
#[inline]
fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
self.set_len(offset.checked_add(len).ok_or_else(|| {
io::Error::new(io::ErrorKind::Other, "overflow while allocating file space")
})?)
}
#[inline]
fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
Read::read(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_exact(&self, buf: &mut [u8]) -> io::Result<()> {
Read::read_exact(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
let reopened = reopen(self)?;
reopened.seek_read(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.read_exact(buf)
}
#[inline]
fn read_vectored(&self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
Read::read_vectored(&mut *unsafe { as_file(self) }, bufs)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
let reopened = reopen(self)?;
reopened.seek(SeekFrom::Start(offset))?;
reopened.read_vectored(bufs)
}
#[inline]
fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.read_exact_vectored(bufs)
}
#[inline]
fn is_read_vectored_at(&self) -> bool {
true
}
#[inline]
fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
Read::read_to_end(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_to_string(&self, buf: &mut String) -> io::Result<usize> {
Read::read_to_string(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn bytes(self) -> io::Bytes<fs::File> where {
Read::bytes(into_file(self))
}
#[inline]
fn take(self, limit: u64) -> io::Take<fs::File> where {
Read::take(into_file(self), limit)
}
#[inline]
fn write(&self, buf: &[u8]) -> io::Result<usize> {
Write::write(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn write_all(&self, buf: &[u8]) -> io::Result<()> {
Write::write_all(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
let reopened = reopen_write(self)?;
reopened.seek_write(buf, offset)
}
#[inline]
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen_write(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.write_all(buf)
}
#[inline]
fn write_vectored(&self, bufs: &[IoSlice]) -> io::Result<usize> {
Write::write_vectored(&mut *unsafe { as_file(self) }, bufs)
}
#[inline]
fn write_vectored_at(&self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
let reopened = reopen_write(self)?;
reopened.seek(SeekFrom::Start(offset))?;
reopened.write_vectored(bufs)
}
#[inline]
fn write_all_vectored_at(&self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen_write(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.write_all_vectored(bufs)
}
#[inline]
fn is_write_vectored_at(&self) -> bool {
true
}
#[inline]
fn flush(&self) -> io::Result<()> {
Write::flush(&mut *unsafe { as_file(self) })
}
#[inline]
fn write_fmt(&self, fmt: Arguments) -> io::Result<()> {
Write::write_fmt(&mut *unsafe { as_file(self) }, fmt)
}
#[inline]
fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
Seek::seek(&mut *unsafe { as_file(self) }, pos)
}
#[inline]
fn stream_position(&self) -> io::Result<u64> {
Seek::seek(&mut *unsafe { as_file(self) }, SeekFrom::Current(0))
}
}
#[cfg(all(windows, feature = "cap_std_impls"))]
impl FileIoExt for cap_std::fs::File {
#[inline]
fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> io::Result<()> {
Ok(())
}
#[inline]
fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
self.set_len(offset.checked_add(len).ok_or_else(|| {
io::Error::new(io::ErrorKind::Other, "overflow while allocating file space")
})?)
}
#[inline]
fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
Read::read(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_exact(&self, buf: &mut [u8]) -> io::Result<()> {
Read::read_exact(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
let reopened = reopen(self)?;
reopened.seek_read(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.read_exact(buf)
}
#[inline]
fn read_vectored(&self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
Read::read_vectored(&mut *unsafe { as_file(self) }, bufs)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
let reopened = reopen(self)?;
reopened.seek(SeekFrom::Start(offset))?;
reopened.read_vectored(bufs)
}
#[inline]
fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.read_exact_vectored(bufs)
}
#[inline]
fn is_read_vectored_at(&self) -> bool {
true
}
#[inline]
fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
Read::read_to_end(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn read_to_string(&self, buf: &mut String) -> io::Result<usize> {
Read::read_to_string(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn bytes(self) -> io::Bytes<fs::File> where {
Read::bytes(into_file(self))
}
#[inline]
fn take(self, limit: u64) -> io::Take<fs::File> where {
Read::take(into_file(self), limit)
}
#[inline]
fn write(&self, buf: &[u8]) -> io::Result<usize> {
Write::write(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn write_all(&self, buf: &[u8]) -> io::Result<()> {
Write::write_all(&mut *unsafe { as_file(self) }, buf)
}
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
let reopened = reopen_write(self)?;
reopened.seek_write(buf, offset)
}
#[inline]
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen_write(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.write_all(buf)
}
#[inline]
fn write_vectored(&self, bufs: &[IoSlice]) -> io::Result<usize> {
Write::write_vectored(&mut *unsafe { as_file(self) }, bufs)
}
#[inline]
fn write_vectored_at(&self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
let reopened = reopen_write(self)?;
reopened.seek(SeekFrom::Start(offset))?;
reopened.write_vectored(bufs)
}
#[inline]
fn write_all_vectored_at(&self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
let reopened = loop {
match reopen_write(self) {
Ok(file) => break file,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
};
loop {
match reopened.seek(SeekFrom::Start(offset)) {
Ok(_) => break,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
reopened.write_all_vectored(bufs)
}
#[inline]
fn is_write_vectored_at(&self) -> bool {
true
}
#[inline]
fn flush(&self) -> io::Result<()> {
Write::flush(&mut *unsafe { as_file(self) })
}
#[inline]
fn write_fmt(&self, fmt: Arguments) -> io::Result<()> {
Write::write_fmt(&mut *unsafe { as_file(self) }, fmt)
}
#[inline]
fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
Seek::seek(&mut *unsafe { as_file(self) }, pos)
}
#[inline]
fn stream_position(&self) -> io::Result<u64> {
Seek::seek(&mut *unsafe { as_file(self) }, SeekFrom::Current(0))
}
}
#[cfg(windows)]
fn reopen<Handle: AsRawHandle>(handle: &Handle) -> io::Result<fs::File> {
let handle = handle.as_raw_handle();
unsafe { _reopen(handle) }
}
#[cfg(windows)]
unsafe fn _reopen(handle: RawHandle) -> io::Result<fs::File> {
let new = reopen_file(handle, AccessMode::FILE_READ_DATA, Flags::empty())?;
Ok(fs::File::from_raw_handle(new))
}
#[cfg(windows)]
fn reopen_write<Handle: AsRawHandle>(handle: &Handle) -> io::Result<fs::File> {
let handle = handle.as_raw_handle();
unsafe { _reopen_write(handle) }
}
#[cfg(windows)]
unsafe fn _reopen_write(handle: RawHandle) -> io::Result<fs::File> {
let new = reopen_file(
handle,
AccessMode::FILE_WRITE_DATA | AccessMode::FILE_APPEND_DATA,
Flags::empty(),
)?;
Ok(fs::File::from_raw_handle(new))
}
fn _file_io_ext_can_be_trait_object(_: &dyn FileIoExt) {}