1use std::collections::HashMap;
4
5use crate::binary::SignedInvocation;
6use crate::dispatch::handler::{SharedArgs, ToolHandler, ToolResult};
7use crate::protocol::schema::SchemaValidator;
8use crate::protocol::ToolSchema;
9use crate::security::{NonceStore, Verifier};
10use crate::{CapabilityManifest, DCPError, SecurityError};
11
12pub struct BinaryTrieRouter {
14 handlers: Vec<Option<Box<dyn ToolHandler>>>,
16 name_to_id: HashMap<String, u16>,
18 max_tool_id: u16,
20}
21
22impl BinaryTrieRouter {
23 pub const MAX_TOOLS: usize = CapabilityManifest::MAX_TOOLS;
25
26 pub fn new() -> Self {
28 Self {
29 handlers: Vec::new(),
30 name_to_id: HashMap::new(),
31 max_tool_id: 0,
32 }
33 }
34
35 pub fn with_capacity(capacity: usize) -> Self {
37 Self {
38 handlers: Vec::with_capacity(capacity.min(Self::MAX_TOOLS)),
39 name_to_id: HashMap::with_capacity(capacity),
40 max_tool_id: 0,
41 }
42 }
43
44 pub fn register(&mut self, handler: Box<dyn ToolHandler>) -> Result<u16, DCPError> {
46 let tool_id = handler.tool_id();
47 let tool_name = handler.tool_name().to_string();
48
49 let id_usize = tool_id as usize;
51 if id_usize >= Self::MAX_TOOLS {
52 return Err(DCPError::ValidationFailed);
53 }
54 if self.name_to_id.contains_key(&tool_name) {
55 return Err(DCPError::ValidationFailed);
56 }
57 if self
58 .handlers
59 .get(id_usize)
60 .and_then(|handler| handler.as_ref())
61 .is_some()
62 {
63 return Err(DCPError::ValidationFailed);
64 }
65
66 while self.handlers.len() <= id_usize {
67 self.handlers.push(None);
68 }
69
70 self.handlers[id_usize] = Some(handler);
72 self.name_to_id.insert(tool_name, tool_id);
73
74 if tool_id > self.max_tool_id {
75 self.max_tool_id = tool_id;
76 }
77
78 Ok(tool_id)
79 }
80
81 #[inline(always)]
83 pub(crate) fn dispatch(&self, tool_id: u16) -> Option<&dyn ToolHandler> {
84 self.handlers
85 .get(tool_id as usize)
86 .and_then(|h| h.as_ref())
87 .map(|h| h.as_ref())
88 }
89
90 pub fn tool_schema(&self, tool_id: u16) -> Option<&ToolSchema> {
92 self.dispatch(tool_id).map(|handler| handler.schema())
93 }
94
95 pub fn execute(&self, tool_id: u16, args: &SharedArgs) -> Result<ToolResult, DCPError> {
100 let _ = (tool_id, args);
101 Err(DCPError::CapabilityDenied)
102 }
103
104 pub fn execute_authorized(
106 &self,
107 capabilities: &CapabilityManifest,
108 tool_id: u16,
109 args: &SharedArgs,
110 ) -> Result<ToolResult, SecurityError> {
111 let handler = self.validate_authorized_tool(capabilities, tool_id, args)?;
112 handler
113 .execute(args)
114 .map_err(|_| SecurityError::InsufficientCapabilities)
115 }
116
117 pub fn execute_signed_authorized(
120 &self,
121 capabilities: &CapabilityManifest,
122 invocation: &SignedInvocation,
123 public_key: &[u8; 32],
124 nonce_store: &mut NonceStore,
125 args: &SharedArgs,
126 ) -> Result<ToolResult, SecurityError> {
127 Verifier::verify_invocation(invocation, public_key)?;
128 if !Verifier::verify_args_hash(invocation, args.data()) {
129 return Err(SecurityError::ArgsHashMismatch);
130 }
131
132 let tool_id = u16::try_from(invocation.tool_id)
133 .map_err(|_| SecurityError::InsufficientCapabilities)?;
134 nonce_store.check_nonce(invocation.nonce, invocation.timestamp)?;
135
136 let handler = self.validate_authorized_tool(capabilities, tool_id, args)?;
137
138 handler
139 .execute(args)
140 .map_err(|_| SecurityError::InsufficientCapabilities)
141 }
142
143 fn validate_authorized_tool(
144 &self,
145 capabilities: &CapabilityManifest,
146 tool_id: u16,
147 args: &SharedArgs,
148 ) -> Result<&dyn ToolHandler, SecurityError> {
149 capabilities.require_tool(tool_id)?;
150 let handler = self
151 .dispatch(tool_id)
152 .ok_or(SecurityError::InsufficientCapabilities)?;
153 SchemaValidator::validate_shared_args(&handler.schema().input, args)
154 .map_err(|_| SecurityError::ValidationFailed)?;
155 Ok(handler)
156 }
157
158 pub fn resolve_name(&self, name: &str) -> Option<u16> {
160 self.name_to_id.get(name).copied()
161 }
162
163 pub fn max_tool_id(&self) -> u16 {
165 self.max_tool_id
166 }
167
168 pub fn tool_count(&self) -> usize {
170 self.handlers.iter().filter(|h| h.is_some()).count()
171 }
172
173 pub fn has_tool(&self, tool_id: u16) -> bool {
175 self.dispatch(tool_id).is_some()
176 }
177
178 pub fn tool_names(&self) -> impl Iterator<Item = &str> {
180 self.name_to_id.keys().map(|s| s.as_str())
181 }
182
183 pub fn capabilities(&self) -> ServerCapabilities {
185 ServerCapabilities {
186 tools: self.tool_count() > 0,
187 resources: false, prompts: false, logging: true,
190 }
191 }
192}
193
194#[derive(Debug, Clone, Default)]
196pub struct ServerCapabilities {
197 pub tools: bool,
198 pub resources: bool,
199 pub prompts: bool,
200 pub logging: bool,
201}
202
203impl Default for BinaryTrieRouter {
204 fn default() -> Self {
205 Self::new()
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212 use crate::protocol::schema::{InputSchema, ToolSchema};
213
214 struct TestHandler {
216 schema: ToolSchema,
217 }
218
219 impl TestHandler {
220 fn new(id: u16, name: &'static str) -> Self {
221 Self {
222 schema: ToolSchema {
223 name,
224 id,
225 description: "Test tool",
226 input: InputSchema::new(),
227 },
228 }
229 }
230 }
231
232 impl ToolHandler for TestHandler {
233 fn execute(&self, _args: &SharedArgs) -> Result<ToolResult, DCPError> {
234 Ok(ToolResult::success(vec![self.schema.id as u8]))
235 }
236
237 fn schema(&self) -> &ToolSchema {
238 &self.schema
239 }
240 }
241
242 #[test]
243 fn test_register_and_dispatch() {
244 let mut router = BinaryTrieRouter::new();
245
246 let handler = Box::new(TestHandler::new(1, "test_tool"));
247 router.register(handler).unwrap();
248
249 assert!(router.has_tool(1));
250 assert!(!router.has_tool(0));
251 assert!(!router.has_tool(2));
252
253 let dispatched = router.dispatch(1).unwrap();
254 assert_eq!(dispatched.tool_id(), 1);
255 }
256
257 #[test]
258 fn test_resolve_name() {
259 let mut router = BinaryTrieRouter::new();
260
261 router
262 .register(Box::new(TestHandler::new(42, "my_tool")))
263 .unwrap();
264
265 assert_eq!(router.resolve_name("my_tool"), Some(42));
266 assert_eq!(router.resolve_name("unknown"), None);
267 }
268
269 #[test]
270 fn test_raw_execute_is_deny_by_default() {
271 let mut router = BinaryTrieRouter::new();
272 router
273 .register(Box::new(TestHandler::new(5, "exec_test")))
274 .unwrap();
275
276 let args = SharedArgs::new(&[], 0);
277 let result = router.execute(5, &args);
278
279 assert_eq!(result, Err(DCPError::CapabilityDenied));
280 }
281
282 #[test]
283 fn test_raw_execute_hides_tool_existence() {
284 let router = BinaryTrieRouter::new();
285 let args = SharedArgs::new(&[], 0);
286
287 let result = router.execute(999, &args);
288 assert_eq!(result, Err(DCPError::CapabilityDenied));
289 }
290
291 #[test]
292 fn test_multiple_tools() {
293 let mut router = BinaryTrieRouter::new();
294
295 for i in 0..10 {
296 let name: &'static str = Box::leak(format!("tool_{}", i).into_boxed_str());
297 router
298 .register(Box::new(TestHandler::new(i, name)))
299 .unwrap();
300 }
301
302 assert_eq!(router.tool_count(), 10);
303 assert_eq!(router.max_tool_id(), 9);
304
305 for i in 0..10 {
306 assert!(router.has_tool(i));
307 }
308 }
309
310 #[test]
311 fn test_sparse_registration() {
312 let mut router = BinaryTrieRouter::new();
313
314 router
315 .register(Box::new(TestHandler::new(0, "first")))
316 .unwrap();
317 router
318 .register(Box::new(TestHandler::new(100, "hundredth")))
319 .unwrap();
320 router
321 .register(Box::new(TestHandler::new(1000, "thousandth")))
322 .unwrap();
323
324 assert_eq!(router.tool_count(), 3);
325 assert!(router.has_tool(0));
326 assert!(router.has_tool(100));
327 assert!(router.has_tool(1000));
328 assert!(!router.has_tool(50));
329 }
330}