1use crate::{BytePos, SessionGlobals};
2use std::{
3 cmp, fmt,
4 ops::{Deref, DerefMut, Range},
5};
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash)]
19#[repr(Rust, packed(4))]
20pub struct Span {
21 data: u64,
26}
27
28impl Default for Span {
29 #[inline(always)]
30 fn default() -> Self {
31 Self::DUMMY
32 }
33}
34
35impl Default for &Span {
36 #[inline(always)]
37 fn default() -> Self {
38 &Span::DUMMY
39 }
40}
41
42impl fmt::Debug for Span {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 fn fallback(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 write!(f, "Span({lo}..{hi})", lo = span.lo().0, hi = span.hi().0)
49 }
50
51 if SessionGlobals::is_set() {
52 SessionGlobals::with(|g| {
53 let sm = &g.source_map;
54 if !sm.is_empty() {
55 write!(f, "{}", sm.span_to_diagnostic_string(*self))
56 } else {
57 fallback(*self, f)
58 }
59 })
60 } else {
61 fallback(*self, f)
62 }
63 }
64}
65
66impl PartialOrd for Span {
67 #[inline]
68 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
69 Some(self.cmp(other))
70 }
71}
72
73impl Ord for Span {
74 #[inline]
75 fn cmp(&self, other: &Self) -> cmp::Ordering {
76 self.lo().cmp(&other.lo()).then(self.hi().cmp(&other.hi()))
77 }
78}
79
80impl Span {
81 pub const DUMMY: Self = Self::new_(BytePos(0), BytePos(0));
83
84 #[inline]
86 pub fn new(mut lo: BytePos, mut hi: BytePos) -> Self {
87 if lo > hi {
88 std::mem::swap(&mut lo, &mut hi);
89 }
90 Self::new_(lo, hi)
91 }
92
93 #[inline]
99 #[cfg_attr(debug_assertions, track_caller)]
100 pub fn new_unchecked(lo: BytePos, hi: BytePos) -> Self {
101 debug_assert!(lo <= hi, "creating span with lo {lo:?} > hi {hi:?}");
102 Self::new_(lo, hi)
103 }
104
105 #[inline(always)]
106 const fn new_(lo: BytePos, hi: BytePos) -> Self {
107 Self { data: (lo.0 as u64) | ((hi.0 as u64) << 32) }
108 }
109
110 #[inline]
115 pub fn to_range(self) -> Range<usize> {
116 self.lo().to_usize()..self.hi().to_usize()
117 }
118
119 #[inline]
124 pub fn to_u32_range(self) -> Range<u32> {
125 self.lo().to_u32()..self.hi().to_u32()
126 }
127
128 #[inline(always)]
133 pub fn lo(self) -> BytePos {
134 BytePos(self.data as u32)
135 }
136
137 #[inline]
139 pub fn with_lo(self, lo: BytePos) -> Self {
140 Self::new(lo, self.hi())
141 }
142
143 #[inline(always)]
148 pub fn hi(self) -> BytePos {
149 BytePos((self.data >> 32) as u32)
150 }
151
152 #[inline]
154 pub fn with_hi(self, hi: BytePos) -> Self {
155 Self::new(self.lo(), hi)
156 }
157
158 #[inline]
160 pub fn shrink_to_lo(self) -> Self {
161 Self::new(self.lo(), self.lo())
162 }
163
164 #[inline]
166 pub fn shrink_to_hi(self) -> Self {
167 Self::new(self.hi(), self.hi())
168 }
169
170 #[inline]
172 pub fn is_dummy(self) -> bool {
173 self == Self::DUMMY
174 }
175
176 #[inline]
178 pub fn contains(self, other: Self) -> bool {
179 self.lo() <= other.lo() && other.hi() <= self.hi()
180 }
181
182 #[inline]
184 pub fn overlaps(self, other: Self) -> bool {
185 self.lo() < other.hi() && other.lo() < self.hi()
186 }
187
188 #[inline]
190 pub fn is_empty(self, other: Self) -> bool {
191 self.lo() == other.lo() && self.hi() == other.hi()
192 }
193
194 #[inline]
196 pub fn split_at(self, pos: u32) -> (Self, Self) {
197 let len = self.hi().0 - self.lo().0;
198 debug_assert!(pos <= len);
199
200 let split_pos = BytePos(self.lo().0 + pos);
201 (Self::new(self.lo(), split_pos), Self::new(split_pos, self.hi()))
202 }
203
204 #[inline]
215 pub fn to(self, end: Self) -> Self {
216 Self::new(cmp::min(self.lo(), end.lo()), cmp::max(self.hi(), end.hi()))
217 }
218
219 #[inline]
227 pub fn between(self, end: Self) -> Self {
228 Self::new(self.hi(), end.lo())
229 }
230
231 #[inline]
239 pub fn until(self, end: Self) -> Self {
240 Self::new(self.lo(), end.lo())
241 }
242
243 #[inline]
247 pub fn join_many(spans: impl IntoIterator<Item = Self>) -> Self {
248 spans.into_iter().reduce(Self::to).unwrap_or_default()
249 }
250
251 #[inline]
255 pub fn join_first_last(
256 spans: impl IntoIterator<Item = Self, IntoIter: DoubleEndedIterator>,
257 ) -> Self {
258 let mut spans = spans.into_iter();
259 let first = spans.next().unwrap_or_default();
260 if let Some(last) = spans.next_back() { first.to(last) } else { first }
261 }
262}
263
264#[derive(Clone, Copy, Debug, Default)]
269pub struct Spanned<T> {
270 pub span: Span,
271 pub data: T,
272}
273
274impl<T> Deref for Spanned<T> {
275 type Target = T;
276
277 fn deref(&self) -> &Self::Target {
278 &self.data
279 }
280}
281
282impl<T> DerefMut for Spanned<T> {
283 fn deref_mut(&mut self) -> &mut Self::Target {
284 &mut self.data
285 }
286}
287
288impl<T> Spanned<T> {
289 pub fn map<U, F>(self, f: F) -> Spanned<U>
290 where
291 F: FnOnce(T) -> U,
292 {
293 Spanned { span: self.span, data: f(self.data) }
294 }
295
296 pub fn as_ref(&self) -> Spanned<&T> {
297 Spanned { span: self.span, data: &self.data }
298 }
299
300 pub fn as_mut(&mut self) -> Spanned<&mut T> {
301 Spanned { span: self.span, data: &mut self.data }
302 }
303
304 pub fn into_inner(self) -> T {
305 self.data
306 }
307}
308
309#[derive(Clone, Copy, Debug)]
317pub enum SpannedOption<T> {
318 Some(T),
319 None(Span),
320}
321
322impl<T> SpannedOption<T> {
323 pub fn is_none(&self) -> bool {
325 matches!(&self, Self::None(_))
326 }
327
328 pub fn is_some(&self) -> bool {
330 matches!(&self, Self::Some(_))
331 }
332
333 pub fn unspan(self) -> Option<T> {
335 match self {
336 Self::Some(value) => Some(value),
337 Self::None(_) => None,
338 }
339 }
340
341 pub fn map<U, F>(self, f: F) -> SpannedOption<U>
343 where
344 F: FnOnce(T) -> U,
345 {
346 match self {
347 Self::Some(value) => SpannedOption::Some(f(value)),
348 Self::None(span) => SpannedOption::None(span),
349 }
350 }
351
352 pub fn as_ref(&self) -> SpannedOption<&T> {
354 match &self {
355 Self::Some(value) => SpannedOption::Some(value),
356 Self::None(span) => SpannedOption::None(*span),
357 }
358 }
359}
360
361impl<T: Deref> SpannedOption<T> {
362 pub fn as_deref(&self) -> SpannedOption<&<T as Deref>::Target> {
364 self.as_ref().map(Deref::deref)
365 }
366}
367
368impl<T> From<SpannedOption<T>> for Option<T> {
369 fn from(spanned: SpannedOption<T>) -> Self {
370 spanned.unspan()
371 }
372}