freedesktop_desktop_entry/
iter.rs1use std::{collections::VecDeque, fs, path::PathBuf};
5
6use crate::DesktopEntry;
7
8pub struct Iter {
9 directories_to_walk: VecDeque<PathBuf>,
10 actively_walking: Option<fs::ReadDir>,
11}
12
13impl Iter {
14 pub fn new<I: Iterator<Item = PathBuf>>(directories_to_walk: I) -> Self {
16 Self {
17 directories_to_walk: directories_to_walk.collect(),
18 actively_walking: None,
19 }
20 }
21}
22
23impl Iterator for Iter {
24 type Item = PathBuf;
25
26 fn next(&mut self) -> Option<Self::Item> {
27 'outer: loop {
28 let mut iterator = match self.actively_walking.take() {
29 Some(dir) => dir,
30 None => {
31 while let Some(path) = self.directories_to_walk.pop_front() {
32 match fs::read_dir(&path) {
33 Ok(directory) => {
34 self.actively_walking = Some(directory);
35 continue 'outer;
36 }
37
38 Err(_) => continue,
40 }
41 }
42
43 return None;
44 }
45 };
46
47 'inner: while let Some(entry) = iterator.next() {
48 if let Ok(entry) = entry {
49 let mut path = entry.path();
50
51 path = match path.canonicalize() {
52 Ok(canonicalized) => canonicalized,
53 Err(_) => continue 'inner,
54 };
55
56 if let Ok(metadata) = path.metadata() {
57 if metadata.is_dir() {
58 self.directories_to_walk.push_front(path);
59 } else if metadata.is_file()
60 && path.extension().map_or(false, |ext| ext == "desktop")
61 {
62 self.actively_walking = Some(iterator);
63 return Some(path);
64 }
65 }
66 }
67 }
68 }
69 }
70}
71
72impl Iter {
73 pub fn entries<'i, 'l: 'i, L>(
74 self,
75 locales_filter: Option<&'l [L]>,
76 ) -> impl Iterator<Item = DesktopEntry> + 'i
77 where
78 L: AsRef<str>,
79 {
80 self.map(move |path| DesktopEntry::from_path(path, locales_filter))
81 .filter_map(|e| e.ok())
82 }
83}