use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::{Arc, OnceLock, RwLock};
use crate::gpu::params::ParamDef;
pub struct ToolRegistration {
pub type_id: &'static str,
pub display_name: &'static str,
pub params: &'static [ParamDef],
}
pub struct ToolRegistry {
entries: HashMap<&'static str, ToolEntry>,
}
struct ToolEntry {
display_name: &'static str,
params: &'static [ParamDef],
}
impl Default for ToolRegistry {
fn default() -> Self {
Self::new()
}
}
impl ToolRegistry {
pub fn new() -> Self {
let mut entries = HashMap::new();
for reg in crate::tools::registrations() {
entries.insert(
reg.type_id,
ToolEntry {
display_name: reg.display_name,
params: reg.params,
},
);
}
ToolRegistry { entries }
}
pub fn display_name(&self, type_id: &str) -> &'static str {
self.entries
.get(type_id)
.map(|e| e.display_name)
.unwrap_or("")
}
pub fn param_defs(&self, type_id: &str) -> &'static [ParamDef] {
self.entries.get(type_id).map(|e| e.params).unwrap_or(&[])
}
pub fn types(&self) -> Vec<(&'static str, &'static str, &'static [ParamDef])> {
let mut v: Vec<_> = self
.entries
.iter()
.map(|(&id, e)| (id, e.display_name, e.params))
.collect();
v.sort_by_key(|(id, _, _)| *id);
v
}
}
pub fn registry() -> &'static ToolRegistry {
static REGISTRY: OnceLock<ToolRegistry> = OnceLock::new();
REGISTRY.get_or_init(ToolRegistry::new)
}
pub struct ToolSession {
states: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
}
impl ToolSession {
pub fn new() -> Self {
ToolSession {
states: HashMap::new(),
}
}
pub fn insert<T: 'static + Send + Sync>(&mut self, value: T) {
self.states.insert(TypeId::of::<T>(), Box::new(value));
}
pub fn get<T: 'static>(&self) -> Option<&T> {
self.states.get(&TypeId::of::<T>())?.downcast_ref::<T>()
}
pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.states.get_mut(&TypeId::of::<T>())?.downcast_mut::<T>()
}
pub fn get_or_default<T: 'static + Send + Sync + Default>(&mut self) -> &mut T {
self.states
.entry(TypeId::of::<T>())
.or_insert_with(|| Box::new(T::default()))
.downcast_mut::<T>()
.expect("TypeId key guarantees the stored type matches `T`")
}
}
impl Default for ToolSession {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone)]
pub struct SharedToolSession(Arc<RwLock<ToolSession>>);
impl SharedToolSession {
pub fn new() -> Self {
SharedToolSession(Arc::new(RwLock::new(ToolSession::new())))
}
pub fn read(&self) -> std::sync::RwLockReadGuard<'_, ToolSession> {
self.0.read().expect("tool session lock poisoned")
}
pub fn write(&self) -> std::sync::RwLockWriteGuard<'_, ToolSession> {
self.0.write().expect("tool session lock poisoned")
}
}
impl Default for SharedToolSession {
fn default() -> Self {
Self::new()
}
}