Skip to main content

tinywasm_cli/
cli.rs

1use clap::builder::Styles;
2use clap::builder::styling::{AnsiColor, Effects};
3use clap::{Args, Parser, Subcommand, ValueEnum};
4use clap_complete::Shell;
5
6use crate::engine_flags::EngineFlags;
7
8// based on https://github.com/crate-ci/clap-cargo/blob/master/src/style.rs
9const STYLES: Styles = Styles::styled()
10    .header(AnsiColor::BrightGreen.on_default().effects(Effects::BOLD))
11    .usage(AnsiColor::BrightGreen.on_default().effects(Effects::BOLD))
12    .literal(AnsiColor::BrightCyan.on_default().effects(Effects::BOLD))
13    .placeholder(AnsiColor::Cyan.on_default())
14    .error(AnsiColor::BrightRed.on_default().effects(Effects::BOLD))
15    .valid(AnsiColor::BrightCyan.on_default().effects(Effects::BOLD))
16    .invalid(AnsiColor::Yellow.on_default());
17
18#[derive(Parser)]
19#[command(
20    name = "tinywasm",
21    about = "TinyWasm CLI",
22    styles = STYLES,
23    version,
24    args_conflicts_with_subcommands = true,
25    subcommand_negates_reqs = true
26)]
27pub struct Cli {
28    #[arg(long, global = true, value_enum, default_value_t = LogLevel::Info)]
29    pub log_level: LogLevel,
30
31    #[command(subcommand)]
32    pub command: Option<Commands>,
33
34    #[command(flatten)]
35    pub run: RunArgs,
36}
37
38#[derive(Subcommand)]
39pub enum Commands {
40    /// Run a module
41    Run(RunArgs),
42    /// Compile a Wasm/WAT module to a .twasm archive
43    Compile(CompileArgs),
44    /// Dump lowered TinyWasm bytecode
45    Dump(ModuleInputArgs),
46    /// Inspect imports and exports
47    Inspect(ModuleInputArgs),
48    #[cfg(feature = "wast")]
49    /// Execute WebAssembly spec scripts (.wast)
50    Wast(WastArgs),
51    /// Generate shell completions
52    Completion(CompletionArgs),
53}
54
55#[derive(Args, Clone)]
56pub struct RunArgs {
57    /// Module path, or `-` to read from stdin
58    pub module: Option<String>,
59
60    /// Invoke a named export instead of the default entrypoint
61    #[arg(long)]
62    pub invoke: Option<String>,
63
64    #[command(flatten)]
65    pub engine: EngineFlags,
66
67    /// Arguments passed to the invoked Wasm function
68    #[arg(trailing_var_arg = true)]
69    pub args: Vec<String>,
70}
71
72#[derive(Args, Clone)]
73pub struct CompileArgs {
74    /// Input module path, or `-` to read from stdin
75    pub input: String,
76
77    /// Output path, or `-` to write to stdout
78    #[arg(short, long)]
79    pub output: Option<String>,
80
81    /// Overwrite the output file if it already exists
82    #[arg(short, long)]
83    pub force: bool,
84}
85
86#[derive(Args, Clone)]
87pub struct ModuleInputArgs {
88    /// Module path, or `-` to read from stdin
89    pub module: String,
90}
91
92#[derive(Args, Clone)]
93pub struct CompletionArgs {
94    pub shell: Shell,
95}
96
97#[cfg(feature = "wast")]
98#[derive(Args, Clone)]
99pub struct WastArgs {
100    /// WAST files or directories containing .wast files
101    #[arg(required = true)]
102    pub paths: Vec<String>,
103}
104
105#[derive(Clone, Copy, ValueEnum)]
106pub enum LogLevel {
107    Trace,
108    Debug,
109    Info,
110    Warn,
111    Error,
112}
113
114impl From<LogLevel> for log::LevelFilter {
115    fn from(value: LogLevel) -> Self {
116        match value {
117            LogLevel::Trace => log::LevelFilter::Trace,
118            LogLevel::Debug => log::LevelFilter::Debug,
119            LogLevel::Info => log::LevelFilter::Info,
120            LogLevel::Warn => log::LevelFilter::Warn,
121            LogLevel::Error => log::LevelFilter::Error,
122        }
123    }
124}