sway_types/
ident.rs

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    /// Returns the identifier as a string, prefixed with `r#` if it is a raw identifier.
31    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
98/// An [Ident] is an _identifier_ with a corresponding `span` from which it was derived.
99/// It relies on a custom implementation of Hash which only looks at its textual name
100/// representation, so that namespacing isn't reliant on the span itself, which will
101/// often be different.
102pub 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/// An [IdentUnique] is an _identifier_ with a corresponding `span` from which it was derived.
149/// Its hash and equality implementation takes the full span into account, meaning that identifiers
150/// are considered unique if they originate from different files.
151#[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}