Skip to content

Commit

Permalink
[wasm-metadata] pretty-print cli output (#1946)
Browse files Browse the repository at this point in the history
* [wasm-metadata] pretty-print cli output

* disable crossterm dep

* rebase on main

* update snapshot tests

* Move print logic to cli tools
  • Loading branch information
yoshuawuyts authored Dec 10, 2024
1 parent 1bcecbc commit de978e1
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 93 deletions.
37 changes: 37 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ anyhow = "1.0.58"
arbitrary = "1.1.0"
clap = { version = "4.0.0", features = ["derive"] }
clap_complete = "4.4.7"
comfy-table = { version = "7.1.3", default-features = false }
criterion = { version = "0.5.1", default-features = false }
env_logger = "0.11"
indexmap = { version = "2.0.0", default-features = false }
Expand Down Expand Up @@ -122,6 +123,7 @@ env_logger = { workspace = true }
log = { workspace = true }
clap = { workspace = true, features = ['wrap_help'] }
clap_complete = { workspace = true, optional = true }
comfy-table = { workspace = true }
tempfile = "3.2.0"
wat = { workspace = true, features = ['dwarf', 'component-model'] }
termcolor = { workspace = true }
Expand Down
45 changes: 0 additions & 45 deletions crates/wasm-metadata/src/payload.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::fmt::{self, Display};
use std::ops::Range;

use anyhow::Result;
Expand Down Expand Up @@ -181,48 +180,4 @@ impl Payload {
Self::Component { children, .. } => children.push(child),
}
}

fn display(&self, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
let spaces = std::iter::repeat(" ").take(indent).collect::<String>();
match self {
Self::Module(Metadata {
name, producers, ..
}) => {
if let Some(name) = name {
writeln!(f, "{spaces}module {name}:")?;
} else {
writeln!(f, "{spaces}module:")?;
}
if let Some(producers) = producers {
producers.display(f, indent + 4)?;
}
Ok(())
}
Self::Component {
children,
metadata: Metadata {
name, producers, ..
},
} => {
if let Some(name) = name {
writeln!(f, "{spaces}component {name}:")?;
} else {
writeln!(f, "{spaces}component:")?;
}
if let Some(producers) = producers {
producers.display(f, indent + 4)?;
}
for c in children {
c.display(f, indent + 4)?;
}
Ok(())
}
}
}
}

impl Display for Payload {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.display(f, 0)
}
}
22 changes: 0 additions & 22 deletions crates/wasm-metadata/src/producers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use anyhow::Result;
use indexmap::{map::Entry, IndexMap};
use serde_derive::Serialize;
use std::fmt;
use wasm_encoder::Encode;
use wasmparser::{BinaryReader, KnownCustom, Parser, ProducersSectionReader};

Expand Down Expand Up @@ -150,27 +149,6 @@ impl Producers {
pub fn add_to_wasm(&self, input: &[u8]) -> Result<Vec<u8>> {
rewrite_wasm(&None, self, &None, &None, &None, &None, &None, input)
}

pub(crate) fn display(&self, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
let indent = std::iter::repeat(" ").take(indent).collect::<String>();
for (fieldname, fieldvalues) in self.0.iter() {
writeln!(f, "{indent}{fieldname}:")?;
for (name, version) in fieldvalues {
if version.is_empty() {
writeln!(f, "{indent} {name}")?;
} else {
writeln!(f, "{indent} {name}: {version}")?;
}
}
}
Ok(())
}
}

impl fmt::Display for Producers {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.display(f, 0)
}
}

/// Contents of a producers field
Expand Down
86 changes: 82 additions & 4 deletions src/bin/wasm-tools/metadata.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use anyhow::Result;
use std::io::Write;

use anyhow::Result;
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
use comfy_table::presets::UTF8_FULL;
use comfy_table::{ContentArrangement, Table};
use termcolor::WriteColor;
use wasm_metadata::{Metadata, Payload};

/// Manipulate metadata (module name, producers) to a WebAssembly file.
#[derive(clap::Parser)]
pub enum Opts {
Expand Down Expand Up @@ -44,11 +50,11 @@ impl ShowOpts {
let input = self.io.parse_input_wasm()?;
let mut output = self.io.output_writer()?;

let metadata = wasm_metadata::Payload::from_binary(&input)?;
let payload = wasm_metadata::Payload::from_binary(&input)?;
if self.json {
write!(output, "{}", serde_json::to_string(&metadata)?)?;
write!(output, "{}", serde_json::to_string(&payload)?)?;
} else {
write!(output, "{metadata}")?;
fmt_payload(&payload, &mut output)?;
}
Ok(())
}
Expand Down Expand Up @@ -82,3 +88,75 @@ impl AddOpts {
Ok(())
}
}

