#[cfg(unix)]
#[path = "unix.rs"]
mod sys;
#[cfg(windows)]
#[path = "windows.rs"]
mod sys;
use std::{io, path::Path};
use compio_buf::{buf_try, BufResult, IoBuf};
use compio_io::{AsyncReadAtExt, AsyncWriteAtExt};
use crate::{metadata, File};
pub async fn remove_file(path: impl AsRef<Path>) -> io::Result<()> {
sys::remove_file(path).await
}
pub async fn remove_dir(path: impl AsRef<Path>) -> io::Result<()> {
sys::remove_dir(path).await
}
pub async fn create_dir(path: impl AsRef<Path>) -> io::Result<()> {
DirBuilder::new().create(path).await
}
pub async fn create_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
DirBuilder::new().recursive(true).create(path).await
}
pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
sys::rename(from, to).await
}
#[cfg(unix)]
pub async fn symlink(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
sys::symlink(original, link).await
}
#[cfg(windows)]
pub async fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
sys::symlink_file(original, link).await
}
#[cfg(windows)]
pub async fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
sys::symlink_dir(original, link).await
}
pub async fn hard_link(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
sys::hard_link(original, link).await
}
pub async fn write<P: AsRef<Path>, B: IoBuf>(path: P, buf: B) -> BufResult<(), B> {
let (mut file, buf) = buf_try!(File::create(path).await, buf);
file.write_all_at(buf, 0).await
}
pub async fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
let file = File::open(path).await?;
let BufResult(res, buffer) = file.read_to_end_at(Vec::new(), 0).await;
res?;
Ok(buffer)
}
pub struct DirBuilder {
inner: sys::DirBuilder,
recursive: bool,
}
impl Default for DirBuilder {
fn default() -> Self {
Self::new()
}
}
impl DirBuilder {
pub fn new() -> Self {
Self {
inner: sys::DirBuilder::new(),
recursive: false,
}
}
pub fn recursive(&mut self, recursive: bool) -> &mut Self {
self.recursive = recursive;
self
}
pub async fn create(&self, path: impl AsRef<Path>) -> io::Result<()> {
let path = path.as_ref();
if self.recursive {
self.create_dir_all(path).await
} else {
self.inner.create(path).await
}
}
async fn create_dir_all(&self, path: &Path) -> io::Result<()> {
if path == Path::new("") {
return Ok(());
}
match self.inner.create(path).await {
Ok(()) => return Ok(()),
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
Err(_) if metadata(path).await.map(|m| m.is_dir()).unwrap_or_default() => return Ok(()),
Err(e) => return Err(e),
}
match path.parent() {
Some(p) => Box::pin(self.create_dir_all(p)).await?,
None => {
return Err(io::Error::new(
io::ErrorKind::Other,
"failed to create whole tree",
));
}
}
match self.inner.create(path).await {
Ok(()) => Ok(()),
Err(_) if metadata(path).await.map(|m| m.is_dir()).unwrap_or_default() => Ok(()),
Err(e) => Err(e),
}
}
}
#[cfg(unix)]
impl std::os::unix::fs::DirBuilderExt for DirBuilder {
fn mode(&mut self, mode: u32) -> &mut Self {
self.inner.mode(mode);
self
}
}