#[cfg(feature = "sync")]
pub mod sync {
use std::path::Path;
use crate::sync::OpenOptions;
pub struct File(std::fs::File);
impl File {
pub fn open(path: impl AsRef<Path>) -> std::io::Result<Self> {
Ok(Self(std::fs::File::open(path)?))
}
pub fn create(path: impl AsRef<Path>) -> std::io::Result<Self> {
Ok(Self(std::fs::File::create(path)?))
}
#[must_use]
pub const fn options() -> OpenOptions {
OpenOptions::new()
}
pub fn metadata(&self) -> std::io::Result<Metadata> {
Ok(Metadata(self.0.metadata()?))
}
#[must_use]
pub const fn inner(&self) -> &std::fs::File {
&self.0
}
#[must_use]
pub fn into_inner(self) -> std::fs::File {
self.0
}
}
impl From<std::fs::File> for File {
fn from(file: std::fs::File) -> Self {
Self(file)
}
}
impl From<File> for std::fs::File {
fn from(file: File) -> Self {
file.0
}
}
impl std::io::Read for File {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.0.read(buf)
}
}
impl std::io::Write for File {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.0.flush()
}
}
impl std::io::Seek for File {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
self.0.seek(pos)
}
}
#[derive(Debug, Clone)]
pub struct Metadata(std::fs::Metadata);
impl Metadata {
#[must_use]
pub fn len(&self) -> u64 {
self.0.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn is_file(&self) -> bool {
self.0.is_file()
}
#[must_use]
pub fn is_dir(&self) -> bool {
self.0.is_dir()
}
#[must_use]
pub fn is_symlink(&self) -> bool {
self.0.is_symlink()
}
#[must_use]
pub const fn inner(&self) -> &std::fs::Metadata {
&self.0
}
}
impl From<std::fs::Metadata> for Metadata {
fn from(metadata: std::fs::Metadata) -> Self {
Self(metadata)
}
}
pub fn read<P: AsRef<Path>>(path: P) -> std::io::Result<Vec<u8>> {
::std::fs::read(path)
}
pub fn read_to_string<P: AsRef<Path>>(path: P) -> std::io::Result<String> {
::std::fs::read_to_string(path)
}
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> std::io::Result<()> {
::std::fs::write(path, contents)
}
pub fn create_dir<P: AsRef<Path>>(path: P) -> std::io::Result<()> {
::std::fs::create_dir(path)
}
pub fn create_dir_all<P: AsRef<Path>>(path: P) -> std::io::Result<()> {
::std::fs::create_dir_all(path)
}
pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> std::io::Result<()> {
::std::fs::remove_dir_all(path)
}
pub fn canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<std::path::PathBuf> {
::std::fs::canonicalize(path)
}
pub fn read_dir_sorted<P: AsRef<Path>>(path: P) -> std::io::Result<Vec<std::fs::DirEntry>> {
let mut entries: Vec<_> = ::std::fs::read_dir(path)?.collect::<Result<Vec<_>, _>>()?;
entries.sort_by_key(std::fs::DirEntry::file_name);
Ok(entries)
}
pub fn walk_dir_sorted<P: AsRef<Path>>(path: P) -> std::io::Result<Vec<std::fs::DirEntry>> {
fn walk_recursive(
path: &Path,
entries: &mut Vec<std::fs::DirEntry>,
) -> std::io::Result<()> {
let mut dir_entries: Vec<_> =
::std::fs::read_dir(path)?.collect::<Result<Vec<_>, _>>()?;
dir_entries.sort_by_key(std::fs::DirEntry::file_name);
for entry in dir_entries {
let path = entry.path();
entries.push(entry);
if path.is_dir() {
walk_recursive(&path, entries)?;
}
}
Ok(())
}
let mut all_entries = Vec::new();
walk_recursive(path.as_ref(), &mut all_entries)?;
all_entries.sort_by_key(std::fs::DirEntry::path);
Ok(all_entries)
}
impl From<OpenOptions> for std::fs::OpenOptions {
fn from(value: OpenOptions) -> Self {
let mut options = Self::new();
options
.create(value.create)
.append(value.append)
.read(value.read)
.write(value.write)
.truncate(value.truncate);
options
}
}
#[cfg(not(feature = "simulator"))]
impl OpenOptions {
pub fn open(self, path: impl AsRef<::std::path::Path>) -> ::std::io::Result<File> {
let options: std::fs::OpenOptions = self.into();
Ok(File(options.open(path)?))
}
}
}
#[must_use]
pub fn exists<P: AsRef<std::path::Path>>(path: P) -> bool {
path.as_ref().exists()
}
#[cfg(feature = "std")]
pub mod temp_dir {
use std::{
ffi::OsStr,
path::{Path, PathBuf},
};
pub struct TempDir {
inner: Option<tempfile::TempDir>,
path: PathBuf,
}
impl TempDir {
pub fn new() -> std::io::Result<Self> {
let td = tempfile::TempDir::new()?;
let path = td.path().to_path_buf();
Ok(Self {
inner: Some(td),
path,
})
}
pub fn new_in<P: AsRef<Path>>(dir: P) -> std::io::Result<Self> {
let td = tempfile::TempDir::new_in(dir)?;
let path = td.path().to_path_buf();
Ok(Self {
inner: Some(td),
path,
})
}
pub fn with_prefix<S: AsRef<OsStr>>(prefix: S) -> std::io::Result<Self> {
let td = tempfile::TempDir::with_prefix(prefix)?;
let path = td.path().to_path_buf();
Ok(Self {
inner: Some(td),
path,
})
}
pub fn with_suffix<S: AsRef<OsStr>>(suffix: S) -> std::io::Result<Self> {
let td = tempfile::TempDir::with_suffix(suffix)?;
let path = td.path().to_path_buf();
Ok(Self {
inner: Some(td),
path,
})
}
pub fn with_prefix_in<S: AsRef<OsStr>, P: AsRef<Path>>(
prefix: S,
dir: P,
) -> std::io::Result<Self> {
let td = tempfile::TempDir::with_prefix_in(prefix, dir)?;
let path = td.path().to_path_buf();
Ok(Self {
inner: Some(td),
path,
})
}
pub fn with_suffix_in<S: AsRef<OsStr>, P: AsRef<Path>>(
suffix: S,
dir: P,
) -> std::io::Result<Self> {
let td = tempfile::TempDir::with_suffix_in(suffix, dir)?;
let path = td.path().to_path_buf();
Ok(Self {
inner: Some(td),
path,
})
}
#[must_use]
pub fn path(&self) -> &Path {
&self.path
}
#[must_use]
pub fn keep(mut self) -> PathBuf {
if let Some(td) = self.inner.take() {
td.keep()
} else {
self.path.clone()
}
}
#[deprecated = "use TempDir::keep()"]
#[must_use]
pub fn into_path(self) -> PathBuf {
self.keep()
}
pub fn disable_cleanup(&mut self, disable_cleanup: bool) {
if let Some(ref mut td) = self.inner {
td.disable_cleanup(disable_cleanup);
}
}
pub fn close(self) -> std::io::Result<()> {
self.inner.map_or(Ok(()), tempfile::TempDir::close)
}
}
impl AsRef<Path> for TempDir {
fn as_ref(&self) -> &Path {
self.path()
}
}
impl std::fmt::Debug for TempDir {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TempDir")
.field("path", &self.path)
.finish_non_exhaustive()
}
}
pub use tempfile::Builder;
pub fn tempdir() -> std::io::Result<TempDir> {
TempDir::new()
}
pub fn tempdir_in<P: AsRef<Path>>(dir: P) -> std::io::Result<TempDir> {
TempDir::new_in(dir)
}
}