mc_repack_core/entry/
fs.rs1use std::{fs, io, path::Path};
2use super::{EntryReader, EntrySaver, ReadEntry, SavingEntry};
3
4type FSEntry = io::Result<(Option<bool>, Box<Path>)>;
5
6pub struct FSEntryReader<I: ExactSizeIterator<Item = FSEntry>> {
8 src_dir: Box<Path>,
9 iter: I
10}
11impl FSEntryReader<std::vec::IntoIter<FSEntry>> {
12 pub fn new(src_dir: Box<Path>) -> Self {
14 let files = walkdir::WalkDir::new(src_dir.clone()).into_iter().map(check_dir_entry).collect::<Vec<_>>();
15 Self::from_vec(src_dir, files)
16 }
17 pub fn from_vec(src_dir: Box<Path>, files: Vec<FSEntry>) -> Self {
19 Self { src_dir, iter: files.into_iter() }
20 }
21}
22impl <I: ExactSizeIterator<Item = FSEntry>> FSEntryReader<I> {
23 pub fn custom(src_dir: Box<Path>, iter: I) -> Self {
25 Self { src_dir, iter }
26 }
27}
28impl <I: ExactSizeIterator<Item = FSEntry>> EntryReader for FSEntryReader<I> {
29 type RE<'a> = ReadFileEntry<'a> where Self: 'a;
30 #[inline]
31 fn read_len(&self) -> usize {
32 self.iter.len()
33 }
34 #[inline]
35 fn read_next(&mut self) -> Option<Self::RE<'_>> {
36 self.iter.next().map(|cur| ReadFileEntry { src_dir: &self.src_dir, cur })
37 }
38}
39
40pub struct ReadFileEntry<'a> {
42 src_dir: &'a Path,
43 cur: FSEntry
44}
45impl ReadEntry for ReadFileEntry<'_> {
46 fn meta(&self) -> (Option<bool>, Box<str>) {
47 let Ok((is_dir, p)) = &self.cur else { return (None, "".into()) };
48 let lname = if let Ok(p) = p.strip_prefix(self.src_dir) {
49 p.to_string_lossy().to_string()
50 } else {
51 return (None, "".into())
52 };
53 (*is_dir, lname.into_boxed_str())
54 }
55 fn data(self) -> crate::Result_<bytes::Bytes> {
56 match self.cur {
57 Ok((_, p)) => Ok(fs::read(&p)?.into()),
58 Err(e) => Err(e.into()),
59 }
60 }
61}
62
63pub struct FSEntrySaver {
65 dest_dir: Box<Path>
66}
67impl FSEntrySaver {
68 pub const fn new(dest_dir: Box<Path>) -> Self {
70 Self { dest_dir }
71 }
72}
73impl EntrySaver for FSEntrySaver {
74 fn save(&mut self, name: &str, entry: SavingEntry) -> crate::Result_<()> {
75 let mut np = self.dest_dir.to_path_buf();
76 np.push(name);
77 match entry {
78 SavingEntry::Directory => fs::create_dir(np),
79 SavingEntry::File(buf, _) => fs::write(np, buf),
80 }?;
81 Ok(())
82 }
83}
84
85fn check_dir_entry(de: walkdir::Result<walkdir::DirEntry>) -> FSEntry {
86 match de {
87 Err(e) => Err(e.into()),
88 Ok(de) => {
89 let ft = de.file_type();
90 let p = de.into_path().into_boxed_path();
91 Ok((if ft.is_dir() {
92 Some(true)
93 } else if ft.is_file() {
94 Some(false)
95 } else {
96 None
97 }, p))
98 }
99 }
100}