fn fmt_payload(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
let mut table = Table::new();
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS)
.set_content_arrangement(ContentArrangement::Dynamic)
.set_width(80)
.set_header(vec!["KIND", "VALUE"]);
let Metadata {
name,
author,
description,
producers,
licenses,
source,
homepage,
range,
} = payload.metadata();

// Print the basic information
let kind = match payload {
Payload::Component { .. } => "component",
Payload::Module(_) => "module",
};
table.add_row(vec!["kind", &kind]);
let name = name.as_deref().unwrap_or("<unknown>");
table.add_row(vec!["name", &name]);
table.add_row(vec![
"range",
&format!("0x{:x}..0x{:x}", range.start, range.end),
]);

// Print the OCI annotations
if let Some(description) = description {
table.add_row(vec!["description", &description.to_string()]);
}
if let Some(licenses) = licenses {
table.add_row(vec!["licenses", &licenses.to_string()]);
}
if let Some(author) = author {
table.add_row(vec!["author", &author.to_string()]);
}
if let Some(source) = source {
table.add_row(vec!["source", &source.to_string()]);
}
if let Some(homepage) = homepage {
table.add_row(vec!["homepage", &homepage.to_string()]);
}

if let Some(producers) = producers {
for (name, pairs) in producers.iter() {
for (field, version) in pairs.iter() {
match version.len() {
0 => table.add_row(vec![name, &format!("{field}")]),
_ => table.add_row(vec![name, &format!("{field} [{version}]")]),
};
}
}
}

// Write the table to the writer
writeln!(f, "{table}")?;

if let Payload::Component { children, .. } = payload {
for payload in children {
fmt_payload(payload, f)?;
}
}

Ok(())
}
21 changes: 15 additions & 6 deletions tests/cli/add-metadata-merge-sections.wat.stdout
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
module:
language:
foo: 3
bar: 1
sdk:
foo: 2
╭──────────┬───────────╮
│ KIND ┆ VALUE │
╞══════════╪═══════════╡
│ kind ┆ module │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ <unknown> │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0x0..0x36 │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ language ┆ foo [3] │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ language ┆ bar [1] │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ sdk ┆ foo [2] │
╰──────────┴───────────╯
10 changes: 9 additions & 1 deletion tests/cli/add-metadata-overwrite-name.wat.stdout
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
module foo:
╭───────┬───────────╮
│ KIND ┆ VALUE │
╞═══════╪═══════════╡
│ kind ┆ module │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ foo │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0x0..0x15 │
╰───────┴───────────╯
22 changes: 15 additions & 7 deletions tests/cli/add-metadata.wat.stdout
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
module foo:
language:
bar: 1
processed-by:
baz: 1
sdk:
my-sdk: 2
╭──────────────┬────────────╮
│ KIND ┆ VALUE │
╞══════════════╪════════════╡
│ kind ┆ module │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ foo │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0x0..0x54 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ language ┆ bar [1] │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ baz [1] │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ sdk ┆ my-sdk [2] │
╰──────────────┴────────────╯
24 changes: 20 additions & 4 deletions tests/cli/metadata-add-component.wat.stdout
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
component foo:
language:
foo: 1
module:
╭──────────┬───────────╮
│ KIND ┆ VALUE │
╞══════════╪═══════════╡
│ kind ┆ component │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ foo │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0x0..0x65 │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ language ┆ foo [1] │
╰──────────┴───────────╯
╭───────┬───────────╮
│ KIND ┆ VALUE │
╞═══════╪═══════════╡
│ kind ┆ module │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ <unknown> │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0xa..0x31 │
╰───────┴───────────╯
30 changes: 27 additions & 3 deletions tests/cli/metadata-component.wat.stdout
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
component my-name:
module submodule:
module another submodule:
╭───────┬───────────╮
│ KIND ┆ VALUE │
╞═══════╪═══════════╡
│ kind ┆ component │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ my-name │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0x0..0x88 │
╰───────┴───────────╯
╭───────┬───────────╮
│ KIND ┆ VALUE │
╞═══════╪═══════════╡
│ kind ┆ module │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ submodule │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0xa..0x25 │
╰───────┴───────────╯
╭───────┬───────────────────╮
│ KIND ┆ VALUE │
╞═══════╪═══════════════════╡
│ kind ┆ module │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ name ┆ another submodule │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ range ┆ 0x27..0x4a │
╰───────┴───────────────────╯
Loading

0 comments on commit de978e1

Please sign in to comment.