ferrin_spec/shared/ids.rs
1//! Newtype identifiers.
2//!
3//! Each identifier wraps a `String` and serializes transparently as a JSON
4//! string. Distinct types prevent, for example, passing a tool name where a
5//! tool call id is expected.
6
7macro_rules! string_id {
8 ($(#[$meta:meta])* $name:ident) => {
9 $(#[$meta])*
10 #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
11 #[derive(serde::Serialize, serde::Deserialize)]
12 #[serde(transparent)]
13 pub struct $name(String);
14
15 impl $name {
16 /// Creates a new identifier from any string-like value.
17 #[must_use]
18 pub fn new(value: impl Into<String>) -> Self {
19 Self(value.into())
20 }
21
22 /// Returns the identifier as a string slice.
23 #[must_use]
24 pub fn as_str(&self) -> &str {
25 &self.0
26 }
27
28 /// Consumes the identifier and returns the inner `String`.
29 #[must_use]
30 pub fn into_string(self) -> String {
31 self.0
32 }
33 }
34
35 impl std::fmt::Display for $name {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 f.write_str(&self.0)
38 }
39 }
40
41 impl From<String> for $name {
42 fn from(value: String) -> Self {
43 Self(value)
44 }
45 }
46
47 impl From<&str> for $name {
48 fn from(value: &str) -> Self {
49 Self(value.to_owned())
50 }
51 }
52
53 impl From<$name> for String {
54 fn from(value: $name) -> Self {
55 value.0
56 }
57 }
58
59 impl AsRef<str> for $name {
60 fn as_ref(&self) -> &str {
61 &self.0
62 }
63 }
64
65 impl std::borrow::Borrow<str> for $name {
66 fn borrow(&self) -> &str {
67 &self.0
68 }
69 }
70
71 impl PartialEq<str> for $name {
72 fn eq(&self, other: &str) -> bool {
73 self.0 == other
74 }
75 }
76
77 impl PartialEq<&str> for $name {
78 fn eq(&self, other: &&str) -> bool {
79 self.0 == *other
80 }
81 }
82 };
83}
84
85string_id! {
86 /// Provider identifier, for example `openai.responses` or `anthropic.messages`.
87 ProviderId
88}
89
90string_id! {
91 /// Model identifier as understood by the provider, for example `gpt-5`.
92 ModelId
93}
94
95string_id! {
96 /// Name of a tool as exposed to the model.
97 ToolName
98}
99
100string_id! {
101 /// Identifier of a tool call, assigned by the provider.
102 ToolCallId
103}
104
105string_id! {
106 /// Identifier of a tool approval request.
107 ApprovalId
108}
109
110string_id! {
111 /// Identifier of a provider batch job.
112 BatchId
113}
114
115string_id! {
116 /// Identifier of a text, reasoning or tool-input part within a stream.
117 ///
118 /// Provider-assigned part ids are unique within a single call only; the
119 /// core remaps colliding ids across steps.
120 PartId
121}