use crate::{file::File, DirEntry};
use std::fs;
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Dir {
path: &'static str,
entries: &'static [DirEntry],
}
impl Dir {
pub const fn new(path: &'static str, entries: &'static [DirEntry]) -> Self {
Dir { path, entries }
}
pub fn path(&self) -> &'static Path {
Path::new(self.path)
}
pub const fn entries(&self) -> &'static [DirEntry] {
self.entries
}
pub fn files(&self) -> impl Iterator<Item = &'static File> + 'static {
self.entries().iter().filter_map(DirEntry::as_file)
}
pub fn dirs(&self) -> impl Iterator<Item = &'static Dir> + 'static {
self.entries().iter().filter_map(DirEntry::as_dir)
}
pub fn get_entry<S: AsRef<Path>>(&self, path: S) -> Option<&'static DirEntry> {
let path = path.as_ref();
for entry in self.entries() {
if entry.path() == path {
return Some(entry);
}
if let DirEntry::Dir(d) = entry {
if let Some(nested) = d.get_entry(path) {
return Some(nested);
}
}
}
None
}
pub fn get_file<S: AsRef<Path>>(&self, path: S) -> Option<&'static File> {
self.get_entry(path).and_then(DirEntry::as_file)
}
pub fn get_dir<S: AsRef<Path>>(&self, path: S) -> Option<&'static Dir> {
self.get_entry(path).and_then(DirEntry::as_dir)
}
pub fn contains<S: AsRef<Path>>(&self, path: S) -> bool {
self.get_entry(path).is_some()
}
pub fn extract<S: AsRef<Path>>(&self, base_path: S) -> std::io::Result<()> {
let base_path = base_path.as_ref();
for entry in self.entries() {
let path = base_path.join(entry.path());
match entry {
DirEntry::Dir(d) => {
fs::create_dir_all(&path)?;
d.extract(base_path)?;
}
DirEntry::File(f) => {
fs::write(path, f.contents())?;
}
}
}
Ok(())
}
}