hel_fs/read/
read_dir_rec.rs

1use std::{
2	fs::{self, ReadDir},
3	io,
4	path::Path,
5};
6
7#[derive(Debug)]
8pub struct ReadDirRec(Vec<ReadDir>);
9
10/// Reads a directory recursively. Order is not guaranteed.
11pub fn read_dir_rec<P: AsRef<Path>>(path: P) -> io::Result<ReadDirRec> {
12	Ok(fs::read_dir(path)?.into())
13}
14
15impl From<ReadDir> for ReadDirRec {
16	fn from(value: std::fs::ReadDir) -> Self {
17		const CAP: usize = 5;
18		let mut inner = Vec::with_capacity(CAP);
19		inner.push(value);
20		Self(inner)
21	}
22}
23
24impl Iterator for ReadDirRec {
25	type Item = fs::DirEntry;
26
27	fn next(&mut self) -> Option<Self::Item> {
28		let last = self.0.last_mut()?;
29
30		let Some(Ok(entry)) = last.next() else {
31			self.0.pop();
32			return <Self as Iterator>::next(self)
33		};
34
35		let Ok(file_type) = entry.file_type() else {
36			return <Self as Iterator>::next(self)
37		};
38
39		if !file_type.is_dir() {
40			return Some(entry);
41		};
42
43		let Ok(dir) = fs::read_dir(entry.path()) else {
44			return <Self as Iterator>::next(self);
45		};
46
47		self.0.push(dir);
48
49		<Self as Iterator>::next(self)
50	}
51}
52
53#[cfg(test)]
54mod tests {
55	#[test]
56	fn read_dir() {
57		let contents: Vec<_> = crate::read_dir_rec(".").unwrap().collect();
58
59		assert!(!contents.is_empty());
60
61		assert!(
62			contents
63				.iter()
64				.filter(|entry| entry.file_name().to_str().unwrap().ends_with(".rs"))
65				.count() > 0
66		);
67	}
68}