use std::collections::VecDeque; use std::ops::AsyncFn; use std::path::PathBuf; use tokio::fs::DirEntry; use crate::error::CustomError; pub(crate) async fn walk_fs< P: Into, F: AsyncFn(&DirEntry) -> Result, >( root: P, filter: F, ) -> Result, CustomError> { let mut ret = Vec::new(); let mut backlog = VecDeque::new(); backlog.push_back(root.into()); while let Some(p) = backlog.pop_front() { let mut entries = tokio::fs::read_dir(p).await?; while let Some(entry) = entries.next_entry().await? { let action = filter(&entry).await?; match action { WalkAction::HaltAndCapture => { ret.push(entry); } WalkAction::Halt => {} WalkAction::RecurseAndCapture => { backlog.push_back(entry.path()); ret.push(entry); } WalkAction::Recurse => { backlog.push_back(entry.path()); } }; } } Ok(ret) } pub(crate) enum WalkAction { /// Do not walk down this path but add it to the return list. HaltAndCapture, /// Do not walk down this path and do not add it to the return list. Halt, /// Walk down this path and add it to the return list. RecurseAndCapture, /// Walk down this path but do not add it to the return list. Recurse, }