db improve data builder

This commit is contained in:
Dmitriy Pleshevskiy 2022-05-08 16:21:06 +03:00
parent bd8855fde6
commit 4d13485253
4 changed files with 186 additions and 111 deletions

View File

@ -3,6 +3,76 @@ use std::io::{BufWriter, Write};
use serde::Deserialize; use serde::Deserialize;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
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);
write_structs(&mut buf)?;
println!("cargo:rerun-if-changed=data/ingredients/*.toml");
write_ingredients(&mut buf)?;
Ok(())
}
fn write_structs(file: &mut BufWriter<fs::File>) -> Result<(), std::io::Error> {
let structs = r#"
#[derive(Debug)]
pub struct Ingredient {
pub key: &'static str,
pub translates: IngredientTranslate,
}
#[derive(Debug)]
pub struct IngredientTranslate {
pub ru: &'static str,
pub en: Option<&'static str>,
}
#[derive(Debug)]
pub struct Recipe {
key: &'static str,
ingredients: Vec<RecipeIngredient>,
steps: u8,
translates: RecipeTranslates,
}
#[derive(Debug)]
pub struct RecipeIngredient {
key: &'static str,
measure: RecipeIngredientMeasure,
}
#[derive(Debug)]
pub enum RecipeIngredientMeasure {
Gram(u32),
KiloGram(u32),
MilliLiter(u32),
Liter(u32),
}
#[derive(Debug)]
pub struct RecipeTranslates {
ru: RecipeTranslate,
en: Option<RecipeTranslate>,
}
#[derive(Debug)]
pub struct RecipeTranslate {
name: &'static str,
instructions: Vec<&'static str>,
}
"#;
writeln!(file, "{}", structs)?;
Ok(())
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Main { pub struct Main {
ingredients: Option<Vec<Ingredient>>, ingredients: Option<Vec<Ingredient>>,
@ -60,109 +130,49 @@ pub struct RecipeTranslate {
instructions: Vec<String>, instructions: Vec<String>,
} }
fn write_structs(file: &mut BufWriter<fs::File>) -> 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<RecipeIngredient>,")?;
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<RecipeTranslate>,")?;
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<fs::File>) -> Result<(), std::io::Error> { fn write_ingredients(file: &mut BufWriter<fs::File>) -> Result<(), std::io::Error> {
// fs::read_dir("data/ingredients") let ingredients = get_ingredient_configs()?;
let fruit = fs::read_to_string("data/ingredients/fruit.toml")?;
let cfg: Main = toml::from_str(&fruit).unwrap();
let mut ins: usize = 0;
writeln!( writeln!(
file, file,
"pub const INGREDIENTS: [Ingredient; {}] = [", "pub const INGREDIENTS: [Ingredient; {}] = [{}];",
cfg.ingredients ingredients.len(),
.as_ref() ingredients
.map(|i| i.len()) .into_iter()
.unwrap_or_default() .map(|i| to_ingredient_data_content(1, i))
.collect::<String>()
)?; )?;
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(()) Ok(())
} }
fn gen_data_mod() -> Result<(), std::io::Error> { fn to_ingredient_data_content(indent_size: usize, ingredient: Ingredient) -> String {
let file = fs::File::create("src/data.rs")?; format!(
let mut buf = BufWriter::new(file); r#"
write_structs(&mut buf)?; {i}Ingredient {{
println!("cargo:rerun-if-changed=data"); {i} key: {key:?},
write_ingredients(&mut buf)?; {i} translates: IngredientTranslate {{
Ok(()) {i} ru: {tr_ru:?},
{i} en: {tr_en:?},
{i} }},
{i}}},
"#,
i = indent(indent_size),
key = to_str(ingredient.key),
tr_ru = to_str(ingredient.translates.ru),
tr_en = ingredient.translates.en.map(to_str),
)
}
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>>())
} }
fn indent(indent_size: usize) -> String { fn indent(indent_size: usize) -> String {
@ -172,10 +182,3 @@ fn indent(indent_size: usize) -> String {
fn to_str(string: String) -> &'static str { fn to_str(string: String) -> &'static str {
Box::leak(string.into_boxed_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);
}
}

View File

@ -8,7 +8,7 @@ measure = "kg"
[[ingredients]] [[ingredients]]
key = "potato" key = "potato"
measure = "kg" measure = "kg"
[ingredienst.translates] [ingredients.translates]
ru = "картофель" ru = "картофель"
en = "potato" en = "potato"

View File

@ -1,13 +1,16 @@
#[derive(Debug)] #[derive(Debug)]
pub struct Ingredient { pub struct Ingredient {
pub key: &'static str, pub key: &'static str,
translates: IngredientTranslate, pub translates: IngredientTranslate,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct IngredientTranslate { pub struct IngredientTranslate {
ru: &'static str, pub ru: &'static str,
en: Option<&'static str>, pub en: Option<&'static str>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Recipe { pub struct Recipe {
key: &'static str, key: &'static str,
@ -15,11 +18,13 @@ pub struct Recipe {
steps: u8, steps: u8,
translates: RecipeTranslates, translates: RecipeTranslates,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct RecipeIngredient { pub struct RecipeIngredient {
key: &'static str, key: &'static str,
measure: RecipeIngredientMeasure, measure: RecipeIngredientMeasure,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum RecipeIngredientMeasure { pub enum RecipeIngredientMeasure {
Gram(u32), Gram(u32),
@ -27,36 +32,105 @@ pub enum RecipeIngredientMeasure {
MilliLiter(u32), MilliLiter(u32),
Liter(u32), Liter(u32),
} }
#[derive(Debug)] #[derive(Debug)]
pub struct RecipeTranslates { pub struct RecipeTranslates {
ru: RecipeTranslate, ru: RecipeTranslate,
en: Option<RecipeTranslate>, en: Option<RecipeTranslate>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct RecipeTranslate { pub struct RecipeTranslate {
name: &'static str, name: &'static str,
instructions: Vec<&'static str>, instructions: Vec<&'static str>,
} }
pub const INGREDIENTS: [Ingredient; 3] = [
pub const INGREDIENTS: [Ingredient; 11] = [
Ingredient {
key: "water",
translates: IngredientTranslate {
ru: "вода",
en: Some("water"),
},
},
Ingredient {
key: "carrot",
translates: IngredientTranslate {
ru: "морковь",
en: Some("carrot"),
},
},
Ingredient {
key: "potato",
translates: IngredientTranslate {
ru: "картофель",
en: Some("potato"),
},
},
Ingredient {
key: "wheat_flour",
translates: IngredientTranslate {
ru: "пшеничная мука",
en: Some("wheat flour"),
},
},
Ingredient {
key: "olive_oil",
translates: IngredientTranslate {
ru: "оливковое масло",
en: Some("olive oil"),
},
},
Ingredient {
key: "dry_yeast",
translates: IngredientTranslate {
ru: "сухие дрожжи",
en: Some("dry yeast"),
},
},
Ingredient { Ingredient {
key: "apple", key: "apple",
translates: IngredientTranslate { translates: IngredientTranslate {
ru: "яблоко", ru: "яблоко",
en: Some("apple"), en: Some("apple"),
} },
}, },
Ingredient { Ingredient {
key: "banana", key: "banana",
translates: IngredientTranslate { translates: IngredientTranslate {
ru: "банан", ru: "банан",
en: Some("banana"), en: Some("banana"),
} },
}, },
Ingredient { Ingredient {
key: "orange", key: "orange",
translates: IngredientTranslate { translates: IngredientTranslate {
ru: "апельсин", ru: "апельсин",
en: Some("orange"), en: Some("orange"),
} },
},
Ingredient {
key: "salt",
translates: IngredientTranslate {
ru: "соль",
en: Some("salt"),
},
},
Ingredient {
key: "sugar",
translates: IngredientTranslate {
ru: "сахар",
en: Some("sugar"),
},
}, },
]; ];

View File

@ -1,5 +1,3 @@
use crate::data::Ingredient;
mod data; mod data;
fn main() { fn main() {