use std::path::{Path, PathBuf}; #[derive(Debug, PartialEq)] pub enum ProjectType { Maven, Npm, Cargo } impl ProjectType { fn detect>(path: P) -> Option { let project_path: PathBuf = path.as_ref().into(); if project_path.join("pom.xml").is_file() { return Some(ProjectType::Maven); } else if project_path.join("package.json").is_file() { return Some(ProjectType::Npm); } else if project_path.join("Cargo.toml").is_file() { return Some(ProjectType::Cargo); } None } } #[derive(Debug)] pub struct Project { pub project_type: ProjectType, path: PathBuf } impl Project { pub fn path(&self) -> &Path { &self.path } } pub struct Scouter { search_path: PathBuf } impl Scouter { pub fn new>(path: P) -> Scouter { let mut search_path: PathBuf = path.as_ref().into(); if !search_path.is_dir() { search_path.pop(); } Scouter { search_path: search_path } } } impl Iterator for Scouter { type Item = Project; fn next(&mut self) -> Option { loop { let project_type = ProjectType::detect(&self.search_path); if project_type.is_some() { return project_type.map(|project_type| Project { project_type: project_type, path: self.search_path.to_owned() }); } if !self.search_path.pop() { return None; } } } } #[cfg(test)] mod test { use super::{ProjectType, Scouter}; #[test] fn test_scouter() { let mut scouter = Scouter::new(file!()); assert_eq!(ProjectType::Cargo, scouter.next().unwrap().project_type); } }