systemprompt_identifiers/
macros.rs1#[macro_export]
2macro_rules! define_id {
3 ($name:ident) => {
4 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
5 #[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
6 #[cfg_attr(feature = "sqlx", sqlx(transparent))]
7 #[serde(transparent)]
8 pub struct $name(String);
9
10 impl $name {
11 pub fn new(id: impl Into<String>) -> Self {
12 Self(id.into())
13 }
14
15 pub fn as_str(&self) -> &str {
16 &self.0
17 }
18 }
19
20 impl From<String> for $name {
21 fn from(s: String) -> Self {
22 Self(s)
23 }
24 }
25
26 impl From<&str> for $name {
27 fn from(s: &str) -> Self {
28 Self(s.to_string())
29 }
30 }
31
32 $crate::__define_id_common!($name);
33 };
34
35 ($name:ident, non_empty) => {
36 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize)]
37 #[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
38 #[cfg_attr(feature = "sqlx", sqlx(transparent))]
39 #[serde(transparent)]
40 pub struct $name(String);
41
42 impl $name {
43 pub fn try_new(value: impl Into<String>) -> Result<Self, $crate::error::IdValidationError> {
44 let value = value.into();
45 if value.is_empty() {
46 return Err($crate::error::IdValidationError::empty(stringify!($name)));
47 }
48 Ok(Self(value))
49 }
50
51 #[allow(clippy::expect_used)]
52 pub fn new(value: impl Into<String>) -> Self {
53 Self::try_new(value).expect(concat!(stringify!($name), " cannot be empty"))
54 }
55
56 pub fn as_str(&self) -> &str {
57 &self.0
58 }
59 }
60
61 $crate::__define_id_validated_conversions!($name);
62 $crate::__define_id_common!($name);
63 };
64
65 ($name:ident, validated, $validator:expr) => {
66 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize)]
67 #[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
68 #[cfg_attr(feature = "sqlx", sqlx(transparent))]
69 #[serde(transparent)]
70 pub struct $name(String);
71
72 impl $name {
73 pub fn try_new(value: impl Into<String>) -> Result<Self, $crate::error::IdValidationError> {
74 let value = value.into();
75 let validator: fn(&str) -> Result<(), $crate::error::IdValidationError> = $validator;
76 validator(&value)?;
77 Ok(Self(value))
78 }
79
80 #[allow(clippy::expect_used)]
81 pub fn new(value: impl Into<String>) -> Self {
82 Self::try_new(value).expect(concat!(stringify!($name), " validation failed"))
83 }
84
85 pub fn as_str(&self) -> &str {
86 &self.0
87 }
88 }
89
90 $crate::__define_id_validated_conversions!($name);
91 $crate::__define_id_common!($name);
92 };
93
94 ($name:ident, generate) => {
95 $crate::define_id!($name);
96
97 impl $name {
98 pub fn generate() -> Self {
99 Self(uuid::Uuid::new_v4().to_string())
100 }
101 }
102 };
103
104 ($name:ident, system) => {
105 $crate::define_id!($name);
106
107 impl $name {
108 pub fn system() -> Self {
109 Self("system".to_string())
110 }
111 }
112 };
113
114 ($name:ident, generate, system) => {
115 $crate::define_id!($name);
116
117 impl $name {
118 pub fn generate() -> Self {
119 Self(uuid::Uuid::new_v4().to_string())
120 }
121
122 pub fn system() -> Self {
123 Self("system".to_string())
124 }
125 }
126 };
127
128 ($name:ident, schema) => {
129 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
130 #[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
131 #[cfg_attr(feature = "sqlx", sqlx(transparent))]
132 #[serde(transparent)]
133 pub struct $name(String);
134
135 impl $name {
136 pub fn new(id: impl Into<String>) -> Self {
137 Self(id.into())
138 }
139
140 pub fn as_str(&self) -> &str {
141 &self.0
142 }
143 }
144
145 impl From<String> for $name {
146 fn from(s: String) -> Self {
147 Self(s)
148 }
149 }
150
151 impl From<&str> for $name {
152 fn from(s: &str) -> Self {
153 Self(s.to_string())
154 }
155 }
156
157 $crate::__define_id_common!($name);
158 };
159
160 ($name:ident, generate, schema) => {
161 $crate::define_id!(@ $name, schema);
162
163 impl $name {
164 pub fn generate() -> Self {
165 Self(uuid::Uuid::new_v4().to_string())
166 }
167 }
168 };
169
170 (@ $name:ident, schema) => {
171 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
172 #[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
173 #[cfg_attr(feature = "sqlx", sqlx(transparent))]
174 #[serde(transparent)]
175 pub struct $name(String);
176
177 impl $name {
178 pub fn new(id: impl Into<String>) -> Self {
179 Self(id.into())
180 }
181
182 pub fn as_str(&self) -> &str {
183 &self.0
184 }
185 }
186
187 impl From<String> for $name {
188 fn from(s: String) -> Self {
189 Self(s)
190 }
191 }
192
193 impl From<&str> for $name {
194 fn from(s: &str) -> Self {
195 Self(s.to_string())
196 }
197 }
198
199 $crate::__define_id_common!($name);
200 };
201}
202
203#[doc(hidden)]
204#[macro_export]
205macro_rules! __define_id_common {
206 ($name:ident) => {
207 impl std::fmt::Display for $name {
208 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 write!(f, "{}", self.0)
210 }
211 }
212
213 impl AsRef<str> for $name {
214 fn as_ref(&self) -> &str {
215 &self.0
216 }
217 }
218
219 impl $crate::ToDbValue for $name {
220 fn to_db_value(&self) -> $crate::DbValue {
221 $crate::DbValue::String(self.0.clone())
222 }
223 }
224
225 impl $crate::ToDbValue for &$name {
226 fn to_db_value(&self) -> $crate::DbValue {
227 $crate::DbValue::String(self.0.clone())
228 }
229 }
230
231 impl From<$name> for String {
232 fn from(id: $name) -> Self {
233 id.0
234 }
235 }
236
237 impl From<&$name> for String {
238 fn from(id: &$name) -> Self {
239 id.0.clone()
240 }
241 }
242
243 impl PartialEq<&str> for $name {
244 fn eq(&self, other: &&str) -> bool {
245 self.0 == *other
246 }
247 }
248
249 impl PartialEq<str> for $name {
250 fn eq(&self, other: &str) -> bool {
251 self.0 == other
252 }
253 }
254
255 impl PartialEq<$name> for &str {
256 fn eq(&self, other: &$name) -> bool {
257 *self == other.0
258 }
259 }
260
261 impl PartialEq<$name> for str {
262 fn eq(&self, other: &$name) -> bool {
263 self == other.0
264 }
265 }
266
267 impl std::borrow::Borrow<str> for $name {
268 fn borrow(&self) -> &str {
269 &self.0
270 }
271 }
272 };
273}
274
275#[doc(hidden)]
276#[macro_export]
277macro_rules! __define_id_validated_conversions {
278 ($name:ident) => {
279 impl TryFrom<String> for $name {
280 type Error = $crate::error::IdValidationError;
281
282 fn try_from(s: String) -> Result<Self, Self::Error> {
283 Self::try_new(s)
284 }
285 }
286
287 impl TryFrom<&str> for $name {
288 type Error = $crate::error::IdValidationError;
289
290 fn try_from(s: &str) -> Result<Self, Self::Error> {
291 Self::try_new(s)
292 }
293 }
294
295 impl std::str::FromStr for $name {
296 type Err = $crate::error::IdValidationError;
297
298 fn from_str(s: &str) -> Result<Self, Self::Err> {
299 Self::try_new(s)
300 }
301 }
302
303 impl<'de> serde::Deserialize<'de> for $name {
304 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
305 where
306 D: serde::Deserializer<'de>,
307 {
308 let s = String::deserialize(deserializer)?;
309 Self::try_new(s).map_err(serde::de::Error::custom)
310 }
311 }
312 };
313}
314
315pub use __define_id_common;
316pub use __define_id_validated_conversions;
317pub use define_id;
318
319#[macro_export]
320macro_rules! define_token {
321 ($name:ident) => {
322 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
323 #[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
324 #[cfg_attr(feature = "sqlx", sqlx(transparent))]
325 #[serde(transparent)]
326 pub struct $name(String);
327
328 impl $name {
329 pub fn new(token: impl Into<String>) -> Self {
330 Self(token.into())
331 }
332
333 pub fn as_str(&self) -> &str {
334 &self.0
335 }
336
337 #[must_use]
338 pub fn redacted(&self) -> String {
339 let len = self.0.len();
340 if len <= 16 {
341 "*".repeat(len.min(8))
342 } else {
343 format!("{}...{}", &self.0[..8], &self.0[len - 4..])
344 }
345 }
346 }
347
348 impl std::fmt::Display for $name {
349 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
350 write!(f, "{}", self.redacted())
351 }
352 }
353
354 impl From<String> for $name {
355 fn from(s: String) -> Self {
356 Self(s)
357 }
358 }
359
360 impl From<&str> for $name {
361 fn from(s: &str) -> Self {
362 Self(s.to_string())
363 }
364 }
365
366 impl AsRef<str> for $name {
367 fn as_ref(&self) -> &str {
368 &self.0
369 }
370 }
371
372 impl $crate::ToDbValue for $name {
373 fn to_db_value(&self) -> $crate::DbValue {
374 $crate::DbValue::String(self.0.clone())
375 }
376 }
377
378 impl $crate::ToDbValue for &$name {
379 fn to_db_value(&self) -> $crate::DbValue {
380 $crate::DbValue::String(self.0.clone())
381 }
382 }
383 };
384}
385
386pub use define_token;