use anyhow::Context;
use serde::{Deserialize, Serialize};
use std::{
collections::{HashMap, HashSet},
env, fs,
path::Path,
};
use crate::path_safety::normalize_under_root;
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct AdapterCatalog {
pub adapters: HashMap<String, HashSet<String>>,
}
impl AdapterCatalog {
pub fn load_from_file(path: impl AsRef<Path>) -> anyhow::Result<Self> {
let path_ref = path.as_ref();
let registry_root = env::current_dir().context("unable to resolve registry root")?;
let safe_path = normalize_under_root(®istry_root, path_ref)?;
let txt = fs::read_to_string(&safe_path).with_context(|| {
format!("unable to read adapter registry at {}", safe_path.display())
})?;
if let Ok(value) = serde_json::from_str::<Self>(&txt) {
return Ok(value);
}
#[cfg(feature = "toml")]
{
if let Ok(value) = toml::from_str::<Self>(&txt) {
return Ok(value);
}
}
#[cfg(feature = "toml")]
{
anyhow::bail!(
"unsupported registry format in {}: expected JSON or TOML",
path_ref.display()
);
}
#[cfg(not(feature = "toml"))]
{
anyhow::bail!(
"unsupported registry format in {}: expected JSON (enable `toml` feature for TOML support)",
path_ref.display()
);
}
}
pub fn contains(&self, namespace: &str, adapter: &str, operation: &str) -> bool {
let key = format!("{namespace}.{adapter}");
self.adapters
.get(&key)
.map(|ops| ops.contains(operation))
.unwrap_or(false)
}
}