Skip to main content

pawkit_fs/
list_files.rs

1use std::{
2    fs::ReadDir,
3    sync::{Arc, Mutex},
4};
5
6use zip::ZipArchive;
7
8use crate::{VfsError, buffer::VfsBuffer};
9
10pub enum VfsListFiles {
11    Working(ReadDir),
12    ZipArchive {
13        index: usize,
14        prefix: Box<str>,
15        zip: Arc<Mutex<ZipArchive<VfsBuffer>>>,
16    },
17}
18
19impl VfsListFiles {
20    fn next_working(iter: &mut ReadDir) -> Option<<Self as Iterator>::Item> {
21        let mut name = None;
22        while name.is_none() {
23            match iter.next()?.map_err(Into::into) {
24                Ok(dir) => match dir.file_type().map_err(Into::into) {
25                    Ok(it) => {
26                        if it.is_file() {
27                            name = dir.file_name().to_str().map(Into::into);
28                        }
29                    }
30                    Err(err) => return Some(Err(err)),
31                },
32
33                Err(err) => {
34                    return Some(Err(err));
35                }
36            }
37        }
38
39        return Some(Ok(name?));
40    }
41
42    fn next_zip(
43        index: &mut usize,
44        prefix: &Box<str>,
45        zip: &Arc<Mutex<ZipArchive<VfsBuffer>>>,
46    ) -> Option<<Self as Iterator>::Item> {
47        let Ok(mut zip) = zip.lock() else {
48            return Some(Err(VfsError::Other));
49        };
50
51        while *index < zip.len() {
52            let file = match zip.by_index(*index).map_err(Into::into) {
53                Ok(file) => file,
54                Err(err) => return Some(Err(err)),
55            };
56            *index += 1;
57
58            let name = file.name();
59            let prefix: &str = &prefix;
60            if name.starts_with(prefix) {
61                let remaining = &name[prefix.len()..];
62
63                if !remaining.contains('/') && file.is_file() {
64                    return Some(Ok(remaining.to_string()));
65                }
66            }
67        }
68
69        return None;
70    }
71}
72
73impl Iterator for VfsListFiles {
74    type Item = Result<String, VfsError>;
75
76    fn next(&mut self) -> Option<Self::Item> {
77        match self {
78            Self::Working(iter) => Self::next_working(iter),
79
80            Self::ZipArchive { index, prefix, zip } => Self::next_zip(index, prefix, zip),
81        }
82    }
83}