Repository: bytecodealliance/wasm-tools
Pull request #2074 (2025-02-26 14:20:13)

[wasm-metadata] change the print ordering
Nothing too fancy here, this changes the print ordering of the `wasm-metadata` table to print the "kind" and "range" together at the start, and "language" as the first item of the producers section. I was looking at the output in https://github.com/bytecodealliance/cargo-component/pull/372 last week, and felt like the fields would benefit from a slight reordering.

I'm still hopeful that https://github.com/Nukesor/comfy-table/issues/160 will eventually be implemented, enabling us to lift the `name`, `kind`, and `range` fields into a separate title bar. But until then I figured it would be good to group them together at the start of the table. With `range` before `name`, so that if fields like `description`, `license`, and so on exist they are all grouped together.

Thanks!

## Example 

```text
╭──────────────┬─────────────────────────╮
│ KIND         ┆ VALUE                   │
╞══════════════╪═════════════════════════╡
│ kind         ┆ component               │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ range        ┆ 0x0..0x2c9f9b           │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ name         ┆ <unknown>               │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-component [0.216.0] │
╰──────────────┴─────────────────────────╯
╭──────────────┬───────────────────────────────────────────────────────────────╮
│ KIND         ┆ VALUE                                                         │
╞══════════════╪═══════════════════════════════════════════════════════════════╡
│ kind         ┆ module                                                        │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ range        ┆ 0x117c..0x2c5813                                              │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ name         ┆ rust_wasi_hello.wasm                                          │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ language     ┆ Rust                                                          │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ language     ┆ C11                                                           │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ rustc [1.82.0 (f6e511eec 2024-10-15)]                         │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ clang [18.1.2-wasi-sdk (https://github.com/llvm/llvm-project  │
│              ┆ 26a1d6601d727a96f4301d0d8647b5a42760ae0c)]                    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-component [0.20.1]                                        │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-bindgen-rust [0.33.0]                                     │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-bindgen-c [0.17.0]                                        │
╰──────────────┴───────────────────────────────────────────────────────────────╯
```


Patch:
diff --git a/src/bin/wasm-tools/metadata.rs b/src/bin/wasm-tools/metadata.rs
index cfa83536..364b902d 100644
--- a/src/bin/wasm-tools/metadata.rs
+++ b/src/bin/wasm-tools/metadata.rs
@@ -54,7 +54,7 @@ impl ShowOpts {
         if self.json {
             write!(output, "{}", serde_json::to_string(&payload)?)?;
         } else {
-            fmt_payload(&payload, &mut output)?;
+            write_table(&payload, &mut output)?;
         }
         Ok(())
     }
@@ -89,7 +89,9 @@ impl AddOpts {
     }
 }
 
-fn fmt_payload(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
+/// Write a table containing a wasm binary's metadata to a writer
+fn write_table(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
+    // Prepare a table and get the individual metadata
     let mut table = Table::new();
     table
         .load_preset(UTF8_FULL)
@@ -110,43 +112,60 @@ fn fmt_payload(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
         version,
     } = payload.metadata();
 
-    // Print the basic information
+    // Add the basic information to the table first
     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),
     ]);
+    let name = name.as_deref().unwrap_or("<unknown>");
+    table.add_row(vec!["name", &name]);
 
-    // Print the OCI annotations
+    // Add the OCI annotations to the table
     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(authors) = authors {
         table.add_row(vec!["authors", &authors.to_string()]);
     }
