1use std::sync::Arc;
4
5use ferrin_spec::ToolName;
6use indexmap::IndexMap;
7
8use crate::error::DuplicateToolError;
9use crate::tool::Tool;
10
11#[derive(Debug, Clone, Default)]
14pub struct ToolSet {
15 tools: IndexMap<ToolName, Arc<Tool>>,
16}
17
18impl ToolSet {
19 #[must_use]
21 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn insert(
31 mut self,
32 name: impl Into<ToolName>,
33 tool: Tool,
34 ) -> Result<Self, DuplicateToolError> {
35 self.try_insert(name, tool)?;
36 Ok(self)
37 }
38
39 pub fn try_insert(
45 &mut self,
46 name: impl Into<ToolName>,
47 tool: Tool,
48 ) -> Result<(), DuplicateToolError> {
49 self.try_insert_arc(name, Arc::new(tool))
50 }
51
52 pub fn try_insert_arc(
58 &mut self,
59 name: impl Into<ToolName>,
60 tool: Arc<Tool>,
61 ) -> Result<(), DuplicateToolError> {
62 let name = name.into();
63 if self.tools.contains_key(&name) {
64 return Err(DuplicateToolError { name });
65 }
66 self.tools.insert(name, tool);
67 Ok(())
68 }
69
70 pub fn replace(&mut self, name: impl Into<ToolName>, tool: Arc<Tool>) -> Option<Arc<Tool>> {
72 self.tools.insert(name.into(), tool)
73 }
74
75 pub fn remove(&mut self, name: &str) -> Option<Arc<Tool>> {
77 self.tools.shift_remove(name)
78 }
79
80 #[must_use]
82 pub fn get(&self, name: &str) -> Option<&Arc<Tool>> {
83 self.tools.get(name)
84 }
85
86 #[must_use]
88 pub fn contains(&self, name: &str) -> bool {
89 self.tools.contains_key(name)
90 }
91
92 pub fn names(&self) -> impl Iterator<Item = &ToolName> + '_ {
94 self.tools.keys()
95 }
96
97 pub fn iter(&self) -> impl Iterator<Item = (&ToolName, &Arc<Tool>)> + '_ {
99 self.tools.iter()
100 }
101
102 #[must_use]
104 pub fn len(&self) -> usize {
105 self.tools.len()
106 }
107
108 #[must_use]
110 pub fn is_empty(&self) -> bool {
111 self.tools.is_empty()
112 }
113
114 #[must_use]
117 pub fn filter_active(&self, active: &[ToolName]) -> Self {
118 Self {
119 tools: self
120 .tools
121 .iter()
122 .filter(|(name, _)| active.contains(name))
123 .map(|(name, tool)| (name.clone(), Arc::clone(tool)))
124 .collect(),
125 }
126 }
127
128 pub fn merge(mut self, other: Self) -> Result<Self, DuplicateToolError> {
134 for (name, tool) in other.tools {
135 self.try_insert_arc(name, tool)?;
136 }
137 Ok(self)
138 }
139
140 #[must_use]
143 pub fn ordered(&self, order: &[ToolName]) -> Vec<(&ToolName, &Arc<Tool>)> {
144 let mut listed: Vec<(&ToolName, &Arc<Tool>)> = order
145 .iter()
146 .filter_map(|name| self.tools.get_key_value(name))
147 .collect();
148 let mut rest: Vec<(&ToolName, &Arc<Tool>)> = self
149 .tools
150 .iter()
151 .filter(|(name, _)| !order.contains(name))
152 .collect();
153 rest.sort_by(|(a, _), (b, _)| a.as_str().cmp(b.as_str()));
154 listed.append(&mut rest);
155 listed
156 }
157}
158
159impl<'a> IntoIterator for &'a ToolSet {
160 type Item = (&'a ToolName, &'a Arc<Tool>);
161 type IntoIter = indexmap::map::Iter<'a, ToolName, Arc<Tool>>;
162
163 fn into_iter(self) -> Self::IntoIter {
164 self.tools.iter()
165 }
166}