use std::collections::HashMap;
use std::sync::OnceLock;
use serde::Deserialize;
use crate::error::{Error, Result};
pub const SPDX_LICENSES: &str = include_str!("vocabularies/licenses.json");
pub fn load_vocabulary(name: &str) -> Result<&'static str> {
match name {
"SPDX.Licenses" => Ok(SPDX_LICENSES),
other => Err(Error::Parse(format!("unsupported vocabulary: {other}"))),
}
}
const SUBJECTS_OPENALEX_YAML: &str = include_str!("vocabularies/subjects_openalex.yaml");
#[derive(Deserialize)]
struct OaEntry {
id: String,
subject: String,
}
fn openalex_vocab() -> &'static HashMap<String, (String, String)> {
static VOCAB: OnceLock<HashMap<String, (String, String)>> = OnceLock::new();
VOCAB.get_or_init(|| {
let entries: Vec<OaEntry> =
serde_yaml::from_str(SUBJECTS_OPENALEX_YAML).unwrap_or_default();
entries
.into_iter()
.map(|e| {
let key = e.id.rsplit('/').next().unwrap_or("").to_string();
(key, (e.id, e.subject))
})
.collect()
})
}
pub fn lookup_openalex_subject(id: &str) -> Option<(String, String)> {
if id.is_empty() {
return None;
}
openalex_vocab()
.get(id)
.map(|(url, name)| (url.clone(), name.clone()))
}