use std::fs::{Metadata, OpenOptions, Permissions};
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::{fmt, io};
use crate::errors::AioCommandError;
use crate::fs::AioOpenOptionsExt;
use crate::{AioContextHandle, AioResult, LockedBuf, Opcode, RawCommand, ReadFlags, WriteFlags};
pub struct File {
pub(crate) inner: tokio::fs::File,
}
impl fmt::Debug for File {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("File").field("inner", &self.inner).finish()
}
}
impl File {
pub async fn open(path: impl AsRef<Path>, is_sync: bool) -> io::Result<File> {
let mut open_options = OpenOptions::new();
open_options.read(true).write(false);
let mut path_buf = PathBuf::new();
path_buf.push(path);
open_options.aio_open(path_buf, is_sync).await
}
pub async fn create(path: impl AsRef<Path>, is_sync: bool) -> io::Result<File> {
let mut open_options = OpenOptions::new();
open_options.write(true).truncate(true).create(true);
let mut path_buf = PathBuf::new();
path_buf.push(path);
open_options.aio_open(path_buf, is_sync).await
}
pub async fn set_len(&mut self, size: u64) -> io::Result<()> {
self.inner.set_len(size).await
}
pub async fn metadata(&self) -> io::Result<Metadata> {
self.inner.metadata().await
}
pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
self.inner.set_permissions(perm).await
}
pub async fn read_at(
&self,
aio_handle: &AioContextHandle,
offset: u64,
buffer: &mut LockedBuf,
flags: ReadFlags,
) -> Result<AioResult, AioCommandError> {
let (ptr, len) = buffer.aio_addr_and_len();
aio_handle
.submit_request(
self,
RawCommand {
opcode: Opcode::Pread,
offset,
len,
buf: ptr,
flags: flags.bits() as _,
},
)
.await
}
pub async fn write_at(
&self,
aio_handle: &AioContextHandle,
offset: u64,
buffer: &LockedBuf,
flags: WriteFlags,
) -> Result<AioResult, AioCommandError> {
let (ptr, len) = buffer.aio_addr_and_len();
aio_handle
.submit_request(
self,
RawCommand {
opcode: Opcode::Pwrite,
offset,
len,
buf: ptr as u64,
flags: flags.bits() as _,
},
)
.await
}
pub async fn sync_all(
&self,
aio_handle: &AioContextHandle,
) -> Result<AioResult, AioCommandError> {
aio_handle
.submit_request(
self,
RawCommand {
opcode: Opcode::Fsync,
buf: 0,
len: 0,
offset: 0,
flags: 0,
},
)
.await
}
pub async fn sync_data(
&self,
aio_handle: &AioContextHandle,
) -> Result<AioResult, AioCommandError> {
aio_handle
.submit_request(
self,
RawCommand {
opcode: Opcode::Fdsync,
buf: 0,
len: 0,
offset: 0,
flags: 0,
},
)
.await
}
}
impl AsRawFd for File {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
impl AsRawFd for &'_ File {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}