@@ -6,6 +6,30 @@ use std::mem;
66use wasm_encoder:: * ;
77use wit_parser:: * ;
88
9+ /// Encodes the given `package` within `resolve` to a binary WebAssembly
10+ /// representation.
11+ ///
12+ /// This function is the root of the implementation of serializing a WIT package
13+ /// into a WebAssembly representation. The wasm representation serves two
14+ /// purposes:
15+ ///
16+ /// * One is to be a binary encoding of a WIT document which is ideally more
17+ /// stable than the WIT textual format itself.
18+ /// * Another is to provide a clear mapping of all WIT features into the
19+ /// component model through use of its binary representation.
20+ ///
21+ /// The `resolve` provided is a set of packages and types and such and the
22+ /// `package` argument is an ID within the world provided. The documents within
23+ /// `package` will all be encoded into the binary returned.
24+ ///
25+ /// The binary returned can be [`decode`d](crate::decode) to recover the WIT
26+ /// package provided.
27+ pub fn encode ( resolve : & Resolve , package : PackageId ) -> Result < Vec < u8 > > {
28+ let mut component = encode_component ( resolve, package) ?;
29+ component. raw_custom_section ( & crate :: base_producers ( ) . raw_custom_section ( ) ) ;
30+ Ok ( component. finish ( ) )
31+ }
32+
933/// Encodes the given `package` within `resolve` to a binary WebAssembly
1034/// representation.
1135///
@@ -41,6 +65,82 @@ pub fn encode_component(resolve: &Resolve, package: PackageId) -> Result<Compone
4165 Ok ( encoder. component )
4266}
4367
68+ /// Encodes a `world` as a component type.
69+ pub fn encode_world ( resolve : & Resolve , world_id : WorldId ) -> Result < ComponentType > {
70+ let mut component = InterfaceEncoder :: new ( resolve) ;
71+ let world = & resolve. worlds [ world_id] ;
72+ log:: trace!( "encoding world {}" , world. name) ;
73+
74+ // This sort is similar in purpose to the sort below in
75+ // `encode_instance`, but different in its sort. The purpose here is
76+ // to ensure that when a document is either printed as WIT or
77+ // encoded as wasm that decoding from those artifacts produces the
78+ // same WIT package. Namely both encoding processes should encode
79+ // things in the same order.
80+ //
81+ // When printing worlds in WIT freestanding function imports are
82+ // printed first, then types. Resource functions are attached to
83+ // types which means that they all come last. Sort all
84+ // resource-related functions here to the back of the `imports` list
85+ // while keeping everything else in front, using a stable sort to
86+ // preserve preexisting ordering.
87+ let mut imports = world. imports . iter ( ) . collect :: < Vec < _ > > ( ) ;
88+ imports. sort_by_key ( |( _name, import) | match import {
89+ WorldItem :: Function ( f) => match f. kind {
90+ FunctionKind :: Freestanding => 0 ,
91+ _ => 1 ,
92+ } ,
93+ _ => 0 ,
94+ } ) ;
95+
96+ // Encode the imports
97+ for ( name, import) in imports {
98+ let name = resolve. name_world_key ( name) ;
99+ log:: trace!( "encoding import {name}" ) ;
100+ let ty = match import {
101+ WorldItem :: Interface { id, .. } => {
102+ component. interface = Some ( * id) ;
103+ let idx = component. encode_instance ( * id) ?;
104+ ComponentTypeRef :: Instance ( idx)
105+ }
106+ WorldItem :: Function ( f) => {
107+ component. interface = None ;
108+ let idx = component. encode_func_type ( resolve, f) ?;
109+ ComponentTypeRef :: Func ( idx)
110+ }
111+ WorldItem :: Type ( t) => {
112+ component. interface = None ;
113+ component. import_types = true ;
114+ component. encode_valtype ( resolve, & Type :: Id ( * t) ) ?;
115+ component. import_types = false ;
116+ continue ;
117+ }
118+ } ;
119+ component. outer . import ( & name, ty) ;
120+ }
121+ // Encode the exports
122+ for ( name, export) in world. exports . iter ( ) {
123+ let name = resolve. name_world_key ( name) ;
124+ log:: trace!( "encoding export {name}" ) ;
125+ let ty = match export {
126+ WorldItem :: Interface { id, .. } => {
127+ component. interface = Some ( * id) ;
128+ let idx = component. encode_instance ( * id) ?;
129+ ComponentTypeRef :: Instance ( idx)
130+ }
131+ WorldItem :: Function ( f) => {
132+ component. interface = None ;
133+ let idx = component. encode_func_type ( resolve, f) ?;
134+ ComponentTypeRef :: Func ( idx)
135+ }
136+ WorldItem :: Type ( _) => unreachable ! ( ) ,
137+ } ;
138+ component. outer . export ( & name, ty) ;
139+ }
140+
141+ Ok ( component. outer )
142+ }
143+
44144struct Encoder < ' a > {
45145 component : ComponentBuilder ,
46146 resolve : & ' a Resolve ,
@@ -49,6 +149,34 @@ struct Encoder<'a> {
49149
50150impl Encoder < ' _ > {
51151 fn run ( & mut self ) -> Result < ( ) > {
152+ // Encode all interfaces as component types and then export them.
153+ for ( name, & id) in self . resolve . packages [ self . package ] . interfaces . iter ( ) {
154+ let component_ty = self . encode_interface ( id) ?;
155+ let ty = self . component . type_component ( & component_ty) ;
156+ self . component
157+ . export ( name. as_ref ( ) , ComponentExportKind :: Type , ty, None ) ;
158+ }
159+
160+ // For each `world` encode it directly as a component and then create a
161+ // wrapper component that exports that component.
162+ for ( name, & world) in self . resolve . packages [ self . package ] . worlds . iter ( ) {
163+ let component_ty = encode_world ( self . resolve , world) ?;
164+
165+ let world = & self . resolve . worlds [ world] ;
166+ let mut wrapper = ComponentType :: new ( ) ;
167+ wrapper. ty ( ) . component ( & component_ty) ;
168+ let pkg = & self . resolve . packages [ world. package . unwrap ( ) ] ;
169+ wrapper. export ( & pkg. name . interface_id ( name) , ComponentTypeRef :: Component ( 0 ) ) ;
170+
171+ let ty = self . component . type_component ( & wrapper) ;
172+ self . component
173+ . export ( name. as_ref ( ) , ComponentExportKind :: Type , ty, None ) ;
174+ }
175+
176+ Ok ( ( ) )
177+ }
178+
179+ fn encode_interface ( & mut self , id : InterfaceId ) -> Result < ComponentType > {
52180 // Build a set of interfaces reachable from this document, including the
53181 // interfaces in the document itself. This is used to import instances
54182 // into the component type we're encoding. Note that entire interfaces
@@ -58,9 +186,7 @@ impl Encoder<'_> {
58186 // notably on the order that types are defined in to assist with
59187 // roundtripping.
60188 let mut interfaces = IndexSet :: new ( ) ;
61- for ( _, id) in self . resolve . packages [ self . package ] . interfaces . iter ( ) {
62- self . add_live_interfaces ( & mut interfaces, * id) ;
63- }
189+ self . add_live_interfaces ( & mut interfaces, id) ;
64190
65191 // Seed the set of used names with all exported interfaces to ensure
66192 // that imported interfaces choose different names as the import names
@@ -73,23 +199,15 @@ impl Encoder<'_> {
73199 assert ! ( first) ;
74200 }
75201 }
76- for ( name, _world) in self . resolve . packages [ self . package ] . worlds . iter ( ) {
77- let first = used_names. insert ( name. clone ( ) ) ;
78- assert ! ( first) ;
79- }
80202
81- // Encode all interfaces, foreign and local, into this component type.
82- // Local interfaces get their functions defined as well and are
83- // exported. Foreign interfaces are imported and only have their types
84- // encoded.
85203 let mut encoder = InterfaceEncoder :: new ( self . resolve ) ;
86204 for interface in interfaces {
87205 encoder. interface = Some ( interface) ;
88206 let iface = & self . resolve . interfaces [ interface] ;
89207 let name = self . resolve . id_of ( interface) . unwrap ( ) ;
90- log:: trace!( "encoding interface {name}" ) ;
91- if iface. package == Some ( self . package ) {
208+ if interface == id {
92209 let idx = encoder. encode_instance ( interface) ?;
210+ log:: trace!( "exporting self as {idx}" ) ;
93211 encoder. outer . export ( & name, ComponentTypeRef :: Instance ( idx) ) ;
94212 } else {
95213 encoder. push_instance ( ) ;
@@ -104,21 +222,10 @@ impl Encoder<'_> {
104222 encoder. outer . import ( & name, ComponentTypeRef :: Instance ( idx) ) ;
105223 }
106224 }
107- encoder. interface = None ;
108225
109- for ( name, world) in self . resolve . packages [ self . package ] . worlds . iter ( ) {
110- let component_ty = encode_world ( self . resolve , * world) ?;
111- let idx = encoder. outer . type_count ( ) ;
112- encoder. outer . ty ( ) . component ( & component_ty) ;
113- let id = self . resolve . packages [ self . package ] . name . interface_id ( name) ;
114- encoder. outer . export ( & id, ComponentTypeRef :: Component ( idx) ) ;
115- }
226+ encoder. interface = None ;
116227
117- let ty = self . component . type_component ( & encoder. outer ) ;
118- let id = self . resolve . packages [ self . package ] . name . interface_id ( "wit" ) ;
119- self . component
120- . export ( & id, ComponentExportKind :: Type , ty, None ) ;
121- Ok ( ( ) )
228+ Ok ( encoder. outer )
122229 }
123230
124231 /// Recursively add all live interfaces reachable from `id` into the
@@ -317,79 +424,3 @@ impl<'a> ValtypeEncoder<'a> for InterfaceEncoder<'a> {
317424 & mut self . func_type_map
318425 }
319426}
320-
321- /// Encodes a `world` as a component type.
322- pub fn encode_world ( resolve : & Resolve , world_id : WorldId ) -> Result < ComponentType > {
323- let mut component = InterfaceEncoder :: new ( resolve) ;
324- let world = & resolve. worlds [ world_id] ;
325- log:: trace!( "encoding world {}" , world. name) ;
326-
327- // This sort is similar in purpose to the sort below in
328- // `encode_instance`, but different in its sort. The purpose here is
329- // to ensure that when a document is either printed as WIT or
330- // encoded as wasm that decoding from those artifacts produces the
331- // same WIT package. Namely both encoding processes should encode
332- // things in the same order.
333- //
334- // When printing worlds in WIT freestanding function imports are
335- // printed first, then types. Resource functions are attached to
336- // types which means that they all come last. Sort all
337- // resource-related functions here to the back of the `imports` list
338- // while keeping everything else in front, using a stable sort to
339- // preserve preexisting ordering.
340- let mut imports = world. imports . iter ( ) . collect :: < Vec < _ > > ( ) ;
341- imports. sort_by_key ( |( _name, import) | match import {
342- WorldItem :: Function ( f) => match f. kind {
343- FunctionKind :: Freestanding => 0 ,
344- _ => 1 ,
345- } ,
346- _ => 0 ,
347- } ) ;
348-
349- // Encode the imports
350- for ( name, import) in imports {
351- let name = resolve. name_world_key ( name) ;
352- log:: trace!( "encoding import {name}" ) ;
353- let ty = match import {
354- WorldItem :: Interface { id, .. } => {
355- component. interface = Some ( * id) ;
356- let idx = component. encode_instance ( * id) ?;
357- ComponentTypeRef :: Instance ( idx)
358- }
359- WorldItem :: Function ( f) => {
360- component. interface = None ;
361- let idx = component. encode_func_type ( resolve, f) ?;
362- ComponentTypeRef :: Func ( idx)
363- }
364- WorldItem :: Type ( t) => {
365- component. interface = None ;
366- component. import_types = true ;
367- component. encode_valtype ( resolve, & Type :: Id ( * t) ) ?;
368- component. import_types = false ;
369- continue ;
370- }
371- } ;
372- component. outer . import ( & name, ty) ;
373- }
374- // Encode the exports
375- for ( name, export) in world. exports . iter ( ) {
376- let name = resolve. name_world_key ( name) ;
377- log:: trace!( "encoding export {name}" ) ;
378- let ty = match export {
379- WorldItem :: Interface { id, .. } => {
380- component. interface = Some ( * id) ;
381- let idx = component. encode_instance ( * id) ?;
382- ComponentTypeRef :: Instance ( idx)
383- }
384- WorldItem :: Function ( f) => {
385- component. interface = None ;
386- let idx = component. encode_func_type ( resolve, f) ?;
387- ComponentTypeRef :: Func ( idx)
388- }
389- WorldItem :: Type ( _) => unreachable ! ( ) ,
390- } ;
391- component. outer . export ( & name, ty) ;
392- }
393-
394- Ok ( component. outer )
395- }
0 commit comments