@@ -2,17 +2,21 @@ use std::{io::Write as _, path::PathBuf};
22
33use anyhow:: { Context as _, Result } ;
44use clap:: Args ;
5- use wac_graph:: { CompositionGraph , EncodeOptions } ;
5+ use wac_graph:: { CompositionGraph , EncodeOptions , NodeId , PackageId } ;
66use wac_types:: { Package , SubtypeChecker } ;
77
88/// Plugs the exports of any number of 'plug' components into the imports of a 'socket' component.
99#[ derive( Args ) ]
1010#[ clap( disable_version_flag = true ) ]
1111pub struct PlugCommand {
12- /// The path to the plug component
13- pub plug : PathBuf ,
12+ /// The path to the plug component.
13+ ///
14+ /// More than one plug can be supplied.
15+ #[ clap( long = "plug" , value_name = "PLUG_PATH" , required = true ) ]
16+ pub plugs : Vec < PathBuf > ,
1417
1518 /// The path to the socket component
19+ #[ clap( value_name = "SOCKET_PATH" , required = true ) ]
1620 pub socket : PathBuf ,
1721
1822 /// The path to write the output to.
@@ -28,44 +32,35 @@ impl PlugCommand {
2832 log:: debug!( "executing plug command" ) ;
2933 let mut graph = CompositionGraph :: new ( ) ;
3034
31- let plug = std:: fs:: read ( & self . plug ) . with_context ( || {
32- format ! (
33- "failed to read plug component `{path}`" ,
34- path = self . plug. display( )
35- )
36- } ) ?;
3735 let socket = std:: fs:: read ( & self . socket ) . with_context ( || {
3836 format ! (
3937 "failed to read socket component `{path}`" ,
40- path = self . plug . display( )
38+ path = self . socket . display( )
4139 )
4240 } ) ?;
4341
44- // Register the packages
45- let plug = Package :: from_bytes ( "plug" , None , plug, graph. types_mut ( ) ) ?;
46- let plug = graph. register_package ( plug) ?;
4742 let socket = Package :: from_bytes ( "socket" , None , socket, graph. types_mut ( ) ) ?;
4843 let socket = graph. register_package ( socket) ?;
49-
5044 let socket_instantiation = graph. instantiate ( socket) ;
51- let plug_instantiation = graph. instantiate ( plug) ;
52- let mut plugs = Vec :: new ( ) ;
53- let mut cache = Default :: default ( ) ;
54- let mut checker = SubtypeChecker :: new ( & mut cache) ;
55- for ( name, plug_ty) in & graph. types ( ) [ graph[ plug] . ty ( ) ] . exports {
56- if let Some ( socket_ty) = graph. types ( ) [ graph[ socket] . ty ( ) ] . imports . get ( name) {
57- if let Ok ( _) =
58- checker. is_subtype ( * plug_ty, graph. types ( ) , * socket_ty, graph. types ( ) )
59- {
60- plugs. push ( name. clone ( ) ) ;
61- }
62- }
63- }
64- for plug in plugs {
65- log:: debug!( "using export `{plug}` for plug" ) ;
66- let export = graph. alias_instance_export ( plug_instantiation, & plug) ?;
67- graph. set_instantiation_argument ( socket_instantiation, & plug, export) ?;
45+
46+ // Plug each plug into the socket.
47+ for ( i, plug) in self . plugs . iter ( ) . enumerate ( ) {
48+ let plug = std:: fs:: read ( & plug) . with_context ( || {
49+ format ! (
50+ "failed to read plug component `{path}`" ,
51+ path = plug. display( )
52+ )
53+ } ) ?;
54+ plug_into_socket (
55+ & format ! ( "plug{i}" ) ,
56+ plug,
57+ socket,
58+ socket_instantiation,
59+ & mut graph,
60+ ) ?;
6861 }
62+
63+ // Export all exports from the socket component.
6964 for name in graph. types ( ) [ graph[ socket] . ty ( ) ]
7065 . exports
7166 . keys ( )
@@ -93,3 +88,34 @@ impl PlugCommand {
9388 Ok ( ( ) )
9489 }
9590}
91+
92+ /// Take the exports of the plug component and plug them into the socket component.
93+ fn plug_into_socket (
94+ name : & str ,
95+ plug : Vec < u8 > ,
96+ socket : PackageId ,
97+ socket_instantiation : NodeId ,
98+ graph : & mut CompositionGraph ,
99+ ) -> Result < ( ) , anyhow:: Error > {
100+ let plug = Package :: from_bytes ( name, None , plug, graph. types_mut ( ) ) ?;
101+ let plug = graph. register_package ( plug) ?;
102+ let plug_instantiation = graph. instantiate ( plug) ;
103+
104+ let mut plugs = Vec :: new ( ) ;
105+ let mut cache = Default :: default ( ) ;
106+ let mut checker = SubtypeChecker :: new ( & mut cache) ;
107+ for ( name, plug_ty) in & graph. types ( ) [ graph[ plug] . ty ( ) ] . exports {
108+ if let Some ( socket_ty) = graph. types ( ) [ graph[ socket] . ty ( ) ] . imports . get ( name) {
109+ if let Ok ( _) = checker. is_subtype ( * plug_ty, graph. types ( ) , * socket_ty, graph. types ( ) ) {
110+ plugs. push ( name. clone ( ) ) ;
111+ }
112+ }
113+ }
114+
115+ for plug in plugs {
116+ log:: debug!( "using export `{plug}` for plug" ) ;
117+ let export = graph. alias_instance_export ( plug_instantiation, & plug) ?;
118+ graph. set_instantiation_argument ( socket_instantiation, & plug, export) ?;
119+ }
120+ Ok ( ( ) )
121+ }
0 commit comments