use std::env; use std::fs::{read_dir, File}; use std::io::prelude::*; use std::path::Path; fn join_file(s: &str, base: Option<&str>) -> String { let dir = Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join(base.unwrap_or_default()); dir.join(s).to_string_lossy().to_string() } fn join_util(s: &str) -> String { join_file(s, Some("util")) } fn read_all() -> std::io::Result> { let dir = read_dir(join_util(""))?; let iter = dir .into_iter() .map(|f| f.unwrap().file_name().to_string_lossy().to_string()); Ok(iter) } fn read_list(s: &str) -> std::io::Result> { let hidden_list = join_file(s, None); let mut file = File::open(hidden_list)?; let mut content = String::new(); file.read_to_string(&mut content)?; Ok(content.split('\n').map(|s| s.trim().to_owned()).collect()) } fn main() -> std::io::Result<()> { let out_dir = env::var_os("OUT_DIR").unwrap(); let dest = Path::new(&out_dir).join("get_all_utils.rs"); let hidden_list = read_list("hidden_list")?; let last_list = read_list("last_list")?; let mut file = File::create(dest)?; let mut inner = vec![]; let mut last_inner = vec![]; for path in read_all()? { let mut splited = path.rsplitn(2, '.'); let ty = splited.next().unwrap(); let name = splited.next().unwrap(); let hidden = hidden_list.iter().any(|s| s == name); let is_last = last_list.iter().any(|s| s == name); let s = format!( " Util {{ name: \"util/{}\", ty: \"{}\", content: std::include_str!(r\"{}\"), is_hidden: {}, }} ", name, ty, join_util(&path), hidden ); if is_last { last_inner.push(s); } else { inner.push(s); } } file.write_all( b"#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct Util { pub name: &'static str, pub ty: &'static str, pub content: &'static str, pub is_hidden: bool, }", )?; file.write_all(b"pub fn get_all() -> &'static [Util] {\n")?; file.write_all(format!(" &[{}, {}]", inner.join(","), last_inner.join(",")).as_bytes())?; file.write_all(b"}\n")?; Ok(()) }