sway_types/
ident.rs

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
88/// An [Ident] is an _identifier_ with a corresponding `span` from which it was derived.
89/// It relies on a custom implementation of Hash which only looks at its textual name
90/// representation, so that namespacing isn't reliant on the span itself, which will
91/// often be different.
92pub 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/// An [IdentUnique] is an _identifier_ with a corresponding `span` from which it was derived.
139/// Its hash and equality implementation takes the full span into account, meaning that identifiers
140/// are considered unique if they originate from different files.
141#[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}