trillium_include_dir/
globs.rs1use crate::dir::Dir;
2use crate::file::File;
3use glob::{Pattern, PatternError};
4use std::path::Path;
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct Globs<'a> {
8 stack: Vec<DirEntry<'a>>,
9 pattern: Pattern,
10}
11
12impl<'a> Dir<'a> {
13 pub fn find(&self, glob: &str) -> Result<impl Iterator<Item = DirEntry<'a>>, PatternError> {
15 let pattern = Pattern::new(glob)?;
16
17 Ok(Globs::new(pattern, *self))
18 }
19
20 pub(crate) fn dir_entries(&self) -> impl Iterator<Item = DirEntry<'a>> {
21 let files = self.files().iter().map(|f| DirEntry::File(*f));
22 let dirs = self.dirs().iter().map(|d| DirEntry::Dir(*d));
23
24 files.chain(dirs)
25 }
26}
27
28impl<'a> Globs<'a> {
29 pub(crate) fn new(pattern: Pattern, root: Dir<'a>) -> Globs<'a> {
30 let stack = vec![DirEntry::Dir(root)];
31 Globs { stack, pattern }
32 }
33
34 fn fill_buffer(&mut self, item: &DirEntry<'a>) {
35 if let DirEntry::Dir(ref dir) = *item {
36 self.stack.extend(dir.dir_entries());
37 }
38 }
39}
40
41impl<'a> Iterator for Globs<'a> {
42 type Item = DirEntry<'a>;
43
44 fn next(&mut self) -> Option<Self::Item> {
45 while let Some(item) = self.stack.pop() {
46 self.fill_buffer(&item);
47
48 if self.pattern.matches_path(item.path()) {
49 return Some(item);
50 }
51 }
52
53 None
54 }
55}
56
57#[derive(Debug, Copy, Clone, PartialEq)]
59pub enum DirEntry<'a> {
60 File(File<'a>),
62 Dir(Dir<'a>),
64}
65
66impl<'a> DirEntry<'a> {
67 pub fn path(&self) -> &'a Path {
69 match *self {
70 DirEntry::File(f) => f.path(),
71 DirEntry::Dir(d) => d.path(),
72 }
73 }
74}