use std::fs;
use std::fmt;
use std::io;
use std::path::{Path, PathBuf};
use std::ops::Deref;
use std::convert::AsRef;
use super::{PathAbs, PathType};
#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct PathDir(pub(crate) PathAbs);
impl PathDir {
pub fn new<P: AsRef<Path>>(path: P) -> io::Result<PathDir> {
let abs = PathAbs::new(path)?;
PathDir::from_abs(abs)
}
pub fn from_abs(abs: PathAbs) -> io::Result<PathDir> {
if abs.is_dir() {
Ok(PathDir(abs))
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"path is not a dir",
))
}
}
pub fn create<P: AsRef<Path>>(path: P) -> io::Result<PathDir> {
if let Err(err) = fs::create_dir(&path) {
match err.kind() {
io::ErrorKind::AlreadyExists => {}
_ => return Err(err),
}
}
PathDir::new(path)
}
pub fn create_all<P: AsRef<Path>>(path: P) -> io::Result<PathDir> {
fs::create_dir_all(&path)?;
PathDir::new(path)
}
pub fn join_abs<P: AsRef<Path>>(&self, path: P) -> io::Result<PathType> {
let joined = self.join(path.as_ref());
PathType::new(joined)
}
pub fn list(&self) -> io::Result<ListDir> {
Ok(ListDir {
fsread: fs::read_dir(self)?,
})
}
pub fn mock<P: AsRef<Path>>(path: P) -> PathDir {
PathDir(PathAbs::mock(path))
}
}
pub struct ListDir {
fsread: fs::ReadDir,
}
impl ::std::iter::Iterator for ListDir {
type Item = io::Result<PathType>;
fn next(&mut self) -> Option<io::Result<PathType>> {
let entry = match self.fsread.next() {
Some(r) => match r {
Ok(e) => e,
Err(err) => return Some(Err(err)),
},
None => return None,
};
Some(PathType::new(entry.path()))
}
}
impl fmt::Debug for PathDir {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl AsRef<PathAbs> for PathDir {
fn as_ref(&self) -> &PathAbs {
&self.0
}
}
impl AsRef<Path> for PathDir {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}
impl AsRef<PathBuf> for PathDir {
fn as_ref(&self) -> &PathBuf {
self.0.as_ref()
}
}
impl Deref for PathDir {
type Target = PathAbs;
fn deref(&self) -> &PathAbs {
&self.0
}
}
#[cfg(test)]
mod tests {
use tempdir::TempDir;
use std::collections::HashSet;
use super::super::{PathDir, PathFile, PathType};
#[test]
fn sanity_list() {
let tmp_dir = TempDir::new("example").expect("create temp dir");
let tmp_abs = PathDir::new(tmp_dir.path()).unwrap();
let foo_dir = PathDir::create(tmp_abs.join("foo")).unwrap();
let bar_file = PathFile::create(tmp_abs.join("bar.txt")).unwrap();
let mut result = HashSet::new();
for p in tmp_abs.list().unwrap() {
result.insert(p.unwrap());
}
let mut expected = HashSet::new();
expected.insert(PathType::Dir(foo_dir));
expected.insert(PathType::File(bar_file));
assert_eq!(expected, result);
}
}