include_dir/
dir.rs
1use crate::{file::File, DirEntry};
2use std::fs;
3use std::path::Path;
4
5#[derive(Debug, Clone, PartialEq)]
7pub struct Dir<'a> {
8 path: &'a str,
9 entries: &'a [DirEntry<'a>],
10}
11
12impl<'a> Dir<'a> {
13 pub const fn new(path: &'a str, entries: &'a [DirEntry<'a>]) -> Self {
15 Dir { path, entries }
16 }
17
18 pub fn path(&self) -> &'a Path {
21 Path::new(self.path)
22 }
23
24 pub const fn entries(&self) -> &'a [DirEntry<'a>] {
26 self.entries
27 }
28
29 pub fn files(&self) -> impl Iterator<Item = &'a File<'a>> + 'a {
31 self.entries().iter().filter_map(DirEntry::as_file)
32 }
33
34 pub fn dirs(&self) -> impl Iterator<Item = &'a Dir<'a>> + 'a {
36 self.entries().iter().filter_map(DirEntry::as_dir)
37 }
38
39 pub fn get_entry<S: AsRef<Path>>(&self, path: S) -> Option<&'a DirEntry<'a>> {
41 let path = path.as_ref();
42
43 for entry in self.entries() {
44 if entry.path() == path {
45 return Some(entry);
46 }
47
48 if let DirEntry::Dir(d) = entry {
49 if let Some(nested) = d.get_entry(path) {
50 return Some(nested);
51 }
52 }
53 }
54
55 None
56 }
57
58 pub fn get_file<S: AsRef<Path>>(&self, path: S) -> Option<&'a File<'a>> {
60 self.get_entry(path).and_then(DirEntry::as_file)
61 }
62
63 pub fn get_dir<S: AsRef<Path>>(&self, path: S) -> Option<&'a Dir<'a>> {
65 self.get_entry(path).and_then(DirEntry::as_dir)
66 }
67
68 pub fn contains<S: AsRef<Path>>(&self, path: S) -> bool {
70 self.get_entry(path).is_some()
71 }
72
73 pub fn extract<S: AsRef<Path>>(&self, base_path: S) -> std::io::Result<()> {
78 let base_path = base_path.as_ref();
79
80 for entry in self.entries() {
81 let path = base_path.join(entry.path());
82
83 match entry {
84 DirEntry::Dir(d) => {
85 fs::create_dir_all(&path)?;
86 d.extract(base_path)?;
87 }
88 DirEntry::File(f) => {
89 fs::write(path, f.contents())?;
90 }
91 }
92 }
93
94 Ok(())
95 }
96}