use std::collections::BTreeMap;
use std::io::Result;
use std::{
fs::{self, File},
io::Write,
path::Path,
};
mod stdlib_docs;
const ASM_DIR_PATH: &str = "./asm";
const DOC_DIR_PATH: &str = "./docs";
const ASM_FILE_PATH: &str = "./src/asm.rs";
type ModuleMap = BTreeMap<String, String>;
#[cfg(not(feature = "docs-rs"))]
fn main() {
println!("cargo:rerun-if-changed=asm");
let mut modules = BTreeMap::new();
let path = Path::new(ASM_DIR_PATH);
read_modules(path, "std".to_string(), &mut modules)
.expect("failed to read modules from the asm directory");
write_asm_rs(&modules).expect("failed to write modules into the module file");
stdlib_docs::build_stdlib_docs(&modules, DOC_DIR_PATH);
}
fn read_modules(fs_path: &Path, ns_path: String, modules: &mut ModuleMap) -> Result<()> {
for dir in fs_path.read_dir()? {
let path = dir?.path();
if path.is_dir() {
let dir_name = path
.file_name()
.expect("failed to get directory name from path")
.to_str()
.expect("failed to convert directory name to string");
let ns_path = format!("{}::{}", ns_path, dir_name);
read_modules(path.as_path(), ns_path, modules)?;
} else if path.is_file() {
let extension = path
.extension()
.expect("failed to get file extension from path")
.to_str()
.expect("failed to convert file extension to string");
assert_eq!("masm", extension, "invalid file extension at: {:?}", path);
let source = fs::read_to_string(path.as_path())?;
let file_name = path
.with_extension("") .as_path()
.file_name()
.expect("failed to get file name from path")
.to_str()
.expect("failed to convert file name to string")
.to_string();
modules.insert(format!("{}::{}", ns_path, file_name), source);
} else {
panic!("entry not a file or directory");
}
}
Ok(())
}
#[rustfmt::skip]
fn write_asm_rs(modules: &ModuleMap) -> Result<()> {
let mut asm_file = File::create(ASM_FILE_PATH)?;
writeln!(asm_file, "//! This module is automatically generated during build time and should not be modified manually.\n")?;
writeln!(asm_file, "/// An array of modules defined in Miden standard library.")?;
writeln!(asm_file, "///")?;
writeln!(asm_file, "/// Entries in the array are tuples containing module namespace and module source code.")?;
writeln!(asm_file, "#[rustfmt::skip]")?;
writeln!(asm_file, "pub const MODULES: [(&str, &str); {}] = [", modules.len())?;
for (ns, source) in modules {
let separator_suffix = (0..(89 - ns.len())).map(|_| "-").collect::<String>();
writeln!(asm_file, "// ----- {} {}", ns, separator_suffix)?;
writeln!(asm_file, "(\"{}\", \"{}\"),", ns, source)?;
}
writeln!(asm_file, "];")
}