litcheck_core/diagnostics/
span.rs1use core::{
2 borrow::Borrow,
3 fmt,
4 hash::{Hash, Hasher},
5 ops::{Bound, Deref, DerefMut, Index, RangeBounds},
6};
7
8use serde::{Deserialize, Serialize};
9
10use crate::range::Range;
11
12use super::{ByteIndex, ByteOffset, SourceId};
13
14pub trait Spanned {
16 fn span(&self) -> SourceSpan;
17}
18
19impl Spanned for SourceSpan {
20 #[inline(always)]
21 fn span(&self) -> SourceSpan {
22 *self
23 }
24}
25
26impl<T: ?Sized + Spanned> Spanned for &T {
27 fn span(&self) -> SourceSpan {
28 (**self).span()
29 }
30}
31
32impl<T: ?Sized + Spanned> Spanned for Box<T> {
33 fn span(&self) -> SourceSpan {
34 (**self).span()
35 }
36}
37
38impl<T: ?Sized + Spanned> Spanned for std::rc::Rc<T> {
39 fn span(&self) -> SourceSpan {
40 (**self).span()
41 }
42}
43
44impl<T: ?Sized + Spanned> Spanned for std::sync::Arc<T> {
45 fn span(&self) -> SourceSpan {
46 (**self).span()
47 }
48}
49
50pub struct Span<T> {
56 span: SourceSpan,
57 spanned: T,
58}
59
60impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for Span<T> {
61 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
62 where
63 D: serde::Deserializer<'de>,
64 {
65 let spanned = T::deserialize(deserializer)?;
66 Ok(Self {
67 span: SourceSpan::UNKNOWN,
68 spanned,
69 })
70 }
71}
72
73impl<T: serde::Serialize> serde::Serialize for Span<T> {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: serde::Serializer,
77 {
78 T::serialize(&self.spanned, serializer)
79 }
80}
81
82impl<T> Spanned for Span<T> {
83 fn span(&self) -> SourceSpan {
84 self.span
85 }
86}
87
88impl<T: Copy> Copy for Span<T> {}
89
90impl<T: Clone> Clone for Span<T> {
91 fn clone(&self) -> Self {
92 Self {
93 span: self.span,
94 spanned: self.spanned.clone(),
95 }
96 }
97}
98
99impl<T: Default> Default for Span<T> {
100 fn default() -> Self {
101 Self {
102 span: SourceSpan::UNKNOWN,
103 spanned: T::default(),
104 }
105 }
106}
107
108impl<T> Span<T> {
109 #[inline]
111 pub fn new(span: SourceSpan, spanned: T) -> Self {
112 Self { span, spanned }
113 }
114
115 #[inline]
117 pub fn at(source_id: SourceId, offset: usize, spanned: T) -> Self {
118 let offset = u32::try_from(offset).expect("invalid source offset: too large");
119 Self {
120 span: SourceSpan::at(source_id, offset),
121 spanned,
122 }
123 }
124
125 pub fn unknown(spanned: T) -> Self {
127 Self {
128 span: Default::default(),
129 spanned,
130 }
131 }
132
133 #[inline]
135 pub fn with_span(mut self, span: SourceSpan) -> Self {
136 self.span = span;
137 self
138 }
139
140 #[inline(always)]
142 pub const fn span(&self) -> SourceSpan {
143 self.span
144 }
145
146 #[inline(always)]
148 pub const fn inner(&self) -> &T {
149 &self.spanned
150 }
151
152 #[inline]
154 pub fn map<U, F>(self, mut f: F) -> Span<U>
155 where
156 F: FnMut(T) -> U,
157 {
158 Span {
159 span: self.span,
160 spanned: f(self.spanned),
161 }
162 }
163
164 pub fn as_deref<U>(&self) -> Span<&U>
167 where
168 U: ?Sized,
169 T: Deref<Target = U>,
170 {
171 Span {
172 span: self.span,
173 spanned: self.spanned.deref(),
174 }
175 }
176
177 pub fn as_ref(&self) -> Span<&T> {
179 Span {
180 span: self.span,
181 spanned: &self.spanned,
182 }
183 }
184
185 pub fn set_source_id(&mut self, id: SourceId) {
189 self.span.set_source_id(id);
190 }
191
192 #[inline]
194 pub fn shift(&mut self, count: ByteOffset) {
195 self.span.start += count;
196 self.span.end += count;
197 }
198
199 #[inline]
201 pub fn extend(&mut self, count: ByteOffset) {
202 self.span.end += count;
203 }
204
205 #[inline]
208 pub fn into_parts(self) -> (SourceSpan, T) {
209 (self.span, self.spanned)
210 }
211
212 #[inline]
214 pub fn into_inner(self) -> T {
215 self.spanned
216 }
217}
218
219impl<T> Borrow<T> for Span<T> {
220 fn borrow(&self) -> &T {
221 &self.spanned
222 }
223}
224
225impl<T: Borrow<str>> Borrow<str> for Span<T> {
226 fn borrow(&self) -> &str {
227 self.spanned.borrow()
228 }
229}
230
231impl<U, T: Borrow<[U]>> Borrow<[U]> for Span<T> {
232 fn borrow(&self) -> &[U] {
233 self.spanned.borrow()
234 }
235}
236
237impl<T> Deref for Span<T> {
238 type Target = T;
239
240 #[inline(always)]
241 fn deref(&self) -> &Self::Target {
242 &self.spanned
243 }
244}
245
246impl<T> DerefMut for Span<T> {
247 #[inline(always)]
248 fn deref_mut(&mut self) -> &mut Self::Target {
249 &mut self.spanned
250 }
251}
252
253impl<T: ?Sized, U: AsRef<T>> AsRef<T> for Span<U> {
254 fn as_ref(&self) -> &T {
255 self.spanned.as_ref()
256 }
257}
258
259impl<T: ?Sized, U: AsMut<T>> AsMut<T> for Span<U> {
260 fn as_mut(&mut self) -> &mut T {
261 self.spanned.as_mut()
262 }
263}
264
265impl<T: fmt::Debug> fmt::Debug for Span<T> {
266 #[inline]
267 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
268 fmt::Debug::fmt(&self.spanned, f)
269 }
270}
271
272impl<T: fmt::Display> fmt::Display for Span<T> {
273 #[inline]
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 fmt::Display::fmt(&self.spanned, f)
276 }
277}
278
279impl<T: Eq> Eq for Span<T> {}
280
281impl<T: PartialEq> PartialEq for Span<T> {
282 #[inline]
283 fn eq(&self, other: &Self) -> bool {
284 self.spanned.eq(&other.spanned)
285 }
286}
287
288impl<T: PartialEq> PartialEq<T> for Span<T> {
289 #[inline]
290 fn eq(&self, other: &T) -> bool {
291 self.spanned.eq(other)
292 }
293}
294
295impl<T: Ord> Ord for Span<T> {
296 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
297 self.spanned.cmp(&other.spanned)
298 }
299}
300
301impl<T: PartialOrd> PartialOrd for Span<T> {
302 #[inline]
303 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
304 self.spanned.partial_cmp(&other.spanned)
305 }
306}
307
308impl<T: Hash> Hash for Span<T> {
309 fn hash<H: Hasher>(&self, state: &mut H) {
310 self.spanned.hash(state);
311 }
312}
313
314#[derive(
329 Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
330)]
331pub struct SourceSpan {
332 #[serde(default, skip_serializing_if = "SourceId::is_unknown")]
333 source_id: SourceId,
334 start: ByteIndex,
335 end: ByteIndex,
336}
337
338#[derive(Debug, thiserror::Error)]
339#[error("invalid byte index range: maximum supported byte index is 2^32")]
340pub struct InvalidByteIndexRange;
341
342impl SourceSpan {
343 pub const UNKNOWN: Self = Self {
345 source_id: SourceId::UNKNOWN,
346 start: ByteIndex::new(0),
347 end: ByteIndex::new(0),
348 };
349
350 pub fn new<B>(source_id: SourceId, range: Range<B>) -> Self
352 where
353 B: Into<ByteIndex>,
354 {
355 Self {
356 source_id,
357 start: range.start.into(),
358 end: range.end.into(),
359 }
360 }
361
362 pub fn at(source_id: SourceId, offset: impl Into<ByteIndex>) -> Self {
364 let offset = offset.into();
365 Self {
366 source_id,
367 start: offset,
368 end: offset,
369 }
370 }
371
372 pub fn try_from_range(
374 source_id: SourceId,
375 range: core::ops::Range<usize>,
376 ) -> Result<Self, InvalidByteIndexRange> {
377 const MAX: usize = u32::MAX as usize;
378 if range.start > MAX || range.end > MAX {
379 return Err(InvalidByteIndexRange);
380 }
381
382 Ok(SourceSpan::from_range_unchecked(source_id, range))
383 }
384
385 #[inline]
388 pub fn from_range_unchecked(source_id: SourceId, range: core::ops::Range<usize>) -> Self {
389 SourceSpan {
390 source_id,
391 start: ByteIndex::from(range.start as u32),
392 end: ByteIndex::from(range.end as u32),
393 }
394 }
395
396 pub const fn is_unknown(&self) -> bool {
398 self.source_id.is_unknown()
399 }
400
401 #[inline(always)]
403 pub fn source_id(&self) -> SourceId {
404 self.source_id
405 }
406
407 pub fn set_source_id(&mut self, id: SourceId) {
414 self.source_id = id;
415 }
416
417 #[inline(always)]
419 pub fn start(&self) -> ByteIndex {
420 self.start
421 }
422
423 #[inline(always)]
425 pub fn end(&self) -> ByteIndex {
426 self.end
427 }
428
429 #[inline(always)]
431 pub fn len(&self) -> usize {
432 self.end.to_usize() - self.start.to_usize()
433 }
434
435 pub fn is_empty(&self) -> bool {
437 self.len() == 0
438 }
439
440 #[inline]
442 pub fn into_range(self) -> Range<u32> {
443 Range::new(self.start.to_u32(), self.end.to_u32())
444 }
445
446 #[inline]
448 pub fn into_slice_index(self) -> Range<usize> {
449 Range::new(self.start.to_usize(), self.end.to_usize())
450 }
451}
452
453impl From<SourceSpan> for miette::SourceSpan {
454 fn from(span: SourceSpan) -> Self {
455 Self::new(
456 miette::SourceOffset::from(span.start().to_usize()),
457 span.len(),
458 )
459 }
460}
461
462impl From<SourceSpan> for Range<u32> {
463 #[inline(always)]
464 fn from(span: SourceSpan) -> Self {
465 span.into_range()
466 }
467}
468
469impl From<SourceSpan> for Range<usize> {
470 #[inline(always)]
471 fn from(span: SourceSpan) -> Self {
472 span.into_slice_index()
473 }
474}
475
476impl From<SourceSpan> for core::ops::Range<u32> {
477 fn from(value: SourceSpan) -> Self {
478 value.start.to_u32()..value.end.to_u32()
479 }
480}
481
482impl From<SourceSpan> for core::ops::Range<usize> {
483 fn from(value: SourceSpan) -> Self {
484 value.start.to_usize()..value.end.to_usize()
485 }
486}
487
488impl Index<SourceSpan> for [u8] {
489 type Output = [u8];
490
491 #[inline]
492 fn index(&self, index: SourceSpan) -> &Self::Output {
493 &self[index.start().to_usize()..index.end().to_usize()]
494 }
495}
496
497impl RangeBounds<ByteIndex> for SourceSpan {
498 #[inline(always)]
499 fn start_bound(&self) -> Bound<&ByteIndex> {
500 Bound::Included(&self.start)
501 }
502
503 #[inline(always)]
504 fn end_bound(&self) -> Bound<&ByteIndex> {
505 Bound::Excluded(&self.end)
506 }
507}