1use serde::{Deserialize, Serialize};
4use std::borrow::Borrow;
5use std::fmt;
6use std::ops::Deref;
7use std::path::Path;
8
9macro_rules! define_newtype_string {
10 ($name:ident, $doc:expr) => {
11 #[doc = $doc]
12 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
13 #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
14 #[cfg_attr(feature = "ts", derive(ts_rs::TS))]
15 #[cfg_attr(feature = "flow", derive(flowjs_rs::Flow))]
16 #[cfg_attr(feature = "ts", ts(export))]
17 #[cfg_attr(feature = "flow", flow(export))]
18 #[serde(transparent)]
19 pub struct $name(String);
20
21 impl Deref for $name {
22 type Target = str;
23 #[inline]
24 fn deref(&self) -> &str {
25 &self.0
26 }
27 }
28
29 impl AsRef<str> for $name {
30 #[inline]
31 fn as_ref(&self) -> &str {
32 &self.0
33 }
34 }
35
36 impl Borrow<str> for $name {
37 #[inline]
38 fn borrow(&self) -> &str {
39 &self.0
40 }
41 }
42
43 impl fmt::Display for $name {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.write_str(&self.0)
46 }
47 }
48
49 impl From<String> for $name {
50 #[inline]
51 fn from(s: String) -> Self {
52 Self(s)
53 }
54 }
55
56 impl From<&str> for $name {
57 #[inline]
58 fn from(s: &str) -> Self {
59 Self(s.to_owned())
60 }
61 }
62
63 impl PartialEq<str> for $name {
64 #[inline]
65 fn eq(&self, other: &str) -> bool {
66 self.0 == other
67 }
68 }
69
70 impl PartialEq<&str> for $name {
71 #[inline]
72 fn eq(&self, other: &&str) -> bool {
73 self.0 == *other
74 }
75 }
76
77 impl PartialEq<String> for $name {
78 #[inline]
79 fn eq(&self, other: &String) -> bool {
80 self.0 == *other
81 }
82 }
83 };
84}
85
86define_newtype_string!(NodeKind, "tree-sitter AST node kind identifier.");
87define_newtype_string!(RelativePath, "Source file path relative to project root.");
88
89impl AsRef<Path> for RelativePath {
90 #[inline]
91 fn as_ref(&self) -> &Path {
92 Path::new(&self.0)
93 }
94}