1use std::path::{Path, PathBuf};
2
3use anyhow::{bail, Result};
4
5use wit_parser::{Resolve, WorldItem};
6
7#[derive(Default, Clone, Debug, PartialEq)]
9pub struct WitOptions {
10 pub path: Option<PathBuf>,
12 pub world: Option<String>,
14}
15
16impl WitOptions {
17 pub fn from_tuple(opts: (Option<PathBuf>, Option<String>)) -> Result<Self> {
19 match opts {
20 (None, None) => Ok(Self {
21 path: None,
22 world: None,
23 }),
24 (None, Some(_)) => Ok(Self {
25 path: None,
26 world: None,
27 }),
28 (Some(_), None) => bail!("Must provide WIT world when providing WIT file"),
29 (path, world) => Ok(Self { path, world }),
30 }
31 }
32
33 pub(crate) fn defined(&self) -> bool {
35 self.path.is_some() && self.world.is_some()
36 }
37
38 pub(crate) fn unwrap_path(&self) -> &PathBuf {
40 self.path.as_ref().unwrap()
41 }
42
43 pub(crate) fn unwrap_world(&self) -> &String {
45 self.world.as_ref().unwrap()
46 }
47}
48
49pub(crate) fn parse_exports(wit: impl AsRef<Path>, world: &str) -> Result<Vec<String>> {
50 let mut resolve = Resolve::default();
51 resolve.push_path(wit.as_ref())?;
52 let (_, package_id) = resolve.package_names.first().unwrap();
53 let world_id = resolve.select_world(&[*package_id], Some(world))?;
54 let world = resolve.worlds.get(world_id).unwrap();
55
56 if !world.imports.is_empty() {
57 bail!("Imports in WIT file are not supported");
58 }
59 let mut exported_functions = vec![];
60 for (_, export) in &world.exports {
61 match export {
62 WorldItem::Interface { .. } => {
63 bail!("Exported interfaces are not supported")
64 }
65 WorldItem::Function(f) => {
66 if !f.params.is_empty() {
67 bail!("Exported functions with parameters are not supported")
68 } else if f.results.len() != 0 {
69 bail!("Exported functions with return values are not supported")
70 } else {
71 exported_functions.push(f.name.clone())
72 }
73 }
74 WorldItem::Type(_) => bail!("Exported types are not supported"),
75 }
76 }
77 Ok(exported_functions)
78}