use anyhow::Result;
use serde::Deserialize;
use std::collections::HashMap;
use std::path::PathBuf;
const BUNDLED_ALIASES: &str = include_str!("../models.toml");
#[derive(Debug, Deserialize)]
struct AliasEntry {
canonical: String,
#[serde(default)]
aliases: Vec<String>,
}
pub struct AliasMap {
to_canonical: HashMap<String, String>,
}
impl AliasMap {
pub fn load(override_path: Option<&str>) -> Result<Self> {
let mut to_canonical = HashMap::new();
Self::parse_into(BUNDLED_ALIASES, &mut to_canonical)?;
if let Some(path) = override_path {
let p = PathBuf::from(path);
if p.exists() {
let content = std::fs::read_to_string(&p)?;
Self::parse_into(&content, &mut to_canonical)?;
}
} else {
let default_override = dirs::config_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("pondus")
.join("models.toml");
if default_override.exists() {
let content = std::fs::read_to_string(&default_override)?;
Self::parse_into(&content, &mut to_canonical)?;
}
}
Ok(Self { to_canonical })
}
fn parse_into(toml_str: &str, map: &mut HashMap<String, String>) -> Result<()> {
let entries: HashMap<String, AliasEntry> = toml::from_str(toml_str)?;
for (_, entry) in entries {
let canonical = entry.canonical.to_lowercase();
map.insert(canonical.clone(), canonical.clone());
for alias in &entry.aliases {
map.insert(alias.to_lowercase(), canonical.clone());
}
}
Ok(())
}
pub fn resolve(&self, name: &str) -> String {
let lower = name.to_lowercase();
self.to_canonical.get(&lower).cloned().unwrap_or(lower)
}
pub fn matches(&self, source_name: &str, canonical: &str) -> bool {
self.resolve(source_name) == canonical.to_lowercase()
}
}