Skip to main content

forge_primitives/
ids.rs

1//! Identity newtypes used across forge crates.
2//!
3//! Wraps `String` rather than UUID-typed because the upstream `claude`
4//! CLI emits IDs as opaque strings; preserving that shape avoids
5//! accidental parse errors at the codec boundary.
6
7use serde::{Deserialize, Serialize};
8
9/// Session identifier emitted by the `claude` CLI's `system/init` frame.
10#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
11#[serde(transparent)]
12pub struct SessionId(pub String);
13
14/// Per-tool-call identifier carried in `can_use_tool` and tool messages.
15#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
16#[serde(transparent)]
17pub struct ToolUseId(pub String);
18
19macro_rules! id_impls {
20    ($name:ident) => {
21        impl $name {
22            pub fn new(s: impl Into<String>) -> Self {
23                Self(s.into())
24            }
25            pub fn as_str(&self) -> &str {
26                &self.0
27            }
28            pub fn into_string(self) -> String {
29                self.0
30            }
31        }
32        impl std::fmt::Display for $name {
33            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34                f.write_str(&self.0)
35            }
36        }
37        impl From<String> for $name {
38            fn from(s: String) -> Self {
39                Self(s)
40            }
41        }
42        impl From<&str> for $name {
43            fn from(s: &str) -> Self {
44                Self(s.to_owned())
45            }
46        }
47    };
48}
49
50id_impls!(SessionId);
51id_impls!(ToolUseId);
52
53// Convenience comparisons so call sites can write `id == "literal"`
54// without unwrapping the newtype.
55macro_rules! id_str_eq {
56    ($name:ident) => {
57        impl PartialEq<str> for $name {
58            fn eq(&self, other: &str) -> bool {
59                self.0 == other
60            }
61        }
62        impl PartialEq<&str> for $name {
63            fn eq(&self, other: &&str) -> bool {
64                self.0 == *other
65            }
66        }
67        impl PartialEq<String> for $name {
68            fn eq(&self, other: &String) -> bool {
69                &self.0 == other
70            }
71        }
72    };
73}
74
75id_str_eq!(SessionId);
76id_str_eq!(ToolUseId);