use crate::PathBuf;
#[doc = crate::_tags!(fs namespace)]
#[must_use]
#[derive(Debug, Clone)]
pub struct FsPath {
pub path: PathBuf,
}
mod methods {
use crate::{
Cow, Env, FileMetadata, FilePermissions, FileType, Fs, FsPath, IoError, IoErrorKind,
IoResult, Path, PathBuf, PathDisplay, SystemTime,
};
#[rustfmt::skip]
impl FsPath {
pub fn new<P: AsRef<Path>>(path: P) -> Self { Self { path: path.as_ref().to_path_buf() } }
pub fn from_current_dir() -> IoResult<Self> { Ok(Self { path: Env::current_dir()? }) }
pub fn from_manifest_dir() -> Self {
Self {
path: PathBuf::from(Env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"))
}
}
pub fn from_manifest_path() -> Self {
Self {
path: PathBuf::from(Env::var("CARGO_MANIFEST_PATH").expect("CARGO_MANIFEST_PATH not set"))
}
}
pub fn from_temp_dir() -> Self { Self { path: Env::temp_dir() } }
#[cfg(not(miri))] pub fn from_crate_root<P: AsRef<Path>>(path: P) -> IoResult<Self> {
let current_path = Env::current_dir()?;
let mut root_path = current_path.clone();
for p in current_path.as_path().ancestors() {
let has_cargo = Fs::read_dir(p)?.any(|p| p.unwrap().file_name() == *"Cargo.toml");
if has_cargo {
return Ok(Self { path: root_path.join(path.as_ref()) });
}
root_path.pop();
}
Err(IoError::new(IoErrorKind::NotFound, "Ran out of places to find Cargo.toml"))
}
pub fn canonicalize(&self) -> IoResult<FsPath> {
self.path.canonicalize().map(|path| Self { path })
}
pub fn read_link(&self) -> IoResult<FsPath> {
self.path.read_link().map(|path| Self { path })
}
pub fn is_absolute(&self) -> bool { self.path.is_absolute() }
pub fn is_relative(&self) -> bool { self.path.is_relative() }
pub fn parent(&self) -> Option<FsPath> { self.path.parent().map(|o| o.into()) }
pub fn pop(&mut self) -> bool { self.path.pop() }
pub fn push<P: AsRef<Path>>(&mut self, path: P) { self.path.push(path); }
pub fn display(&self) -> PathDisplay<'_> { self.as_path().display() }
pub fn to_str(&self) -> Option<&str> { self.path.to_str() }
pub fn to_string_lossy(&self) -> Cow<'_, str> { self.path.to_string_lossy() }
pub fn into_inner(self) -> PathBuf { self.into() }
pub fn into_ref_mut(&mut self) -> &mut PathBuf { self.into() }
pub fn as_path(&self) -> &Path { self.into() }
}
#[rustfmt::skip]
impl FsPath {
pub fn exists(&self) -> bool { self.path.exists() }
pub fn is_file(&self) -> bool { self.path.is_file() }
pub fn is_dir(&self) -> bool { self.path.is_dir() }
pub fn is_symlink(&self) -> bool { self.metadata().is_ok_and(|m| m.is_symlink()) }
pub fn metadata(&self) -> IoResult<FileMetadata> { self.path.metadata() }
pub fn file_type(&self) -> IoResult<FileType> { Ok(self.metadata()?.file_type()) }
pub fn len(&self) -> IoResult<u64> { Ok(self.metadata()?.len()) }
pub fn is_empty(&self) -> IoResult<bool> { Ok(self.len()? == 0) }
pub fn created(&self) -> IoResult<SystemTime> { self.metadata()?.created() }
pub fn accessed(&self) -> IoResult<SystemTime> { self.metadata()?.accessed() }
pub fn modified(&self) -> IoResult<SystemTime> { self.metadata()?.modified() }
pub fn permissions(&self) -> IoResult<FilePermissions> {
Ok(self.metadata()?.permissions())
}
pub fn is_readonly(&self) -> IoResult<bool> { Ok(self.permissions()?.readonly()) }
pub fn set_readonly(&mut self, readonly: bool) -> IoResult<bool> {
let prev = self.is_readonly()?;
self.permissions()?.set_readonly(readonly);
Ok(prev)
}
}
impl FsPath {
pub fn exists_ts(&self, traverse: bool) -> bool {
self.metadata_ts(traverse).is_ok()
}
pub fn is_file_ts(&self, traverse: bool) -> bool {
self.metadata_ts(traverse).is_ok_and(|m| m.is_file())
}
pub fn is_dir_ts(&self, traverse: bool) -> bool {
self.metadata_ts(traverse).is_ok_and(|m| m.is_dir())
}
pub fn is_symlink_ts(&self, traverse: bool) -> bool {
self.metadata_ts(traverse).is_ok_and(|m| m.is_symlink())
}
pub fn metadata_ts(&self, traverse: bool) -> IoResult<FileMetadata> {
if traverse { self.path.metadata() } else { self.path.symlink_metadata() }
}
pub fn file_type_ts(&self, traverse: bool) -> IoResult<FileType> {
Ok(self.metadata_ts(traverse)?.file_type())
}
#[allow(clippy::len_without_is_empty)]
pub fn len_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.len())
}
pub fn is_empty_ts(&self, traverse: bool) -> IoResult<bool> {
Ok(self.len_ts(traverse)? == 0)
}
pub fn created_ts(&self, traverse: bool) -> IoResult<SystemTime> {
self.metadata_ts(traverse)?.created()
}
pub fn accessed_ts(&self, traverse: bool) -> IoResult<SystemTime> {
self.metadata_ts(traverse)?.accessed()
}
pub fn modified_ts(&self, traverse: bool) -> IoResult<SystemTime> {
self.metadata_ts(traverse)?.modified()
}
pub fn permissions_ts(&self, traverse: bool) -> IoResult<FilePermissions> {
Ok(self.metadata_ts(traverse)?.permissions())
}
pub fn is_readonly_ts(&self, traverse: bool) -> IoResult<bool> {
Ok(self.permissions_ts(traverse)?.readonly())
}
pub fn set_readonly_ts(&mut self, readonly: bool, traverse: bool) -> IoResult<bool> {
let prev = self.is_readonly_ts(traverse)?;
self.permissions_ts(traverse)?.set_readonly(readonly);
Ok(prev)
}
}
}
#[cfg(unix)]
mod unix {
use super::FsPath;
use crate::IoResult;
use std::os::unix::fs::MetadataExt;
#[rustfmt::skip]
impl FsPath {
pub fn dev(&self) -> IoResult<u64> { Ok(self.metadata()?.dev()) }
pub fn ino(&self) -> IoResult<u64> { Ok(self.metadata()?.ino()) }
pub fn mode(&self) -> IoResult<u32> { Ok(self.metadata()?.mode()) }
pub fn nlink(&self) -> IoResult<u64> { Ok(self.metadata()?.nlink()) }
pub fn uid(&self) -> IoResult<u32> { Ok(self.metadata()?.uid()) }
pub fn gid(&self) -> IoResult<u32> { Ok(self.metadata()?.gid()) }
pub fn rdev(&self) -> IoResult<u64> { Ok(self.metadata()?.rdev()) }
pub fn size(&self) -> IoResult<u64> { Ok(self.metadata()?.size()) }
pub fn atime(&self) -> IoResult<i64> { Ok(self.metadata()?.atime()) }
pub fn atime_nsec(&self) -> IoResult<i64> { Ok(self.metadata()?.atime_nsec()) }
pub fn mtime(&self) -> IoResult<i64> { Ok(self.metadata()?.mtime()) }
pub fn mtime_nsec(&self) -> IoResult<i64> { Ok(self.metadata()?.mtime_nsec()) }
pub fn ctime(&self) -> IoResult<i64> { Ok(self.metadata()?.ctime()) }
pub fn ctime_nsec(&self) -> IoResult<i64> { Ok(self.metadata()?.ctime_nsec()) }
pub fn blksize(&self) -> IoResult<u64> { Ok(self.metadata()?.blksize()) }
pub fn blocks(&self) -> IoResult<u64> { Ok(self.metadata()?.blocks()) }
}
impl FsPath {
pub fn dev_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.dev())
}
pub fn ino_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.ino())
}
pub fn mode_ts(&self, traverse: bool) -> IoResult<u32> {
Ok(self.metadata_ts(traverse)?.mode())
}
pub fn nlink_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.nlink())
}
pub fn uid_ts(&self, traverse: bool) -> IoResult<u32> {
Ok(self.metadata_ts(traverse)?.uid())
}
pub fn gid_ts(&self, traverse: bool) -> IoResult<u32> {
Ok(self.metadata_ts(traverse)?.gid())
}
pub fn rdev_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.rdev())
}
pub fn size_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.size())
}
pub fn atime_ts(&self, traverse: bool) -> IoResult<i64> {
Ok(self.metadata_ts(traverse)?.atime())
}
pub fn atime_nsec_ts(&self, traverse: bool) -> IoResult<i64> {
Ok(self.metadata_ts(traverse)?.atime_nsec())
}
pub fn mtime_ts(&self, traverse: bool) -> IoResult<i64> {
Ok(self.metadata_ts(traverse)?.mtime())
}
pub fn mtime_nsec_ts(&self, traverse: bool) -> IoResult<i64> {
Ok(self.metadata_ts(traverse)?.mtime_nsec())
}
pub fn ctime_ts(&self, traverse: bool) -> IoResult<i64> {
Ok(self.metadata_ts(traverse)?.ctime())
}
pub fn ctime_nsec_ts(&self, traverse: bool) -> IoResult<i64> {
Ok(self.metadata_ts(traverse)?.ctime_nsec())
}
pub fn blksize_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.blksize())
}
pub fn blocks_ts(&self, traverse: bool) -> IoResult<u64> {
Ok(self.metadata_ts(traverse)?.blocks())
}
}
}
#[cfg(any(windows, doc))]
#[rustfmt::skip]
mod windows {
use super::FsPath;
use crate::IoResult;
#[cfg(windows)]
use std::os::windows::fs::MetadataExt;
#[cfg(not(windows))]
crate::items! {
#[allow(missing_docs, dead_code)]
trait MetadataExt {
fn file_attributes(&self) -> u32 {0}
fn creation_time(&self) -> u64 {0}
fn last_access_time(&self) -> u64 {0}
fn last_write_time(&self) -> u64 {0}
fn file_size(&self) -> u64 {0}
fn volume_serial_number(&self) -> Option<u32> {None}
fn number_of_links(&self) -> Option<u32> {None}
fn file_index(&self) -> Option<u64> {None}
fn change_time(&self) -> Option<u64> {None}
}
impl MetadataExt for crate::FileMetadata {}
}
impl FsPath {
pub fn file_attributes(&self) -> IoResult<u32> { Ok(self.metadata()?.file_attributes()) }
pub fn creation_time(&self) -> IoResult<u64> { Ok(self.metadata()?.creation_time()) }
pub fn last_access_time(&self) -> IoResult<u64> { Ok(self.metadata()?.last_access_time()) }
pub fn last_write_time(&self) -> IoResult<u64> { Ok(self.metadata()?.last_write_time()) }
pub fn file_size(&self) -> IoResult<u64> { Ok(self.metadata()?.file_size()) }
}
}
#[rustfmt::skip]
mod std_impls {
use super::{FsPath, PathBuf};
use crate::Path;
impl From<PathBuf> for FsPath { fn from(path: PathBuf) -> Self { Self { path } } }
impl From<&PathBuf> for FsPath { fn from(path: &PathBuf) -> Self { Self::new(path) } }
impl From<&mut PathBuf> for FsPath { fn from(path: &mut PathBuf) -> Self { Self::new(path) } }
impl From<FsPath> for PathBuf { fn from(fspath: FsPath) -> Self { fspath.path } }
impl From<&FsPath> for PathBuf { fn from(fspath: &FsPath) -> Self { fspath.path.clone() } }
impl From<&mut FsPath> for PathBuf { fn from(fspath: &mut FsPath)
-> Self { fspath.path.clone() } }
impl<'a> From<&'a FsPath> for &'a PathBuf { fn from(fspath: &'a FsPath)
-> Self { &fspath.path } }
impl<'a> From<&'a mut FsPath> for &'a mut PathBuf { fn from(fspath: &'a mut FsPath)
-> Self { &mut fspath.path } }
impl From<&Path> for FsPath { fn from(path: &Path) -> Self { Self::new(path) } }
impl From<&mut Path> for FsPath { fn from(path: &mut Path) -> Self { Self::new(path) } }
impl<'a> From<&'a FsPath> for &'a Path { fn from(fspath: &'a FsPath)
-> Self { fspath.path.as_path() } }
impl<'a> From<&'a mut FsPath> for &'a Path { fn from(fspath: &'a mut FsPath)
-> Self { fspath.path.as_path() } }
}