use std::collections::BTreeSet;
use standard_plugin_manifest::World;
use wit_parser::{Resolve, WorldItem, WorldKey};
pub const WIT: &str = standard_plugin::sources::WIT;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct WorldShape {
pub imports: BTreeSet<String>,
pub exports: BTreeSet<String>,
}
pub fn shape(world: World) -> WorldShape {
let mut resolve = Resolve::default();
let package = resolve
.push_source("plugin.wit", WIT)
.expect("the embedded WIT package parses");
let id = resolve
.select_world(&[package], Some(world.wit_name()))
.expect("the embedded WIT package has both worlds");
let world = &resolve.worlds[id];
let name = |key: &WorldKey, item: &WorldItem| match (key, item) {
(_, WorldItem::Interface { id, .. }) => resolve.id_of(*id),
(WorldKey::Name(name), WorldItem::Function(_) | WorldItem::Type { .. }) => {
Some(name.clone())
}
_ => None,
};
WorldShape {
imports: world
.imports
.iter()
.filter_map(|(key, item)| name(key, item))
.collect(),
exports: world
.exports
.iter()
.filter_map(|(key, item)| name(key, item))
.collect(),
}
}
pub fn interface(name: &str) -> String {
format!("standard:plugin/{name}@2.0.0")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_worlds_list_their_interfaces_and_exports() {
let ui = shape(World::Ui);
assert!(ui.imports.contains(&interface("surface")));
assert!(ui.imports.contains(&interface("claims")));
assert!(!ui.imports.contains(&interface("daemon-process")));
assert_eq!(
ui.exports,
["activate", "deactivate", "event", "frame"]
.map(String::from)
.into()
);
let daemon = shape(World::Daemon);
assert!(daemon.imports.contains(&interface("daemon-panes")));
assert!(daemon.exports.contains("drive"));
assert!(daemon.exports.contains(&interface("companion")));
assert!(!daemon.exports.contains("handle-call"));
}
}