soma_codemode/types/
id.rs1use crate::{util::invalid_code_mode_id, ToolError};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct CodeModeToolId {
5 pub raw: String,
6 pub reference: CodeModeToolRef,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum CodeModeToolRef {
11 Tool { namespace: String, tool: String },
12}
13
14impl CodeModeToolId {
15 pub fn parse(raw: &str) -> Result<Self, ToolError> {
16 raw.parse()
17 }
18}
19
20impl std::str::FromStr for CodeModeToolId {
21 type Err = ToolError;
22
23 fn from_str(raw: &str) -> Result<Self, Self::Err> {
24 let raw = raw.trim();
25 if raw.is_empty() {
26 return Err(invalid_code_mode_id("Code Mode tool id must not be empty"));
27 }
28 let Some((namespace, tool)) = split_namespaced_id(raw) else {
29 return Err(invalid_code_mode_id(
30 "Code Mode ids must use <namespace>::<tool>",
31 ));
32 };
33 Ok(Self {
34 raw: raw.to_string(),
35 reference: CodeModeToolRef::Tool {
36 namespace: namespace.to_string(),
37 tool: tool.to_string(),
38 },
39 })
40 }
41}
42
43pub fn split_namespaced_id(raw: &str) -> Option<(&str, &str)> {
44 let mut parts = raw.split("::");
45 let namespace = parts.next()?.trim();
46 let tool = parts.next()?.trim();
47 if parts.next().is_some() || namespace.is_empty() || tool.is_empty() {
48 return None;
49 }
50 Some((namespace, tool))
51}
52
53#[must_use]
54pub fn namespaced_tool_id(namespace: &str, tool: &str) -> String {
55 format!("{namespace}::{tool}")
56}