use core::pin::Pin;
use std::fs::{File, FileTimes, Metadata, Permissions};
use std::io;
use std::path::Path;
use std::time::SystemTime;
use futures_io::AsyncWrite;
use super::Allocate;
use super::file::{SyncKind, sync_file};
use super::ops::{OpenOptions, blocking};
use crate::io::Handle;
use crate::io::raw::Raw;
use crate::io::sys;
#[cfg(unix)]
fn raw_of(file: &File) -> Raw {
std::os::fd::AsRawFd::as_raw_fd(file)
}
#[cfg(windows)]
fn raw_of(file: &File) -> Raw {
std::os::windows::io::AsRawHandle::as_raw_handle(file) as usize as Raw
}
impl Handle<File> {
pub async fn create(path: impl AsRef<Path>) -> io::Result<Handle<File>> {
OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(path)
.await
}
pub async fn create_new(path: impl AsRef<Path>) -> io::Result<Handle<File>> {
OpenOptions::new()
.read(true)
.write(true)
.create_new(true)
.open(path)
.await
}
pub fn options() -> OpenOptions {
OpenOptions::new()
}
pub async fn sync_all(&self) -> io::Result<()> {
if !self.is_regular() {
return self.on_pool(File::sync_all).await;
}
self.file()?.sync(SyncKind::All).await
}
pub async fn sync_data(&self) -> io::Result<()> {
if !self.is_regular() {
return self.on_pool(File::sync_data).await;
}
self.file()?.sync(SyncKind::Data).await
}
pub async fn sync_range(&self, offset: u64, len: u64) -> io::Result<()> {
let kind = SyncKind::Range { offset, len };
if !self.is_regular() {
return self.on_pool(move |file| sync_file(file, kind)).await;
}
self.file()?.sync(kind).await
}
pub async fn allocate(&self, offset: u64, len: u64, mode: Allocate) -> io::Result<()> {
if !self.is_regular() {
return self
.on_pool(move |file| sys::allocate(raw_of(file), offset, len, mode))
.await;
}
self.file()?.allocate(offset, len, mode).await
}
pub async fn set_len(&self, len: u64) -> io::Result<()> {
let result = self.on_pool(move |file| file.set_len(len)).await;
if let Some(file) = self.file.get() {
file.moved_on();
}
result
}
pub async fn metadata(&self) -> io::Result<Metadata> {
self.on_pool(File::metadata).await
}
pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
self.on_pool(move |file| file.set_permissions(perm)).await
}
pub async fn set_times(&self, times: FileTimes) -> io::Result<()> {
self.on_pool(move |file| file.set_times(times)).await
}
pub async fn set_modified(&self, time: SystemTime) -> io::Result<()> {
self.on_pool(move |file| file.set_modified(time)).await
}
pub async fn try_clone(&self) -> io::Result<Handle<File>> {
let file = self.on_pool(File::try_clone).await?;
Handle::new(file)
}
async fn on_pool<T, F>(&self, call: F) -> io::Result<T>
where
T: Send + 'static,
F: FnOnce(&File) -> io::Result<T> + Send + 'static,
{
let mut this = self;
core::future::poll_fn(|cx| Pin::new(&mut this).poll_flush(cx)).await?;
let lease = self.source().lease()?;
blocking(move || call(&lease.file())).await
}
}