#![forbid(unsafe_code)]
use std::fs::File;
use std::io::Write;
use structopt::StructOpt;
use strum::VariantNames;
use strum_macros::{Display, EnumString, EnumVariantNames};
mod assemblyscript;
mod astype;
mod doc;
mod error;
mod overview;
mod pretty_writer;
mod rust;
mod zig;
pub use crate::error::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Display, EnumString, EnumVariantNames)]
#[strum(serialize_all = "snake_case")]
pub enum OutputType {
#[strum(serialize = "assemblyscript")]
AssemblyScript,
Rust,
Zig,
Overview,
#[strum(serialize = "doc", serialize = "markdown")]
Doc,
}
#[derive(Debug, Clone, PartialEq, Eq, StructOpt)]
pub struct Config {
#[structopt(short, long)]
pub module_name: Option<String>,
#[structopt(short, long)]
pub output_file: Option<String>,
#[structopt()]
pub witx_files: Vec<String>,
#[structopt(short="t", long, possible_values=OutputType::VARIANTS)]
pub output_type: OutputType,
#[structopt(flatten)]
pub flags: Options,
}
impl Default for Config {
fn default() -> Self {
Self {
module_name: None,
output_file: None,
witx_files: vec![],
output_type: OutputType::Doc,
flags: Options {
skip_header: false,
skip_imports: false,
},
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, StructOpt)]
pub struct Options {
#[structopt(short = "I", long)]
skip_imports: bool,
#[structopt(short = "H", long)]
skip_header: bool,
}
pub trait Generator<T: Write> {
fn generate(
&self,
writer: &mut T,
module_witx: witx::Module,
options: &Options,
) -> Result<(), Error>;
}
fn get_generator<T: Write>(module: Option<&str>, output: OutputType) -> Box<dyn Generator<T>> {
let m = module.map(|v| v.to_string());
match output {
OutputType::AssemblyScript => Box::new(assemblyscript::AssemblyScriptGenerator::new(m)),
OutputType::Zig => Box::new(zig::ZigGenerator::new(m)),
OutputType::Rust => Box::new(rust::RustGenerator::new(m)),
OutputType::Overview => Box::new(overview::OverviewGenerator::new(m)),
OutputType::Doc => Box::new(doc::DocGenerator::new(m)),
}
}
pub fn generate(cfg: &Config) -> Result<(), Error> {
let mut writer: Box<dyn Write> = match cfg.output_file.as_deref() {
None | Some("-") => Box::new(std::io::stdout()),
Some(file) => Box::new(File::create(file).unwrap()),
};
let mut flags = cfg.flags.clone();
for witx_file in &cfg.witx_files {
let witx = witx::load(witx_file).unwrap();
let generator = get_generator(cfg.module_name.as_deref(), cfg.output_type);
generator.generate(&mut writer, witx, &flags).unwrap();
flags.skip_imports = true;
flags.skip_header = true;
}
Ok(())
}