+    if let Some(version) = version {
+        table.add_row(vec!["version", &version.to_string()]);
+    }
+    if let Some(revision) = revision {
+        table.add_row(vec!["revision", &revision.to_string()]);
+    }
+    if let Some(licenses) = licenses {
+        table.add_row(vec!["licenses", &licenses.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(revision) = revision {
-        table.add_row(vec!["revision", &revision.to_string()]);
-    }
-    if let Some(version) = version {
-        table.add_row(vec!["version", &version.to_string()]);
-    }
 
+    // Add the producer section to the table
     if let Some(producers) = producers {
+        // Ensure the "language" fields are listed first
+        let mut producers = producers
+            .iter()
+            .map(|(n, p)| (n.clone(), p))
+            .collect::<Vec<_>>();
+        producers.sort_by(|(a, _), (b, _)| {
+            if a == "language" {
+                std::cmp::Ordering::Less
+            } else if b == "language" {
+                std::cmp::Ordering::Greater
+            } else {
+                a.cmp(b)
+            }
+        });
+
+        // Add the producers to the table
         for (name, pairs) in producers.iter() {
             for (field, version) in pairs.iter() {
                 match version.len() {
@@ -160,9 +179,10 @@ fn fmt_payload(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
     // Write the table to the writer
     writeln!(f, "{table}")?;
 
+    // Recursively print any children
     if let Payload::Component { children, .. } = payload {
         for payload in children {
-            fmt_payload(payload, f)?;
+            write_table(payload, f)?;
         }
     }
 


Test patch:
diff --git a/tests/cli/add-metadata-merge-sections.wat.stdout b/tests/cli/add-metadata-merge-sections.wat.stdout
index 49ed566d..c6491c6f 100644
--- a/tests/cli/add-metadata-merge-sections.wat.stdout
+++ b/tests/cli/add-metadata-merge-sections.wat.stdout
@@ -3,10 +3,10 @@
 ╞══════════╪═══════════╡
 │ kind     ┆ module    │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name     ┆ <unknown> │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range    ┆ 0x0..0x36 │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name     ┆ <unknown> │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ foo [3]   │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ bar [1]   │
diff --git a/tests/cli/add-metadata-overwrite-name.wat.stdout b/tests/cli/add-metadata-overwrite-name.wat.stdout
index 6803d701..3b5e74ed 100644
--- a/tests/cli/add-metadata-overwrite-name.wat.stdout
+++ b/tests/cli/add-metadata-overwrite-name.wat.stdout
@@ -3,7 +3,7 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ foo       │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x15 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ foo       │
 ╰───────┴───────────╯
diff --git a/tests/cli/add-metadata.wat.stdout b/tests/cli/add-metadata.wat.stdout
index b83255d9..3e88493c 100644
--- a/tests/cli/add-metadata.wat.stdout
+++ b/tests/cli/add-metadata.wat.stdout
@@ -3,10 +3,10 @@
 ╞══════════════╪════════════╡
 │ kind         ┆ module     │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
-│ name         ┆ foo        │
-├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ range        ┆ 0x0..0x54  │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ name         ┆ foo        │
+├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ language     ┆ bar [1]    │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ processed-by ┆ baz [1]    │
diff --git a/tests/cli/metadata-add-component.wat.stdout b/tests/cli/metadata-add-component.wat.stdout
index 72c06737..f0d29b40 100644
--- a/tests/cli/metadata-add-component.wat.stdout
+++ b/tests/cli/metadata-add-component.wat.stdout
@@ -3,10 +3,10 @@
 ╞══════════╪═══════════╡
 │ kind     ┆ component │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name     ┆ foo       │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range    ┆ 0x0..0x65 │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name     ┆ foo       │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ foo [1]   │
 ╰──────────┴───────────╯
 ╭───────┬───────────╮
@@ -14,7 +14,7 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ <unknown> │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0xa..0x31 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ <unknown> │
 ╰───────┴───────────╯
diff --git a/tests/cli/metadata-component.wat.stdout b/tests/cli/metadata-component.wat.stdout
index d262ff85..5dd1cdb2 100644
--- a/tests/cli/metadata-component.wat.stdout
+++ b/tests/cli/metadata-component.wat.stdout
@@ -3,25 +3,25 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ component │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ my-name   │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x88 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ my-name   │
 ╰───────┴───────────╯
 ╭───────┬───────────╮
 │ KIND  ┆ VALUE     │
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ submodule │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0xa..0x25 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ submodule │
 ╰───────┴───────────╯
 ╭───────┬───────────────────╮
 │ KIND  ┆ VALUE             │
 ╞═══════╪═══════════════════╡
 │ kind  ┆ module            │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ another submodule │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x27..0x4a        │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ another submodule │
 ╰───────┴───────────────────╯
diff --git a/tests/cli/metadata.wat.stdout b/tests/cli/metadata.wat.stdout
index 9dc357ab..4919b01d 100644
--- a/tests/cli/metadata.wat.stdout
+++ b/tests/cli/metadata.wat.stdout
@@ -3,7 +3,7 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ <unknown> │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x8  │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ <unknown> │
 ╰───────┴───────────╯