Path: blob/main/crates/environ/examples/factc.rs
3073 views
use clap::Parser;1use std::io::{IsTerminal, Write};2use std::path::{Path, PathBuf};3use wasmparser::{Validator, WasmFeatures};4use wasmtime_environ::{5ScopeVec, ToWasmtimeResult as _, Tunables,6component::*,7error::{Context as _, Result, bail},8};910/// A small helper utility to explore generated adapter modules from Wasmtime's11/// adapter fusion compiler.12///13/// This utility takes a `*.wat` file as input which is expected to be a valid14/// WebAssembly component. The component is parsed and any type definition for a15/// component function gets a generated adapter for it as if the caller/callee16/// used that type as the adapter.17///18/// For example with an input that looks like:19///20/// (component21/// (type (func (param u32) (result (list u8))))22/// )23///24/// This tool can be used to generate an adapter for that signature.25#[derive(Parser)]26struct Factc {27/// Whether or not debug code is inserted into the generated adapter.28#[arg(long)]29debug: bool,3031/// Whether or not to skip validation of the generated adapter module.32#[arg(long)]33skip_validate: bool,3435/// Where to place the generated adapter module. Standard output is used if36/// this is not specified.37#[arg(short, long)]38output: Option<PathBuf>,3940/// Output the text format for WebAssembly instead of the binary format.41#[arg(short, long)]42text: bool,4344/// The input component to generate adapters for.45input: PathBuf,46}4748fn main() -> Result<()> {49Factc::parse().execute()50}5152impl Factc {53fn execute(self) -> Result<()> {54env_logger::init();5556let input = wat::parse_file(&self.input)?;5758let tunables = Tunables::default_host();59let mut validator =60wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::all());61let mut component_types = ComponentTypesBuilder::new(&validator);62let adapters = ScopeVec::new();6364Translator::new(&tunables, &mut validator, &mut component_types, &adapters)65.translate(&input)?;6667let (out_name, mut out_file): (_, Box<dyn std::io::Write>) = match &self.output {68Some(file) => (69file.as_path(),70Box::new(std::io::BufWriter::new(71std::fs::File::create(file)72.with_context(|| format!("failed to create {}", file.display()))?,73)),74),75None => (Path::new("stdout"), Box::new(std::io::stdout())),76};7778for wasm in adapters.into_iter() {79let output = if self.text {80wasmprinter::print_bytes(&wasm)81.to_wasmtime_result()82.context("failed to convert binary wasm to text")?83.into_bytes()84} else if self.output.is_none() && std::io::stdout().is_terminal() {85bail!("cannot print binary wasm output to a terminal unless `-t` flag is passed")86} else {87wasm.to_vec()88};8990out_file91.write_all(&output)92.with_context(|| format!("failed to write to {}", out_name.display()))?;9394if !self.skip_validate {95Validator::new_with_features(WasmFeatures::default() | WasmFeatures::MEMORY64)96.validate_all(&wasm)97.context("failed to validate generated module")?;98}99}100101Ok(())102}103}104105106