Skip to content

Commit f2893ca

Browse files
committed
Add implements clause support to wac
Support the component model's implements name form, which allows importing/exporting the same interface multiple times under different plain-name labels (e.g., primary/backup stores).
1 parent 30c8a73 commit f2893ca

10 files changed

Lines changed: 285 additions & 94 deletions

File tree

Cargo.lock

Lines changed: 40 additions & 45 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ wac-parser = { path = "crates/wac-parser", version = "0.10.1", default-features
6363
wac-resolver = { path = "crates/wac-resolver", version = "0.10.1", default-features = false }
6464
wac-graph = { path = "crates/wac-graph", version = "0.10.1" }
6565
wac-types = { path = "crates/wac-types", version = "0.10.1" }
66-
wit-parser = "0.247.0"
67-
wasmparser = "0.247.0"
68-
wit-component = "0.247.0"
69-
wasm-encoder = "0.247.0"
70-
wasmprinter = "0.247.0"
71-
wasm-metadata = "0.247.0"
72-
wat = "1.245.1"
66+
wit-parser = "0.252.0"
67+
wasmparser = "0.252.0"
68+
wit-component = "0.252.0"
69+
wasm-encoder = "0.252.0"
70+
wasmprinter = "0.252.0"
71+
wasm-metadata = "0.252.0"
72+
wat = "1.252.0"
7373
anyhow = "1.0.81"
7474
clap = { version = "4.5.4", features = ["derive"] }
7575
semver = { version = "1.0.22", features = ["serde"] }

crates/wac-graph/src/encoding.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,36 @@
11
use crate::PackageId;
22
use indexmap::IndexMap;
33
use petgraph::graph::NodeIndex;
4+
use std::borrow::Cow;
45
use std::collections::HashMap;
56
use wac_types::{
67
CoreExtern, DefinedType, DefinedTypeId, Enum, Flags, FuncTypeId, InterfaceId, ItemKind,
78
ModuleTypeId, PrimitiveType, Record, ResourceId, Type, Types, UsedType, ValueType, Variant,
89
WorldId,
910
};
1011
use wasm_encoder::{
11-
Alias, ComponentBuilder, ComponentCoreTypeEncoder, ComponentExportKind,
12+
Alias, ComponentBuilder, ComponentCoreTypeEncoder, ComponentExportKind, ComponentExternName,
1213
ComponentOuterAliasKind, ComponentType, ComponentTypeEncoder, ComponentTypeRef,
1314
ComponentValType, EntityType, GlobalType, InstanceType, MemoryType, ModuleType, TableType,
1415
TagKind, TagType, TypeBounds,
1516
};
17+
use wasmparser::names::{ComponentName, ComponentNameKind};
18+
19+
/// Returns the `(implements "I")` interface id for an instance import, if the
20+
/// import name is a plain-name label rather than an interface name.
21+
///
22+
/// A component model `(implements "I")` import is an instance whose extern name
23+
/// is a plain-name label (e.g. `primary`) rather than an interface name, while
24+
/// the interface it implements has its own id (e.g. `foo:bar/iface`). A regular
25+
/// interface import instead uses the interface name itself as its extern name.
26+
pub(crate) fn implements_of<'a>(types: &'a Types, name: &str, id: InterfaceId) -> Option<&'a str> {
27+
types[id].id.as_deref().filter(|_| {
28+
matches!(
29+
ComponentName::new(name, 0).as_ref().map(|n| n.kind()),
30+
Ok(ComponentNameKind::Label(_))
31+
)
32+
})
33+
}
1634

1735
/// A type used to abstract the API differences between a component builder,
1836
/// component type, and instance type from `wasm-encoder`.
@@ -65,7 +83,8 @@ impl Encodable {
6583
}
6684
}
6785

68-
fn import_type(&mut self, name: &str, ty: ComponentTypeRef) {
86+
fn import_type<'a>(&mut self, name: impl Into<ComponentExternName<'a>>, ty: ComponentTypeRef) {
87+
let name = name.into();
6988
match self {
7089
Encodable::Component(t) => {
7190
t.import(name, ty);
@@ -730,13 +749,22 @@ impl<'a> TypeEncoder<'a> {
730749
}
731750
ItemKind::Instance(id) => {
732751
let import_index = state.current.encodable.instance_count();
752+
let implements = implements_of(self.0, name, id);
753+
let extern_name = ComponentExternName {
754+
name: Cow::Borrowed(name),
755+
implements: implements.map(Cow::Borrowed),
756+
};
733757
state
734758
.current
735759
.encodable
736-
.import_type(name, ComponentTypeRef::Instance(index));
737-
if let Some(iid) = &self.0[id].id {
738-
log::debug!("instance index {import_index} ({iid}) is available for aliasing");
739-
state.current.instances.insert(iid.clone(), import_index);
760+
.import_type(extern_name, ComponentTypeRef::Instance(index));
761+
if implements.is_none() {
762+
if let Some(iid) = &self.0[id].id {
763+
log::debug!(
764+
"instance index {import_index} ({iid}) is available for aliasing"
765+
);
766+
state.current.instances.insert(iid.clone(), import_index);
767+
}
740768
}
741769
}
742770
_ => panic!("expected only types, functions, and instance types"),

0 commit comments

Comments
 (0)