Skip to main content

greentic_component/
wasm.rs

1use anyhow::{Result, anyhow};
2use wasmparser::Parser;
3use wit_component::{DecodedWasm, metadata};
4use wit_parser::{Resolve, WorldId};
5
6/// Indicates how a world was decoded from a wasm binary.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum WorldSource {
9    /// Metadata was decoded from a core wasm module.
10    Metadata,
11    /// WIT was reconstructed from a fully-fledged component.
12    Component,
13}
14
15/// Resolved world information extracted from a wasm binary.
16pub struct DecodedWorld {
17    pub resolve: Resolve,
18    pub world: WorldId,
19    pub source: WorldSource,
20}
21
22/// Decode a wasm module or component into its WIT world description.
23pub fn decode_world(bytes: &[u8]) -> Result<DecodedWorld> {
24    if Parser::is_component(bytes) {
25        match wit_component::decode(bytes) {
26            Ok(DecodedWasm::Component(resolve, world)) => Ok(DecodedWorld {
27                resolve,
28                world,
29                source: WorldSource::Component,
30            }),
31            Ok(DecodedWasm::WitPackage(_, _)) | Err(_) => match metadata::decode(bytes) {
32                Ok((_maybe_module, bindgen)) => Ok(DecodedWorld {
33                    resolve: bindgen.resolve,
34                    world: bindgen.world,
35                    source: WorldSource::Metadata,
36                }),
37                Err(module_err) => Err(anyhow!(
38                    "failed to decode component and module metadata ({module_err})"
39                )),
40            },
41        }
42    } else {
43        match metadata::decode(bytes) {
44            Ok((_maybe_module, bindgen)) => Ok(DecodedWorld {
45                resolve: bindgen.resolve,
46                world: bindgen.world,
47                source: WorldSource::Metadata,
48            }),
49            Err(module_err) => match wit_component::decode(bytes) {
50                Ok(DecodedWasm::Component(resolve, world)) => Ok(DecodedWorld {
51                    resolve,
52                    world,
53                    source: WorldSource::Component,
54                }),
55                Ok(DecodedWasm::WitPackage(_, _)) => Err(module_err),
56                Err(component_err) => Err(anyhow!(
57                    "failed to decode module metadata ({module_err}) and component ({component_err})"
58                )),
59            },
60        }
61    }
62}