Skip to content

Commit d38fd96

Browse files
committed
Allow multiple plugs
Signed-off-by: Ryan Levick <ryan.levick@fermyon.com>
1 parent 557a430 commit d38fd96

1 file changed

Lines changed: 57 additions & 31 deletions

File tree

src/commands/plug.rs

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,21 @@ use std::{io::Write as _, path::PathBuf};
22

33
use anyhow::{Context as _, Result};
44
use clap::Args;
5-
use wac_graph::{CompositionGraph, EncodeOptions};
5+
use wac_graph::{CompositionGraph, EncodeOptions, NodeId, PackageId};
66
use 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)]
1111
pub 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

Comments
 (0)