use serde::Deserialize;
use std::any::TypeId;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
#[derive(Debug, Clone, Deserialize)]
pub struct TypeInfo {
pub name: String,
pub kind: String,
pub fields: Vec<FieldInfo>,
pub methods: Vec<MethodInfo>,
pub traits: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct FieldInfo {
pub name: String,
pub ty: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct MethodInfo {
pub name: String,
pub signature: String,
}
#[derive(Debug, Deserialize)]
struct TypeRegistryRaw {
types: HashMap<String, TypeInfo>,
}
#[derive(Debug)]
pub struct Registry {
by_name: HashMap<String, TypeInfo>,
type_ids: HashMap<TypeId, String>,
}
impl Registry {
pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, Box<dyn std::error::Error>> {
let content = fs::read_to_string(path)?;
let raw: TypeRegistryRaw = serde_json::from_str(&content)?;
let by_name: HashMap<String, TypeInfo> = raw
.types
.into_iter()
.map(|(_, info)| (info.name.clone(), info))
.collect();
Ok(Registry {
by_name,
type_ids: HashMap::new(),
})
}
pub fn register<T: 'static>(&mut self, type_name: &str) {
self.type_ids.insert(TypeId::of::<T>(), type_name.to_string());
}
pub fn get<T: 'static>(&self) -> Option<&TypeInfo> {
let type_id = TypeId::of::<T>();
let name = self.type_ids.get(&type_id)?;
self.by_name.get(name)
}
pub fn get_by_name(&self, name: &str) -> Option<&TypeInfo> {
self.by_name.get(name)
}
pub fn type_names(&self) -> impl Iterator<Item = &str> {
self.by_name.keys().map(|s| s.as_str())
}
}