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