diff --git a/tools/src/recipe.rs b/tools/src/recipe.rs index 2796788..5961cdb 100644 --- a/tools/src/recipe.rs +++ b/tools/src/recipe.rs @@ -6,7 +6,7 @@ pub enum Unit { } /// `Quantity` measures the amount of a resource (Input or Output). -#[derive(Clone, Copy, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, serde::Deserialize)] pub struct Quantity { pub amount: f32, pub unit: Option, @@ -37,7 +37,7 @@ pub struct Input { pub quantity: Quantity, } -#[derive(Debug, serde::Deserialize)] +#[derive(Debug, PartialEq, serde::Deserialize)] pub struct Output { // Quantity defaults to "amount=1" if omitted. #[serde(default)] @@ -91,7 +91,18 @@ pub struct Recipe { impl Recipe { pub fn from_file(file: &std::path::PathBuf) -> anyhow::Result { let recipe_contents = std::fs::read_to_string(file)?; - let recipe: Recipe = toml::from_str(&recipe_contents)?; + let mut recipe: Recipe = toml::from_str(&recipe_contents)?; + if recipe.outputs == None { + if let Some(recipe_name) = file.file_stem() { + let mut outputs = std::collections::HashMap::::new(); + let key = recipe_name.to_string_lossy().into_owned(); + let value = Output { + quantity: Quantity::default(), + }; + outputs.insert(key, value); + recipe.outputs = Some(outputs); + } + } // let r = recipe.validate_recipe(); Ok(recipe) } diff --git a/tools/src/repo.rs b/tools/src/repo.rs index c5eb6a8..dfd4f9a 100644 --- a/tools/src/repo.rs +++ b/tools/src/repo.rs @@ -79,7 +79,15 @@ impl Repo { // println!("reading Recipe from {:?}", path); if let Some(recipe_name) = path.file_stem() { let key = recipe_name.to_string_lossy().into_owned(); - let value = crate::Recipe::from_file(path)?; + let value = match crate::Recipe::from_file(path) { + Ok(recipe) => recipe, + Err(e) => { + return Err(anyhow::Error::msg(format!( + "failed to read recipe {}: {:?}", + key, e + ))); + } + }; self.recipes.insert(key, value); } Ok(()) @@ -93,7 +101,15 @@ impl Repo { indent: usize, ) -> anyhow::Result<()> { for (input_name, input_info) in recipe.inputs.iter() { - let input_recipe = self.get_recipe(input_name).unwrap(); + let input_recipe = match self.get_recipe(input_name) { + Some(recipe) => recipe, + None => { + return Err(anyhow::Error::msg(format!( + "failed to get recipe '{}'", + input_name + ))); + } + }; // A Recipe whose only input is Capital is a Vitamin. let cost = match input_recipe.is_vitamin() { @@ -109,10 +125,12 @@ impl Repo { .ok_or(anyhow::Error::msg(format!( "can't find input capital for {input_name}" )))?; - assert_eq!( - input_capital.quantity.unit, - Some(crate::recipe::Unit::USDollar) - ); + if input_capital.quantity.unit != Some(crate::recipe::Unit::USDollar) { + return Err(anyhow::Error::msg(format!( + "{} input capital does not have units USDollar", + input_name + ))); + } let cost = input_capital.quantity.amount; let outputs = match &input_recipe.outputs {