@@ -5,7 +5,7 @@ use std::path::PathBuf;
55use wasm_encoder:: { Encode , Section } ;
66use wasm_metadata:: Producers ;
77use wit_component:: { ComponentEncoder , DecodedWasm , WitPrinter } ;
8- use wit_parser:: Resolve ;
8+ use wit_parser:: { Resolve , WorldItem } ;
99
1010mod bindings {
1111 use super :: WasmToolsJs ;
@@ -16,8 +16,8 @@ mod bindings {
1616}
1717
1818use bindings:: exports:: local:: wasm_tools:: tools:: {
19- EmbedOpts , EnabledFeatureSet , Guest , ModuleMetaType , ModuleMetadata , ProducersFields ,
20- StringEncoding ,
19+ EmbedOpts , EnabledFeatureSet , Guest , InterfaceMetadata , ModuleMetaType , ModuleMetadata ,
20+ ProducersFields , SemverVersion , StringEncoding , WitMetadata ,
2121} ;
2222
2323struct WasmToolsJs ;
@@ -59,8 +59,6 @@ impl Guest for WasmToolsJs {
5959 let decoded = wit_component:: decode ( & binary)
6060 . map_err ( |e| format ! ( "Failed to decode wit component\n {e:?}" ) ) ?;
6161
62- // let world = decode_world("component", &binary);
63-
6462 let doc = match & decoded {
6563 DecodedWasm :: WitPackage ( _, _) => panic ! ( "Unexpected wit package" ) ,
6664 DecodedWasm :: Component ( resolve, world) => resolve. worlds [ * world] . package . unwrap ( ) ,
@@ -74,6 +72,118 @@ impl Guest for WasmToolsJs {
7472 Ok ( printer. output . to_string ( ) )
7573 }
7674
75+ fn component_wit_metadata_for_world (
76+ binary : Vec < u8 > ,
77+ maybe_world_name : Option < String > ,
78+ ) -> Result < WitMetadata , String > {
79+ let decoded = wit_component:: decode ( & binary)
80+ . map_err ( |e| format ! ( "Failed to decode wit component\n {e:?}" ) ) ?;
81+
82+ let ( resolve, world_id) = match & decoded {
83+ DecodedWasm :: WitPackage ( _, _) => panic ! ( "Unexpected wit package" ) ,
84+ DecodedWasm :: Component ( resolve, world) => ( resolve, world) ,
85+ } ;
86+
87+ let world = match maybe_world_name {
88+ Some ( world_name) => {
89+ resolve
90+ . worlds
91+ . iter ( )
92+ . find ( |w| w. 1 . name == world_name)
93+ . ok_or_else ( || String :: from ( "failed to find wold with given name" ) ) ?
94+ . 1
95+ }
96+ None => resolve
97+ . worlds
98+ . get ( * world_id)
99+ . ok_or_else ( || String :: from ( "failed to find package id" ) ) ?,
100+ } ;
101+
102+ let mut imports = Vec :: new ( ) ;
103+ for ( import_key, import_item) in world. imports . iter ( ) {
104+ let WorldItem :: Interface { id, .. } = import_item else {
105+ continue ;
106+ } ;
107+ let iface = resolve
108+ . interfaces
109+ . get ( * id)
110+ . ok_or_else ( || format ! ( "failed to find interface with id [{id:?}]" ) ) ?;
111+ let iface_name = iface
112+ . name
113+ . clone ( )
114+ . ok_or_else ( || format ! ( "missing iface name for world key [{import_key:?}]" ) ) ?;
115+ let pkg_id = iface
116+ . package
117+ . ok_or_else ( || format ! ( "no package for interface [{:?}]" , iface. name) ) ?;
118+ let pkg = resolve
119+ . packages
120+ . get ( pkg_id)
121+ . ok_or_else ( || format ! ( "no package with ID [{pkg_id:?}]" ) ) ?;
122+
123+ imports. push ( InterfaceMetadata {
124+ namespace : pkg. name . namespace . clone ( ) ,
125+ package : pkg. name . name . clone ( ) ,
126+ interface : iface_name. clone ( ) ,
127+ version : pkg. name . version . as_ref ( ) . map ( |v| SemverVersion {
128+ major : v. major ,
129+ minor : v. minor ,
130+ patch : v. patch ,
131+ pre : match v. pre . as_str ( ) {
132+ "" => None ,
133+ v => Some ( v. into ( ) ) ,
134+ } ,
135+ build : match v. build . as_str ( ) {
136+ "" => None ,
137+ v => Some ( v. into ( ) ) ,
138+ } ,
139+ } ) ,
140+ } ) ;
141+ }
142+
143+ let mut exports = Vec :: new ( ) ;
144+ for ( export_key, export_item) in world. exports . iter ( ) {
145+ let WorldItem :: Interface { id, .. } = export_item else {
146+ continue ;
147+ } ;
148+ let iface = resolve
149+ . interfaces
150+ . get ( * id)
151+ . ok_or_else ( || format ! ( "failed to find interface with id [{id:?}]" ) ) ?;
152+ let iface_name = iface
153+ . name
154+ . clone ( )
155+ . ok_or_else ( || format ! ( "missing iface name for world key [{export_key:?}]" ) ) ?;
156+ let pkg_id = iface
157+ . package
158+ . ok_or_else ( || format ! ( "no package for interface [{:?}]" , iface. name) ) ?;
159+ let pkg = resolve
160+ . packages
161+ . get ( pkg_id)
162+ . ok_or_else ( || format ! ( "no package with ID [{pkg_id:?}]" ) ) ?;
163+
164+ exports. push ( InterfaceMetadata {
165+ namespace : pkg. name . namespace . clone ( ) ,
166+ package : pkg. name . name . clone ( ) ,
167+ interface : iface_name. clone ( ) ,
168+ version : pkg. name . version . as_ref ( ) . map ( |v| SemverVersion {
169+ major : v. major ,
170+ minor : v. minor ,
171+ patch : v. patch ,
172+ pre : match v. pre . as_str ( ) {
173+ "" => None ,
174+ v => Some ( v. into ( ) ) ,
175+ } ,
176+ build : match v. build . as_str ( ) {
177+ "" => None ,
178+ v => Some ( v. into ( ) ) ,
179+ } ,
180+ } ) ,
181+ } ) ;
182+ }
183+
184+ Ok ( WitMetadata { imports, exports } )
185+ }
186+
77187 fn component_embed ( embed_opts : EmbedOpts ) -> Result < Vec < u8 > , String > {
78188 let binary = & embed_opts. binary ;
79189
0 commit comments