Skip to main content

badeline_plugin/
lib.rs

1use serde::Deserialize;
2use std::any::TypeId;
3use std::collections::HashMap;
4use std::fs;
5use std::path::Path;
6
7#[derive(Debug, Clone, Deserialize)]
8pub struct TypeInfo {
9    pub name: String,
10    pub kind: String,
11    pub fields: Vec<FieldInfo>,
12    pub methods: Vec<MethodInfo>,
13    pub traits: Vec<String>,
14}
15
16#[derive(Debug, Clone, Deserialize)]
17pub struct FieldInfo {
18    pub name: String,
19    pub ty: String,
20}
21
22#[derive(Debug, Clone, Deserialize)]
23pub struct MethodInfo {
24    pub name: String,
25    pub signature: String,
26}
27
28#[derive(Debug, Deserialize)]
29struct TypeRegistryRaw {
30    types: HashMap<String, TypeInfo>,
31}
32
33/// Runtime registry for querying type metadata.
34///
35/// The registry is loaded from a JSON sidecar file generated by the
36/// badeline-rustc compiler plugin.
37#[derive(Debug)]
38pub struct Registry {
39    /// Maps type names to their metadata
40    by_name: HashMap<String, TypeInfo>,
41    /// Maps TypeId to type name for runtime lookup
42    type_ids: HashMap<TypeId, String>,
43}
44
45impl Registry {
46    /// Load the registry from a JSON file.
47    pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, Box<dyn std::error::Error>> {
48        let content = fs::read_to_string(path)?;
49        let raw: TypeRegistryRaw = serde_json::from_str(&content)?;
50
51        let by_name: HashMap<String, TypeInfo> = raw
52            .types
53            .into_iter()
54            .map(|(_, info)| (info.name.clone(), info))
55            .collect();
56
57        Ok(Registry {
58            by_name,
59            type_ids: HashMap::new(),
60        })
61    }
62
63    /// Register a type for TypeId-based lookup.
64    ///
65    /// Call this for each type you want to query by TypeId.
66    /// The type name should match the name in the registry.
67    pub fn register<T: 'static>(&mut self, type_name: &str) {
68        self.type_ids.insert(TypeId::of::<T>(), type_name.to_string());
69    }
70
71    /// Get type info by TypeId.
72    ///
73    /// The type must have been registered with `register` first.
74    pub fn get<T: 'static>(&self) -> Option<&TypeInfo> {
75        let type_id = TypeId::of::<T>();
76        let name = self.type_ids.get(&type_id)?;
77        self.by_name.get(name)
78    }
79
80    /// Get type info by name.
81    pub fn get_by_name(&self, name: &str) -> Option<&TypeInfo> {
82        self.by_name.get(name)
83    }
84
85    /// List all known type names.
86    pub fn type_names(&self) -> impl Iterator<Item = &str> {
87        self.by_name.keys().map(|s| s.as_str())
88    }
89}