use serde::Deserialize; use std::{collections::HashMap, fmt, fs::File, io, path::Path}; use walkdir::WalkDir; use crate::types::*; #[derive(Clone, Debug, Deserialize)] pub struct Recipe { pub tasks: HashMap, } #[derive(Debug)] pub enum Error { IOError(io::Error), YAMLError(serde_yaml::Error), } impl From for Error { fn from(err: io::Error) -> Self { Error::IOError(err) } } impl From for Error { fn from(err: serde_yaml::Error) -> Self { Error::YAMLError(err) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Error::IOError(err) => write!(f, "IO error: {}", err), Error::YAMLError(err) => write!(f, "YAML error: {}", err), } } } impl std::error::Error for Error {} pub type Result = std::result::Result; pub fn read_recipe(path: &Path) -> Result { let f = File::open(path)?; let recipe: Recipe = serde_yaml::from_reader(f)?; Ok(recipe) } fn is_yml(path: &Path) -> bool { path.extension() == Some("yml".as_ref()) } pub fn read_recipes(path: &Path) -> Result> { let mut ret = HashMap::new(); for entry in WalkDir::new(path) .into_iter() .filter_map(|e| e.ok()) .filter(|e| { let path = e.path(); path.is_file() && is_yml(path) }) { let path = entry.path(); let basename = match path.file_stem().map(|n| n.to_str()) { Some(Some(v)) => v, _ => continue, }; let recipe = read_recipe(path)?; ret.insert(basename.to_string(), recipe); } Ok(ret) }