use std::env; use std::fs; use std::io::Write; use std::path::{Path, PathBuf}; fn main() { generate_styles(); generate_tests(); } fn generate_styles() { let styles: Vec = std::fs::read_dir("./resources/styles") .unwrap() .map(|direntry| direntry.unwrap().path().canonicalize().unwrap()) .collect(); let outfile_path = Path::new(&env::var("OUT_DIR").unwrap()).join("generated_styles.rs"); let mut outfile = fs::File::create(outfile_path).unwrap(); writeln!( outfile, r#"/// Automatically generated styles. use crate::render::GobanStyle;"# ) .unwrap(); writeln!( outfile, r#" lazy_static::lazy_static! {{ static ref STYLES: [GobanStyle; {}] = ["#, styles.len() ) .unwrap(); for path in &styles { writeln!( outfile, r#" toml::from_str(include_str!(r"{path}")).unwrap(),"#, path = path.display(), ) .unwrap(); } writeln!( outfile, r#" ]; }}"# ) .unwrap(); writeln!( outfile, r#" #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, clap::ValueEnum)] pub enum GeneratedStyle {{"# ) .unwrap(); for path in &styles { writeln!(outfile, " {},", style_name(path)).unwrap(); } writeln!(outfile, r#"}}"#).unwrap(); writeln!( outfile, r#" impl GeneratedStyle {{ pub fn style(&self) -> &GobanStyle {{ &STYLES[*self as usize] }} }}"# ) .unwrap(); } fn style_name(path: &Path) -> String { let mut name = path .with_extension("") .file_name() .unwrap() .to_str() .unwrap() .to_owned(); name.get_mut(0..1).unwrap().make_ascii_uppercase(); name } fn generate_tests() { let outfile_path = Path::new(&env::var("OUT_DIR").unwrap()).join("generated_tests.rs"); let mut outfile = fs::File::create(outfile_path).unwrap(); write_tests_header(&mut outfile); let test_data = std::fs::read_dir("./tests/data").unwrap(); for result in test_data { let entry = result.unwrap(); if entry.metadata().unwrap().is_dir() { write_test(&mut outfile, &entry); } } } fn write_tests_header(outfile: &mut fs::File) { write!( outfile, r#"/// Automatically generated tests. use clap::Parser; use sgf_render::{{Goban, RenderArgs, OutputFormat, svg}}; "#, ) .unwrap(); } fn write_test(outfile: &mut fs::File, dir: &fs::DirEntry) { let dir = dir.path().canonicalize().unwrap(); let path = dir.display(); let separator = std::path::MAIN_SEPARATOR; let test_name = dir.file_name().unwrap().to_string_lossy(); writeln!( outfile, r#" #[test] fn {test_name}() {{ let mut arguments = shell_words::split(include_str!(r"{path}{separator}options.txt")).unwrap(); if let Some(i) = arguments.iter().position(|s| s == "--custom-style") {{ arguments[i + 1] = format!(r"{path}{separator}{{}}", arguments[i + 1]); }} arguments.insert(0, "sgf-render".to_string()); let render_args = RenderArgs::parse_from(&arguments); let options = render_args.options(&OutputFormat::Svg).unwrap(); let input = include_str!(r"{path}{separator}input.sgf"); let expected = include_str!(r"{path}{separator}output.svg"); let goban = Goban::from_sgf(input, &options.node_description).unwrap(); let svg = svg::render(&goban, &options).unwrap(); let mut buffer: Vec = vec![]; svg.write_to(&mut buffer).unwrap(); let result = std::str::from_utf8(&buffer).unwrap(); assert_eq!(result, expected); }}"#, test_name = test_name, path = path, separator = separator, ) .unwrap(); }