use std::path::{Path, PathBuf};
use compio::runtime::spawn_blocking;
use crate::{Error, Result};
async fn blocking<T: Send + 'static>(f: impl FnOnce() -> std::io::Result<T> + Send + 'static) -> Result<T> {
Ok(spawn_blocking(f).await.map_err(|_| Error::Join)??)
}
pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
let from = from.as_ref().to_path_buf();
let to = to.as_ref().to_path_buf();
blocking(move || std::fs::rename(from, to)).await
}
pub async fn remove(path: impl AsRef<Path>) -> Result<()> {
let path = path.as_ref().to_path_buf();
blocking(move || std::fs::remove_file(path)).await
}
pub async fn mkdir(path: impl AsRef<Path>) -> Result<()> {
let path = path.as_ref().to_path_buf();
blocking(move || std::fs::create_dir_all(path)).await
}
pub async fn ls(path: impl AsRef<Path>) -> Result<Vec<PathBuf>> {
let path = path.as_ref().to_path_buf();
blocking(move || {
let mut files = Vec::new();
for entry in std::fs::read_dir(path)? {
let entry = entry?;
if entry.file_type()?.is_file() {
files.push(entry.path());
}
}
Ok(files)
})
.await
}
#[inline]
pub fn exists(path: impl AsRef<Path>) -> bool {
path.as_ref().exists()
}
pub async fn size(path: impl AsRef<Path>) -> Result<u64> {
let path = path.as_ref().to_path_buf();
blocking(move || Ok(std::fs::metadata(path)?.len())).await
}
#[cfg(unix)]
pub async fn sync_dir(path: impl AsRef<Path>) -> Result<()> {
use std::os::unix::io::AsRawFd;
let path = path.as_ref().to_path_buf();
blocking(move || {
let dir = std::fs::File::open(&path)?;
if unsafe { libc::fsync(dir.as_raw_fd()) } == -1 {
return Err(std::io::Error::last_os_error());
}
Ok(())
})
.await
}
#[cfg(windows)]
pub async fn sync_dir(_path: impl AsRef<Path>) -> Result<()> {
Ok(())
}