use std::path::{Path, PathBuf};
use anyhow::{Result, bail};
use wit_parser::{Resolve, WorldItem};
#[derive(Default, Clone, Debug, PartialEq)]
pub struct WitOptions {
pub path: Option<PathBuf>,
pub world: Option<String>,
}
impl WitOptions {
pub fn from_tuple(opts: (Option<PathBuf>, Option<String>)) -> Result<Self> {
match opts {
(None, None) => Ok(Self {
path: None,
world: None,
}),
(None, Some(_)) => Ok(Self {
path: None,
world: None,
}),
(Some(_), None) => bail!("Must provide WIT world when providing WIT file"),
(path, world) => Ok(Self { path, world }),
}
}
pub(crate) fn defined(&self) -> bool {
self.path.is_some() && self.world.is_some()
}
pub(crate) fn unwrap_path(&self) -> &PathBuf {
self.path.as_ref().unwrap()
}
pub(crate) fn unwrap_world(&self) -> &String {
self.world.as_ref().unwrap()
}
}
pub(crate) fn parse_exports(wit: impl AsRef<Path>, world: &str) -> Result<Vec<String>> {
let mut resolve = Resolve::default();
resolve.push_path(wit.as_ref())?;
let (_, package_id) = resolve.package_names.first().unwrap();
let world_id = resolve.select_world(&[*package_id], Some(world))?;
let world = resolve.worlds.get(world_id).unwrap();
if !world.imports.is_empty() {
bail!("Imports in WIT file are not supported");
}
let mut exported_functions = vec![];
for (_, export) in &world.exports {
match export {
WorldItem::Interface { .. } => {
bail!("Exported interfaces are not supported")
}
WorldItem::Function(f) => {
if !f.params.is_empty() {
bail!("Exported functions with parameters are not supported")
} else if f.result.is_some() {
bail!("Exported functions with return values are not supported")
} else {
exported_functions.push(f.name.clone())
}
}
WorldItem::Type(_) => bail!("Exported types are not supported"),
}
}
Ok(exported_functions)
}