1use crate::{span::Span, Spanned};
2use serde::{Deserialize, Serialize};
3use std::{
4 borrow::Cow,
5 cmp::{Ord, Ordering},
6 fmt,
7 hash::{Hash, Hasher},
8 sync::Arc,
9};
10
11pub trait Named {
12 fn name(&self) -> &BaseIdent;
13}
14
15#[derive(Clone, Serialize, Deserialize)]
16pub struct BaseIdent {
17 name_override_opt: Option<Arc<String>>,
18 span: Span,
19 is_raw_ident: bool,
20}
21
22impl BaseIdent {
23 pub fn as_str(&self) -> &str {
24 self.name_override_opt
25 .as_deref()
26 .map(|x| x.as_str())
27 .unwrap_or_else(|| self.span.as_str())
28 }
29
30 pub fn as_raw_ident_str(&self) -> Cow<str> {
32 if self.is_raw_ident {
33 Cow::Owned(format!("r#{}", self.as_str()))
34 } else {
35 Cow::Borrowed(self.as_str())
36 }
37 }
38
39 pub fn is_raw_ident(&self) -> bool {
40 self.is_raw_ident
41 }
42
43 pub fn name_override_opt(&self) -> Option<&str> {
44 self.name_override_opt.as_deref().map(|x| x.as_str())
45 }
46
47 pub fn new(span: Span) -> Ident {
48 let span = span.trim();
49 Ident {
50 name_override_opt: None,
51 span,
52 is_raw_ident: false,
53 }
54 }
55
56 pub fn new_no_trim(span: Span) -> Ident {
57 Ident {
58 name_override_opt: None,
59 span,
60 is_raw_ident: false,
61 }
62 }
63
64 pub fn new_with_raw(span: Span, is_raw_ident: bool) -> Ident {
65 let span = span.trim();
66 Ident {
67 name_override_opt: None,
68 span,
69 is_raw_ident,
70 }
71 }
72
73 pub fn new_with_override(name_override: String, span: Span) -> Ident {
74 Ident {
75 name_override_opt: Some(Arc::new(name_override)),
76 span,
77 is_raw_ident: false,
78 }
79 }
80
81 pub fn new_no_span(name: String) -> Ident {
82 Ident {
83 name_override_opt: Some(Arc::new(name)),
84 span: Span::dummy(),
85 is_raw_ident: false,
86 }
87 }
88
89 pub fn dummy() -> Ident {
90 Ident {
91 name_override_opt: Some(Arc::new("foo".into())),
92 span: Span::dummy(),
93 is_raw_ident: false,
94 }
95 }
96}
97
98pub type Ident = BaseIdent;
103
104impl Hash for Ident {
105 fn hash<H: Hasher>(&self, state: &mut H) {
106 self.as_str().hash(state);
107 }
108}
109
110impl PartialEq for Ident {
111 fn eq(&self, other: &Self) -> bool {
112 self.as_str() == other.as_str()
113 }
114}
115
116impl Ord for Ident {
117 fn cmp(&self, other: &Self) -> Ordering {
118 self.as_str().cmp(other.as_str())
119 }
120}
121
122impl PartialOrd for Ident {
123 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
124 Some(self.cmp(other))
125 }
126}
127
128impl Eq for Ident {}
129
130impl Spanned for Ident {
131 fn span(&self) -> Span {
132 self.span.clone()
133 }
134}
135
136impl fmt::Display for Ident {
137 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
138 write!(formatter, "{}", self.as_str())
139 }
140}
141
142impl fmt::Debug for Ident {
143 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
144 write!(formatter, "{}", self.as_str())
145 }
146}
147
148#[derive(Debug, Clone)]
152pub struct IdentUnique(BaseIdent);
153
154impl From<Ident> for IdentUnique {
155 fn from(item: Ident) -> Self {
156 IdentUnique(item)
157 }
158}
159
160impl From<&Ident> for IdentUnique {
161 fn from(item: &Ident) -> Self {
162 IdentUnique(item.clone())
163 }
164}
165
166impl From<&IdentUnique> for Ident {
167 fn from(item: &IdentUnique) -> Self {
168 Ident {
169 name_override_opt: item.0.name_override_opt().map(|s| Arc::new(s.to_string())),
170 span: item.0.span(),
171 is_raw_ident: item.0.is_raw_ident(),
172 }
173 }
174}
175
176impl std::ops::Deref for IdentUnique {
177 type Target = Ident;
178 fn deref(&self) -> &Self::Target {
179 &self.0
180 }
181}
182
183impl Hash for IdentUnique {
184 fn hash<H: Hasher>(&self, state: &mut H) {
185 self.0.span().hash(state);
186 self.0.as_str().hash(state);
187 }
188}
189
190impl PartialEq for IdentUnique {
191 fn eq(&self, other: &Self) -> bool {
192 self.0.as_str() == other.0.as_str() && self.0.span() == other.0.span()
193 }
194}
195
196impl Eq for IdentUnique {}
197
198impl Spanned for IdentUnique {
199 fn span(&self) -> Span {
200 self.0.span()
201 }
202}
203
204impl fmt::Display for IdentUnique {
205 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
206 write!(formatter, "{}", self.0.as_str())
207 }
208}