standard_plugin_cli/
world.rs1use std::collections::BTreeSet;
6
7use standard_plugin_manifest::World;
8use wit_parser::{Resolve, WorldItem, WorldKey};
9
10pub const WIT: &str = standard_plugin::sources::WIT;
13
14#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct WorldShape {
17 pub imports: BTreeSet<String>,
20 pub exports: BTreeSet<String>,
23}
24
25pub fn shape(world: World) -> WorldShape {
27 let mut resolve = Resolve::default();
28 let package = resolve
29 .push_source("plugin.wit", WIT)
30 .expect("the embedded WIT package parses");
31 let id = resolve
32 .select_world(&[package], Some(world.wit_name()))
33 .expect("the embedded WIT package has both worlds");
34 let world = &resolve.worlds[id];
35 let name = |key: &WorldKey, item: &WorldItem| match (key, item) {
36 (_, WorldItem::Interface { id, .. }) => resolve.id_of(*id),
37 (WorldKey::Name(name), WorldItem::Function(_) | WorldItem::Type { .. }) => {
38 Some(name.clone())
39 }
40 _ => None,
41 };
42 WorldShape {
43 imports: world
44 .imports
45 .iter()
46 .filter_map(|(key, item)| name(key, item))
47 .collect(),
48 exports: world
49 .exports
50 .iter()
51 .filter_map(|(key, item)| name(key, item))
52 .collect(),
53 }
54}
55
56pub fn interface(name: &str) -> String {
58 format!("standard:plugin/{name}@2.0.0")
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn the_worlds_list_their_interfaces_and_exports() {
67 let ui = shape(World::Ui);
68 assert!(ui.imports.contains(&interface("surface")));
69 assert!(ui.imports.contains(&interface("claims")));
70 assert!(!ui.imports.contains(&interface("daemon-process")));
71 assert_eq!(
72 ui.exports,
73 ["activate", "deactivate", "event", "frame"]
74 .map(String::from)
75 .into()
76 );
77 let daemon = shape(World::Daemon);
78 assert!(daemon.imports.contains(&interface("daemon-panes")));
79 assert!(daemon.exports.contains("drive"));
80 assert!(daemon.exports.contains(&interface("companion")));
81 assert!(!daemon.exports.contains("handle-call"));
82 }
83}