use crate::FileSize;
use std::fs::Metadata;
use std::io;
use std::path::Path;
use std::rc::Rc;
#[derive(Debug)]
pub struct PathInfo {
path: Rc<Path>,
contents: FileContents,
metadata: Metadata,
}
#[derive(Debug)]
pub struct FileContents {
contents: Option<Rc<[u8]>>,
}
impl PathInfo {
pub fn new<P: AsRef<Path> + ?Sized>(path: &P) -> io::Result<Self> {
let path = Rc::from(path.as_ref().to_owned());
let metadata = std::fs::metadata(&path)?;
Ok(Self { path, metadata, contents: FileContents { contents: None } })
}
pub fn path(&self) -> &Rc<Path> {
&self.path
}
pub fn metadata(&self) -> &Metadata {
&self.metadata
}
pub fn is_dir(&self) -> bool {
self.metadata.is_dir()
}
pub fn is_file(&self) -> bool {
self.metadata.is_file()
}
pub fn contents(&mut self) -> io::Result<Rc<[u8]>> {
if self.contents.contents.is_none() {
self.contents.contents = Some(std::fs::read(self.path())?.into());
}
Ok(self.contents.contents.clone().unwrap())
}
pub fn content_size(&self) -> FileSize {
FileSize::from_bytes(self.metadata.len())
}
pub fn contents_contains(&mut self, slice: &[u8]) -> io::Result<bool> {
Ok(crate::slice_contains(&self.contents()?, slice))
}
}