use super::host_tools::RegisteredTool;
use super::tool_handler::ToolHandler;
use monoloop_contracts::{ToolId, ToolName, ToolSpec};
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Clone)]
pub struct ResolvedTool {
pub spec: ToolSpec,
pub handler: Arc<dyn ToolHandler>,
}
impl std::fmt::Debug for ResolvedTool {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ResolvedTool")
.field("spec", &self.spec)
.field("handler", &"<dyn ToolHandler>")
.finish()
}
}
#[derive(Clone, Debug, Default)]
pub struct ResolvedToolSet {
by_id: HashMap<ToolId, ResolvedTool>,
by_name: HashMap<ToolName, ToolId>,
ordered: Vec<ToolId>,
}
impl ResolvedToolSet {
pub fn empty() -> Self {
Self::default()
}
pub fn from_registered(tools: Vec<RegisteredTool>) -> Self {
let mut by_id = HashMap::new();
let mut by_name = HashMap::new();
let mut ordered = Vec::with_capacity(tools.len());
for tool in tools {
by_name.insert(tool.spec.name.clone(), tool.spec.id.clone());
ordered.push(tool.spec.id.clone());
by_id.insert(
tool.spec.id.clone(),
ResolvedTool {
spec: tool.spec,
handler: tool.handler,
},
);
}
Self {
by_id,
by_name,
ordered,
}
}
pub fn is_empty(&self) -> bool {
self.by_id.is_empty()
}
pub fn len(&self) -> usize {
self.by_id.len()
}
pub fn specs(&self) -> Vec<&ToolSpec> {
self.ordered
.iter()
.filter_map(|id| self.by_id.get(id).map(|t| &t.spec))
.collect()
}
pub fn tools(&self) -> Vec<&ResolvedTool> {
self.ordered
.iter()
.filter_map(|id| self.by_id.get(id))
.collect()
}
pub fn get(&self, id: &ToolId) -> Option<&ResolvedTool> {
self.by_id.get(id)
}
pub fn get_by_name(&self, name: &ToolName) -> Option<&ResolvedTool> {
self.by_name.get(name).and_then(|id| self.by_id.get(id))
}
pub fn contains_name(&self, name: &ToolName) -> bool {
self.by_name.contains_key(name)
}
}