use anyhow::{Context, Result};
use wit_parser::Resolve;
type WorldKeyName = String;
type WitFunctionName = String;
pub(crate) struct WrpcExport {
pub(crate) wit_ns: String,
pub(crate) wit_pkg: String,
pub(crate) wit_iface: String,
pub(crate) wit_iface_fn: String,
pub(crate) types: (WorldKeyName, WitFunctionName, wrpc_types::DynamicFunction),
}
pub(crate) fn generate_wrpc_nats_subject_to_fn_mapping(
resolve: &Resolve,
) -> Result<Vec<WrpcExport>> {
let mut subjects = Vec::new();
for (_, world) in resolve.worlds.iter() {
let mut wrpc_type_lookup = wrpc_types::function_exports(resolve, world.exports.iter());
for (world_item, _) in world.exports.iter() {
match world_item {
wit_parser::WorldKey::Name(_) => continue,
wit_parser::WorldKey::Interface(iface_id) => {
let iface = resolve.interfaces.get(*iface_id).with_context(|| {
format!("unexpectedly missing iface with ID [{iface_id:?}]")
})?;
let iface_name = iface.name.as_ref().with_context(|| {
format!(
"unexpectedly un-named iface ID [{iface_id:?}] in world [{}]",
&world.name,
)
})?;
let iface_pkg = resolve
.packages
.get(iface.package.with_context(|| {
format!("unexpectedly missing package for iface [{iface_name}] ")
})?)
.with_context(|| {
"missing top level referenced package for iface [{iface_name}]"
})?;
let ns = &iface_pkg.name.namespace;
let pkg_name = &iface_pkg.name.name;
for (fn_name, _) in iface.functions.iter() {
let world_key_name = resolve.name_world_key(world_item);
let dynamic_fn = wrpc_type_lookup
.get_mut(&world_key_name)
.and_then(|lookup| lookup.remove(fn_name))
.with_context(|| {
format!("failed to look up dynamic [{world_key_name}.{fn_name}]")
})?;
subjects.push(WrpcExport {
wit_ns: ns.into(),
wit_pkg: pkg_name.into(),
wit_iface: iface_name.into(),
wit_iface_fn: fn_name.into(),
types: (world_key_name, fn_name.into(), dynamic_fn),
});
}
}
}
}
}
Ok(subjects)
}