Skip to content

Commit a265ec1

Browse files
author
Guy Bedford
authored
feat: support basic use syntax in interfaces and worlds (#1659)
* feat: support basic use syntax in interfaces and worlds * fixup
1 parent a2635eb commit a265ec1

File tree

5 files changed

+109
-2
lines changed

5 files changed

+109
-2
lines changed

crates/wit-encoder/src/interface.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt;
22

3-
use crate::{Docs, Ident, Render, RenderOpts, StandaloneFunc, TypeDef};
3+
use crate::{Docs, Ident, Render, RenderOpts, StandaloneFunc, TypeDef, Use};
44

55
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66
pub struct Interface {
@@ -34,6 +34,11 @@ impl Interface {
3434
self.items.push(InterfaceItem::Function(function));
3535
}
3636

37+
/// Add a `Use` to the interface
38+
pub fn use_(&mut self, use_: Use) {
39+
self.items.push(InterfaceItem::Use(use_));
40+
}
41+
3742
pub fn items(&self) -> &[InterfaceItem] {
3843
&self.items
3944
}
@@ -51,6 +56,7 @@ impl Interface {
5156
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5257
pub enum InterfaceItem {
5358
TypeDef(TypeDef),
59+
Use(Use),
5460
Function(StandaloneFunc),
5561
}
5662

@@ -73,6 +79,9 @@ impl Render for InterfaceItems {
7379
}
7480
write!(f, ";\n")?;
7581
}
82+
InterfaceItem::Use(use_) => {
83+
use_.render(f, opts)?;
84+
}
7685
}
7786
}
7887
Ok(())

crates/wit-encoder/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod resource;
1717
mod result;
1818
mod tuple;
1919
mod ty;
20+
mod use_;
2021
mod variant;
2122
mod world;
2223

@@ -34,5 +35,6 @@ pub use resource::*;
3435
pub use result::*;
3536
pub use tuple::*;
3637
pub use ty::*;
38+
pub use use_::*;
3739
pub use variant::*;
3840
pub use world::*;

crates/wit-encoder/src/use_.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use std::fmt;
2+
3+
use crate::{Ident, Render};
4+
5+
/// Enable the union of a world with another world
6+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7+
pub struct Use {
8+
target: Ident,
9+
use_names_list: Vec<(String, Option<String>)>,
10+
}
11+
12+
impl Use {
13+
pub fn new(use_target: impl Into<Ident>) -> Self {
14+
Self {
15+
target: use_target.into(),
16+
use_names_list: vec![],
17+
}
18+
}
19+
20+
pub fn item(&mut self, id: &str, alias: Option<&str>) {
21+
self.use_names_list
22+
.push((id.to_string(), alias.map(|s| s.to_string())));
23+
}
24+
}
25+
26+
impl Render for Use {
27+
fn render(&self, f: &mut fmt::Formatter<'_>, opts: &crate::RenderOpts) -> fmt::Result {
28+
let len = self.use_names_list.len();
29+
30+
write!(f, "{}use {}.{{ ", opts.spaces(), self.target)?;
31+
for (i, (id, alias)) in self.use_names_list.iter().enumerate() {
32+
if let Some(alias) = alias {
33+
write!(f, "{id} as {alias}")?;
34+
} else {
35+
write!(f, "{id}")?;
36+
}
37+
if i < len - 1 {
38+
write!(f, ", ")?;
39+
}
40+
}
41+
write!(f, " }};\n")?;
42+
Ok(())
43+
}
44+
}

crates/wit-encoder/src/world.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt;
22

3-
use crate::{ident::Ident, Docs, Include, Interface, Render, RenderOpts, StandaloneFunc};
3+
use crate::{ident::Ident, Docs, Include, Interface, Render, RenderOpts, StandaloneFunc, Use};
44

55
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66
pub struct World {
@@ -55,6 +55,9 @@ impl World {
5555
pub fn include(&mut self, include: Include) {
5656
self.item(WorldItem::Include(include));
5757
}
58+
pub fn use_(&mut self, use_: Use) {
59+
self.item(WorldItem::Use(use_));
60+
}
5861

5962
/// Set the documentation
6063
pub fn docs(&mut self, docs: Option<impl Into<Docs>>) {
@@ -143,6 +146,7 @@ impl Render for World {
143146
render_function(f, opts, function)?;
144147
}
145148
WorldItem::Include(include) => include.render(f, opts)?,
149+
WorldItem::Use(use_) => use_.render(f, opts)?,
146150
}
147151
}
148152
let opts = &opts.outdent();
@@ -173,6 +177,9 @@ pub enum WorldItem {
173177

174178
/// Include type
175179
Include(Include),
180+
181+
/// Use
182+
Use(Use),
176183
}
177184

178185
impl WorldItem {

crates/wit-encoder/tests/use.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use pretty_assertions::assert_eq;
2+
use wit_encoder::{Interface, Package, PackageName, ResourceFunc, TypeDef, Use, World};
3+
4+
const PACKAGE: &str = indoc::indoc! {"
5+
package foo:foo;
6+
7+
interface foo {
8+
resource bar {
9+
}
10+
}
11+
12+
interface bar {
13+
use foo.{ bar as foobar };
14+
resource baz {
15+
}
16+
}
17+
18+
world baz {
19+
use bar.{ baz };
20+
}
21+
"};
22+
23+
#[test]
24+
fn concrete_types() {
25+
let mut package = Package::new(PackageName::new("foo", "foo", None));
26+
27+
let mut interface = Interface::new("foo");
28+
interface.type_def(TypeDef::resource("bar", Vec::<ResourceFunc>::new()));
29+
package.interface(interface);
30+
31+
let mut interface = Interface::new("bar");
32+
let mut use_ = Use::new("foo");
33+
use_.item("bar", Some("foobar"));
34+
interface.use_(use_);
35+
interface.type_def(TypeDef::resource("baz", Vec::<ResourceFunc>::new()));
36+
package.interface(interface);
37+
38+
let mut world = World::new("baz");
39+
let mut use_ = Use::new("bar");
40+
use_.item("baz", None);
41+
world.use_(use_);
42+
package.world(world);
43+
44+
assert_eq!(package.to_string(), PACKAGE);
45+
}

0 commit comments

Comments
 (0)