use crate::{validate_spath_for_option, validate_spath_for_result, SPath};
use crate::{Error, Result};
use core::fmt;
use std::fs;
use std::path::{Path, PathBuf};
#[derive(Debug)]
pub struct SFile {
path: PathBuf,
}
impl AsRef<Path> for SFile {
fn as_ref(&self) -> &Path {
self.path.as_ref()
}
}
impl fmt::Display for SFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_str())
}
}
impl From<SFile> for String {
fn from(val: SFile) -> Self {
val.to_str().to_string()
}
}
impl From<&SFile> for String {
fn from(val: &SFile) -> Self {
val.to_str().to_string()
}
}
impl SFile {
pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref();
validate_sfile_for_result(path)?;
Ok(Self {
path: path.to_path_buf(),
})
}
pub fn from_path_ok(path: impl AsRef<Path>) -> Option<Self> {
let path = path.as_ref();
validate_sfile_for_option(path)?;
Some(Self {
path: path.to_path_buf(),
})
}
pub fn from_path_buf_ok(path_buf: PathBuf) -> Option<Self> {
validate_sfile_for_option(&path_buf)?;
Some(Self { path: path_buf })
}
pub fn from_fs_entry_ok(fs_entry: fs::DirEntry) -> Option<Self> {
let path_buf = fs_entry.path();
validate_sfile_for_option(&path_buf)?;
Some(Self { path: path_buf })
}
pub fn from_walkdir_entry_ok(wd_entry: walkdir::DirEntry) -> Option<Self> {
let path = wd_entry.path();
validate_sfile_for_option(path)?;
Some(Self {
path: wd_entry.into_path(),
})
}
}
impl TryFrom<&str> for SFile {
type Error = Error;
fn try_from(path: &str) -> Result<SFile> {
let path = Path::new(path);
validate_sfile_for_result(path)?;
Ok(Self {
path: path.to_path_buf(),
})
}
}
impl TryFrom<String> for SFile {
type Error = Error;
fn try_from(path: String) -> Result<SFile> {
SFile::try_from(path.as_str())
}
}
impl TryFrom<&String> for SFile {
type Error = Error;
fn try_from(path: &String) -> Result<SFile> {
SFile::try_from(path.as_str())
}
}
impl TryFrom<PathBuf> for SFile {
type Error = Error;
fn try_from(path_buf: PathBuf) -> Result<SFile> {
validate_sfile_for_result(&path_buf)?;
Ok(Self { path: path_buf })
}
}
impl TryFrom<fs::DirEntry> for SFile {
type Error = Error;
fn try_from(fs_entry: fs::DirEntry) -> Result<SFile> {
let path_buf = fs_entry.path();
validate_sfile_for_result(&path_buf)?;
Ok(Self { path: path_buf })
}
}
impl TryFrom<walkdir::DirEntry> for SFile {
type Error = Error;
fn try_from(wd_entry: walkdir::DirEntry) -> Result<SFile> {
let path = wd_entry.path();
validate_sfile_for_result(path)?;
Ok(Self {
path: wd_entry.into_path(),
})
}
}
impl TryFrom<SPath> for SFile {
type Error = Error;
fn try_from(spath: SPath) -> Result<SFile> {
let path = spath.path();
validate_sfile_for_result(path)?;
Ok(Self {
path: spath.into_path_buf(),
})
}
}
fn validate_sfile_for_result(path: &Path) -> Result<()> {
validate_spath_for_result(path)?;
if path.is_file() {
Ok(())
} else {
Err(Error::FileNotFound(path.to_string_lossy().to_string()))
}
}
fn validate_sfile_for_option(path: &Path) -> Option<()> {
validate_spath_for_option(path)?;
if path.is_file() {
Some(())
} else {
None
}
}
impl SFile {
pub fn into_path_buf(self) -> PathBuf {
self.path
}
pub fn path(&self) -> &Path {
&self.path
}
}
impl SFile {
pub fn to_str(&self) -> &str {
self.path.to_str().unwrap_or_default()
}
pub fn file_name(&self) -> &str {
self.path.file_name().and_then(|n| n.to_str()).unwrap_or_default()
}
pub fn stem(&self) -> &str {
self.path.file_stem().and_then(|n| n.to_str()).unwrap_or_default()
}
pub fn extension(&self) -> Option<&str> {
self.path.extension().and_then(|os_str| os_str.to_str())
}
}