use std::fs;
use std::fmt;
use std::io;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::ops::Deref;
use std::convert::AsRef;
use super::PathAbs;
#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct PathFile(pub(crate) PathAbs);
impl PathFile {
pub fn new<P: AsRef<Path>>(path: P) -> io::Result<PathFile> {
let abs = PathAbs::new(path)?;
PathFile::from_abs(abs)
}
pub fn from_abs(abs: PathAbs) -> io::Result<PathFile> {
if abs.is_file() {
Ok(PathFile(abs))
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"path is not a file",
))
}
}
pub fn create<P: AsRef<Path>>(path: P) -> io::Result<PathFile> {
fs::OpenOptions::new().write(true).create(true).open(&path)?;
PathFile::new(path)
}
pub fn read_string(&self) -> io::Result<String> {
let mut f = fs::OpenOptions::new().read(true).open(self)?;
let mut out = String::with_capacity(f.metadata()?.len() as usize);
f.read_to_string(&mut out)?;
Ok(out)
}
pub fn write_str(&self, s: &str) -> io::Result<()> {
let mut f = fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(self)?;
if s.is_empty() {
return Ok(());
}
f.write_all(s.as_bytes())?;
f.flush()
}
pub fn append_str(&self, s: &str) -> io::Result<()> {
let mut f = fs::OpenOptions::new().append(true).create(true).open(self)?;
if s.is_empty() {
return Ok(());
}
f.write_all(s.as_bytes())?;
f.flush()
}
pub fn mock<P: AsRef<Path>>(path: P) -> PathFile {
PathFile(PathAbs::mock(path))
}
}
impl fmt::Debug for PathFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl AsRef<PathAbs> for PathFile {
fn as_ref(&self) -> &PathAbs {
&self.0
}
}
impl AsRef<Path> for PathFile {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}
impl AsRef<PathBuf> for PathFile {
fn as_ref(&self) -> &PathBuf {
self.0.as_ref()
}
}
impl Deref for PathFile {
type Target = PathAbs;
fn deref(&self) -> &PathAbs {
&self.0
}
}