2022-05-08 23:53:40 +03:00
|
|
|
use core::fmt;
|
2022-05-08 00:58:41 +03:00
|
|
|
use std::fs;
|
|
|
|
use std::io::{BufWriter, Write};
|
|
|
|
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
2022-05-08 16:21:06 +03:00
|
|
|
fn main() {
|
2022-05-08 23:53:40 +03:00
|
|
|
println!("cargo:rerun-if-changed=data/*");
|
2022-05-08 16:21:06 +03:00
|
|
|
if let Err(e) = gen_data_mod() {
|
|
|
|
eprintln!("Error: {}", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gen_data_mod() -> Result<(), std::io::Error> {
|
|
|
|
let file = fs::File::create("src/data.rs")?;
|
|
|
|
let mut buf = BufWriter::new(file);
|
2022-05-15 23:25:11 +03:00
|
|
|
|
|
|
|
writeln!(buf, "use crate::types::*;\n")?;
|
2022-05-08 16:21:06 +03:00
|
|
|
println!("cargo:rerun-if-changed=data/ingredients/*.toml");
|
|
|
|
write_ingredients(&mut buf)?;
|
2022-05-08 23:53:40 +03:00
|
|
|
println!("cargo:rerun-if-changed=data/recipes/*.toml");
|
|
|
|
write_recipes(&mut buf)?;
|
2022-05-08 16:21:06 +03:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-05-08 00:58:41 +03:00
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
pub struct Main {
|
|
|
|
ingredients: Option<Vec<Ingredient>>,
|
|
|
|
recipes: Option<Vec<Recipe>>,
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
#[allow(dead_code)]
|
2022-05-08 00:58:41 +03:00
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
pub struct Ingredient {
|
|
|
|
key: String,
|
|
|
|
translates: IngredientTranslate,
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
#[allow(dead_code)]
|
2022-05-08 00:58:41 +03:00
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
pub struct IngredientTranslate {
|
2022-05-13 19:42:43 +03:00
|
|
|
rus: String,
|
|
|
|
eng: Option<String>,
|
2022-05-08 00:58:41 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
#[derive(Deserialize)]
|
2022-05-08 00:58:41 +03:00
|
|
|
pub struct Recipe {
|
|
|
|
key: String,
|
|
|
|
ingredients: Vec<RecipeIngredient>,
|
|
|
|
steps: u8,
|
|
|
|
translates: RecipeTranslates,
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
impl fmt::Debug for Recipe {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("Recipe")
|
|
|
|
.field("key", &self.key)
|
|
|
|
.field("steps", &self.steps)
|
|
|
|
.field("ingredients", &format_args!("vec!{:#?}", self.ingredients))
|
|
|
|
.field("translates", &self.translates)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
2022-05-08 00:58:41 +03:00
|
|
|
pub struct RecipeIngredient {
|
|
|
|
key: String,
|
|
|
|
#[serde(flatten)]
|
|
|
|
measure: RecipeIngredientMeasure,
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
impl fmt::Debug for RecipeIngredient {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("RecipeIngredient")
|
|
|
|
.field("key", &self.key)
|
2022-05-15 23:25:11 +03:00
|
|
|
.field("measure", &format_args!("Measure::{:?}", self.measure))
|
2022-05-08 23:53:40 +03:00
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-08 00:58:41 +03:00
|
|
|
#[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),
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
#[allow(dead_code)]
|
2022-05-08 00:58:41 +03:00
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
pub struct RecipeTranslates {
|
2022-05-13 19:42:43 +03:00
|
|
|
rus: RecipeTranslate,
|
|
|
|
eng: Option<RecipeTranslate>,
|
2022-05-08 00:58:41 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
#[derive(Deserialize)]
|
2022-05-08 00:58:41 +03:00
|
|
|
pub struct RecipeTranslate {
|
|
|
|
name: String,
|
|
|
|
instructions: Vec<String>,
|
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
impl fmt::Debug for RecipeTranslate {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("RecipeTranslate")
|
|
|
|
.field("name", &self.name)
|
|
|
|
.field(
|
|
|
|
"instructions",
|
|
|
|
&format_args!("vec!{:#?}", self.instructions),
|
|
|
|
)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-08 00:58:41 +03:00
|
|
|
fn write_ingredients(file: &mut BufWriter<fs::File>) -> Result<(), std::io::Error> {
|
2022-05-08 16:21:06 +03:00
|
|
|
let ingredients = get_ingredient_configs()?;
|
2022-05-08 00:58:41 +03:00
|
|
|
|
|
|
|
writeln!(
|
|
|
|
file,
|
2022-05-08 23:53:40 +03:00
|
|
|
"pub const INGREDIENTS: [Ingredient; {}] = {:#?};\n",
|
2022-05-08 16:21:06 +03:00
|
|
|
ingredients.len(),
|
|
|
|
ingredients
|
2022-05-08 00:58:41 +03:00
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-05-08 16:21:06 +03:00
|
|
|
fn get_ingredient_configs() -> Result<Vec<Ingredient>, std::io::Error> {
|
|
|
|
Ok(fs::read_dir("data/ingredients")?
|
|
|
|
.map(|res| res.and_then(|e| fs::read_to_string(e.path())))
|
|
|
|
.collect::<Result<Vec<_>, std::io::Error>>()?
|
|
|
|
.into_iter()
|
|
|
|
.map(|content| toml::from_str(&content).unwrap())
|
|
|
|
.filter_map(|cfg: Main| cfg.ingredients)
|
|
|
|
.flatten()
|
|
|
|
.collect::<Vec<Ingredient>>())
|
2022-05-08 00:58:41 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
fn write_recipes(file: &mut BufWriter<fs::File>) -> Result<(), std::io::Error> {
|
|
|
|
let recipes = get_recipe_configs()?;
|
|
|
|
|
|
|
|
writeln!(
|
|
|
|
file,
|
|
|
|
r#"lazy_static::lazy_static! {{
|
|
|
|
pub static ref RECIPES: [Recipe; {}] = {:#?};
|
|
|
|
}}"#,
|
|
|
|
recipes.len(),
|
|
|
|
recipes
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(())
|
2022-05-08 00:58:41 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 23:53:40 +03:00
|
|
|
fn get_recipe_configs() -> Result<Vec<Recipe>, std::io::Error> {
|
|
|
|
Ok(fs::read_dir("data/recipes")?
|
|
|
|
.map(|res| res.and_then(|e| fs::read_to_string(e.path())))
|
|
|
|
.collect::<Result<Vec<_>, std::io::Error>>()?
|
|
|
|
.into_iter()
|
|
|
|
.map(|content| toml::from_str(&content).unwrap())
|
|
|
|
.filter_map(|cfg: Main| cfg.recipes)
|
|
|
|
.flatten()
|
|
|
|
.collect::<Vec<Recipe>>())
|
2022-05-08 00:58:41 +03:00
|
|
|
}
|