use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
fn gen_order(
result: &mut Vec<Vec<&'static str>>,
index: &Vec<&'static str>,
next: Vec<&'static str>,
deep: i32,
) {
for s in index {
let mut next = next.clone();
next.push(s);
if deep == 0 {
result.push(next);
} else {
gen_order(result, index, next, deep - 1);
}
}
}
fn get_order(index: &Vec<&'static str>) -> Vec<Vec<&'static str>> {
let mut result = vec![];
for i in 0..index.len() {
gen_order(&mut result, &index, vec![], i as i32);
}
result
}
fn is_valid(ls: &[&str], has: &[&str]) -> bool {
for s in ls {
if !has.contains(&s) {
return false;
}
}
true
}
fn gen_code(path: &PathBuf) {
let index = vec!["x", "y", "z", "w"];
let map = HashMap::from([("x", 0), ("y", 1), ("z", 2), ("w", 3)]);
let result = get_order(&index);
let mut file = File::create(path).unwrap();
for i in 2..5 {
writeln!(file, "impl<T:Copy> Vec{}<T> {{", i).unwrap();
let has = &index[..i];
for ls in &result {
let res_type = if ls.len() == 1 {
format!("T")
} else {
format!("Vec{}<T>", ls.len())
};
if is_valid(ls, has) {
writeln!(file, " /// GLSL syntax: v.{}", ls.join("")).unwrap();
writeln!(file, " ///").unwrap();
writeln!(file, " /// # Example").unwrap();
writeln!(file, " /// ```").unwrap();
writeln!(file, " /// use mats::*;").unwrap();
writeln!(file, " ///").unwrap();
let args = (0..i)
.into_iter()
.map(|i| format!("{}", i))
.collect::<Vec<_>>()
.join(", ");
writeln!(file, " /// let v = Vec{}::new([[{}]]);", i, args).unwrap();
writeln!(file, " ///").unwrap();
let left = format!("v.{}()", ls.join(""));
let right = if ls.len() == 1 {
format!("{}", map[ls[0]])
} else {
format!(
"Vec{}::new([[{}]])",
ls.len(),
ls.iter()
.map(|s| format!("{}", map[s]))
.collect::<Vec<_>>()
.join(", ")
)
};
writeln!(file, " /// assert_eq!({}, {});", left, right).unwrap();
writeln!(file, " /// ```").unwrap();
writeln!(file, " #[inline]").unwrap();
writeln!(file, " pub fn {}(&self) -> {} {{", ls.join(""), res_type).unwrap();
if ls.len() > 1 {
writeln!(file, " Vec{}::new([[", ls.len()).unwrap();
}
for s in ls {
write!(file, " self[{}]", map[s]).unwrap();
if ls.len() > 1 {
writeln!(file, ",").unwrap();
} else {
writeln!(file, "").unwrap();
}
}
if ls.len() > 1 {
writeln!(file, " ]])").unwrap();
}
writeln!(file, " }}").unwrap();
writeln!(file, "").unwrap();
}
}
writeln!(file, "}}").unwrap();
writeln!(file, "").unwrap();
}
}
fn gen_crate_io_readme() {
let mut readme = File::open("README.md").unwrap();
let mut release = File::open("RELEASE.md").unwrap();
let mut file = File::create("CRATE.md").unwrap();
let mut buff = Vec::new();
readme.read_to_end(&mut buff).unwrap();
file.write_all(&buff).unwrap();
write!(file, "\n\n-------\n\n").unwrap();
buff.clear();
release.read_to_end(&mut buff).unwrap();
file.write_all(&buff).unwrap();
}
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("generated.rs");
println!("cargo:rerun-if-changed=README.md");
println!("cargo:rerun-if-changed=RELEASE.md");
gen_code(&dest_path);
gen_crate_io_readme();
}