use std::fs; use std::io::{BufWriter, Write}; use serde::Deserialize; #[derive(Deserialize, Debug)] pub struct Main { ingredients: Option>, recipes: Option>, } #[derive(Deserialize, Debug)] pub struct Ingredient { key: String, translates: IngredientTranslate, } #[derive(Deserialize, Debug)] pub struct IngredientTranslate { ru: String, en: Option, } #[derive(Deserialize, Debug)] pub struct Recipe { key: String, ingredients: Vec, steps: u8, translates: RecipeTranslates, } #[derive(Deserialize, Debug)] pub struct RecipeIngredient { key: String, #[serde(flatten)] measure: RecipeIngredientMeasure, } #[derive(Deserialize, Debug)] pub enum RecipeIngredientMeasure { #[serde(rename = "g")] Gram(u32), #[serde(rename = "kg")] KiloGram(u32), #[serde(rename = "ml")] MilliLiter(u32), #[serde(rename = "l")] Liter(u32), } #[derive(Deserialize, Debug)] pub struct RecipeTranslates { ru: RecipeTranslate, en: Option, } #[derive(Deserialize, Debug)] pub struct RecipeTranslate { name: String, instructions: Vec, } fn write_structs(file: &mut BufWriter) -> Result<(), std::io::Error> { writeln!(file, "#[derive(Debug)]")?; writeln!(file, "pub struct Ingredient {{")?; writeln!(file, " pub key: &'static str,")?; writeln!(file, " translates: IngredientTranslate,")?; writeln!(file, "}}")?; writeln!(file, "#[derive(Debug)]")?; writeln!(file, "pub struct IngredientTranslate {{")?; writeln!(file, " ru: &'static str,")?; writeln!(file, " en: Option<&'static str>,")?; writeln!(file, "}}")?; writeln!(file, "#[derive(Debug)]")?; writeln!(file, "pub struct Recipe {{")?; writeln!(file, " key: &'static str,")?; writeln!(file, " ingredients: Vec,")?; writeln!(file, " steps: u8,")?; writeln!(file, " translates: RecipeTranslates,")?; writeln!(file, "}}")?; writeln!(file, "#[derive(Debug)]")?; writeln!(file, "pub struct RecipeIngredient {{")?; writeln!(file, " key: &'static str,")?; writeln!(file, " measure: RecipeIngredientMeasure,")?; writeln!(file, "}}")?; writeln!(file, "#[derive(Debug)]")?; writeln!(file, "pub enum RecipeIngredientMeasure {{")?; writeln!(file, " Gram(u32),")?; writeln!(file, " KiloGram(u32),")?; writeln!(file, " MilliLiter(u32),")?; writeln!(file, " Liter(u32),")?; writeln!(file, "}}")?; writeln!(file, "#[derive(Debug)]")?; writeln!(file, "pub struct RecipeTranslates {{")?; writeln!(file, " ru: RecipeTranslate,")?; writeln!(file, " en: Option,")?; writeln!(file, "}}")?; writeln!(file, "#[derive(Debug)]")?; writeln!(file, "pub struct RecipeTranslate {{")?; writeln!(file, " name: &'static str,")?; writeln!(file, " instructions: Vec<&'static str>,")?; writeln!(file, "}}")?; Ok(()) } fn write_ingredients(file: &mut BufWriter) -> Result<(), std::io::Error> { // fs::read_dir("data/ingredients") let fruit = fs::read_to_string("data/ingredients/fruit.toml")?; let cfg: Main = toml::from_str(&fruit).unwrap(); let mut ins: usize = 0; writeln!( file, "pub const INGREDIENTS: [Ingredient; {}] = [", cfg.ingredients .as_ref() .map(|i| i.len()) .unwrap_or_default() )?; ins += 1; if let Some(ingredients) = cfg.ingredients { for ingredient in ingredients { writeln!(file, "{}Ingredient {{", indent(ins))?; ins += 1; writeln!(file, "{}key: {:?},", indent(ins), to_str(ingredient.key))?; writeln!(file, "{}translates: IngredientTranslate {{", indent(ins))?; ins += 1; writeln!( file, "{}ru: {:?},", indent(ins), to_str(ingredient.translates.ru) )?; writeln!( file, "{}en: {:?},", indent(ins), ingredient.translates.en.map(to_str) )?; ins -= 1; writeln!(file, "{}}}", indent(ins))?; ins -= 1; writeln!(file, "{}}},", indent(ins))?; } } ins -= 1; writeln!(file, "{}];", indent(ins))?; Ok(()) } fn gen_data_mod() -> Result<(), std::io::Error> { let file = fs::File::create("src/data.rs")?; let mut buf = BufWriter::new(file); write_structs(&mut buf)?; println!("cargo:rerun-if-changed=data"); write_ingredients(&mut buf)?; Ok(()) } fn indent(indent_size: usize) -> String { std::iter::repeat(" ").take(indent_size * 4).collect() } fn to_str(string: String) -> &'static str { Box::leak(string.into_boxed_str()) } fn main() { println!("cargo:rerun-if-changed=build.rs"); if let Err(e) = gen_data_mod() { eprintln!("Error: {}", e); } }