Skip to main content

soma_codemode/types/
id.rs

1use 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}