1use super::Box;
2use solar_data_structures::smallvec::SmallVec;
3use solar_interface::{Ident, Span, Symbol};
4use std::fmt;
5
6pub type AstPath<'ast> = Box<'ast, PathSlice>;
8
9#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[repr(transparent)]
14pub struct PathSlice([Ident]);
15
16impl ToOwned for PathSlice {
17 type Owned = Path;
18
19 #[inline]
20 fn to_owned(&self) -> Self::Owned {
21 Path::new(&self.0)
22 }
23}
24
25impl fmt::Debug for PathSlice {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 fmt::Display::fmt(self, f)
28 }
29}
30
31impl fmt::Display for PathSlice {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 for (i, ident) in self.segments().iter().enumerate() {
34 if i != 0 {
35 f.write_str(".")?;
36 }
37 write!(f, "{ident}")?;
38 }
39 Ok(())
40 }
41}
42
43impl PartialEq<Ident> for PathSlice {
44 fn eq(&self, other: &Ident) -> bool {
45 match self.get_ident() {
46 Some(ident) => ident == other,
47 None => false,
48 }
49 }
50}
51
52impl PartialEq<Symbol> for PathSlice {
53 fn eq(&self, other: &Symbol) -> bool {
54 match self.get_ident() {
55 Some(ident) => ident.name == *other,
56 None => false,
57 }
58 }
59}
60
61impl PathSlice {
62 #[inline]
64 pub fn from_ref(segment: &Ident) -> &Self {
65 unsafe { Self::from_slice_unchecked(std::slice::from_ref(segment)) }
66 }
67
68 #[inline]
70 pub fn from_mut(segment: &mut Ident) -> &mut Self {
71 unsafe { Self::from_mut_slice_unchecked(std::slice::from_mut(segment)) }
72 }
73
74 #[inline]
80 pub fn from_slice(segments: &[Ident]) -> &Self {
81 if segments.is_empty() {
82 panic_empty_path();
83 }
84 unsafe { Self::from_slice_unchecked(segments) }
86 }
87
88 #[inline]
94 pub unsafe fn from_slice_unchecked(segments: &[Ident]) -> &Self {
95 debug_assert!(!segments.is_empty());
96 unsafe { &*(segments as *const _ as *const Self) }
98 }
99
100 #[inline]
106 pub fn from_mut_slice(segments: &mut [Ident]) -> &mut Self {
107 assert!(!segments.is_empty());
108 unsafe { Self::from_mut_slice_unchecked(segments) }
110 }
111
112 #[inline]
118 pub unsafe fn from_mut_slice_unchecked(segments: &mut [Ident]) -> &mut Self {
119 unsafe { &mut *(segments as *mut _ as *mut Self) }
121 }
122
123 #[inline]
125 #[cfg_attr(debug_assertions, track_caller)]
126 pub fn span(&self) -> Span {
127 match self.segments() {
128 [] => panic_empty_path(),
129 [ident] => ident.span,
130 [first, .., last] => first.span.with_hi(last.span.hi()),
131 }
132 }
133
134 #[inline]
136 pub fn segments(&self) -> &[Ident] {
137 &self.0
138 }
139
140 #[inline]
142 pub fn segments_mut(&mut self) -> &mut [Ident] {
143 &mut self.0
144 }
145
146 #[inline]
148 pub fn get_ident(&self) -> Option<&Ident> {
149 match self.segments() {
150 [ident] => Some(ident),
151 _ => None,
152 }
153 }
154
155 #[inline]
157 pub fn get_ident_mut(&mut self) -> Option<&mut Ident> {
158 match self.segments_mut() {
159 [ident] => Some(ident),
160 _ => None,
161 }
162 }
163
164 #[inline]
166 #[cfg_attr(debug_assertions, track_caller)]
167 pub fn first(&self) -> &Ident {
168 self.segments().first().unwrap_or_else(|| panic_empty_path())
169 }
170
171 #[inline]
173 #[cfg_attr(debug_assertions, track_caller)]
174 pub fn first_mut(&mut self) -> &mut Ident {
175 self.segments_mut().first_mut().unwrap_or_else(|| panic_empty_path())
176 }
177
178 #[inline]
180 #[cfg_attr(debug_assertions, track_caller)]
181 pub fn last(&self) -> &Ident {
182 self.segments().last().unwrap_or_else(|| panic_empty_path())
183 }
184
185 #[inline]
187 #[cfg_attr(debug_assertions, track_caller)]
188 pub fn last_mut(&mut self) -> &mut Ident {
189 self.segments_mut().last_mut().unwrap_or_else(|| panic_empty_path())
190 }
191}
192
193#[inline(never)]
194#[cold]
195#[cfg_attr(debug_assertions, track_caller)]
196fn panic_empty_path() -> ! {
197 panic!("paths cannot be empty");
198}
199
200#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
204pub struct Path(SmallVec<[Ident; 1]>);
205
206impl fmt::Debug for Path {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 fmt::Debug::fmt(self.as_slice(), f)
209 }
210}
211
212impl fmt::Display for Path {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 fmt::Display::fmt(self.as_slice(), f)
215 }
216}
217
218impl PartialEq<Ident> for Path {
219 fn eq(&self, other: &Ident) -> bool {
220 PartialEq::eq(self.as_slice(), other)
221 }
222}
223
224impl PartialEq<Symbol> for Path {
225 fn eq(&self, other: &Symbol) -> bool {
226 PartialEq::eq(self.as_slice(), other)
227 }
228}
229
230impl FromIterator<Ident> for Path {
231 fn from_iter<T: IntoIterator<Item = Ident>>(iter: T) -> Self {
237 let mut iter = iter.into_iter();
238 let first = iter.next().expect("paths cannot be empty");
239 match iter.next() {
240 Some(second) => Self(SmallVec::from_iter([first, second].into_iter().chain(iter))),
241 None => Self::new_single(first),
242 }
243 }
244}
245
246impl std::ops::Deref for Path {
247 type Target = PathSlice;
248
249 #[inline]
250 fn deref(&self) -> &Self::Target {
251 self.as_slice()
252 }
253}
254
255impl std::ops::DerefMut for Path {
256 #[inline]
257 fn deref_mut(&mut self) -> &mut Self::Target {
258 self.as_mut_slice()
259 }
260}
261
262impl std::borrow::Borrow<PathSlice> for Path {
263 #[inline]
264 fn borrow(&self) -> &PathSlice {
265 self.as_slice()
266 }
267}
268
269impl Path {
270 #[inline]
276 pub fn new(segments: &[Ident]) -> Self {
277 assert!(!segments.is_empty());
278 Self(SmallVec::from_slice(segments))
279 }
280
281 #[inline]
287 pub fn from_vec(segments: Vec<Ident>) -> Self {
288 assert!(!segments.is_empty());
289 Self(SmallVec::from_vec(segments))
290 }
291
292 #[inline]
298 pub fn from_ast(ast: AstPath<'_>) -> Self {
299 Self::new(ast.segments())
300 }
301
302 #[inline]
304 pub fn new_single(ident: Ident) -> Self {
305 Self(SmallVec::from_buf_and_len([ident], 1))
306 }
307
308 #[inline]
310 pub fn as_slice(&self) -> &PathSlice {
311 unsafe { PathSlice::from_slice_unchecked(&self.0) }
312 }
313
314 #[inline]
316 pub fn as_mut_slice(&mut self) -> &mut PathSlice {
317 unsafe { PathSlice::from_mut_slice_unchecked(&mut self.0) }
318 }
319}