mats 2.0.1

A lightweight, efficient, and easy-to-use Rust matrix library.
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();
    // writeln!(file, "//! Generated by `build.rs`").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();
}