1use core::fmt;
2use core::ops::Range;
3use serde::{Deserialize, Serialize};
4
5use super::parser::SourceId;
6
7#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
8#[repr(C)]
9pub struct Span {
10 pub start: u32,
11 pub end: u32,
12 pub source_id: Option<SourceId>,
13}
14
15impl Span {
16 #[inline]
17 pub const fn new(start: u32, end: u32, source_id: Option<SourceId>) -> Self {
18 Self {
19 start,
20 end,
21 source_id,
22 }
23 }
24
25 #[inline]
26 pub const fn double(span: u32, source_id: Option<SourceId>) -> Self {
27 Self {
28 start: span,
29 end: span,
30 source_id,
31 }
32 }
33
34 #[inline]
35 pub const fn start(&self) -> u32 {
36 self.start
37 }
38
39 #[inline]
40 pub const fn end(&self) -> u32 {
41 self.end
42 }
43
44 #[inline]
45 pub const fn range(&self) -> Range<u32> {
46 self.start..self.end
47 }
48
49 #[inline]
50 pub const fn usize_range(&self) -> Range<usize> {
51 self.start as _..self.end as _
52 }
53
54 #[inline]
55 pub const fn source_id(&self) -> Option<SourceId> {
56 self.source_id
57 }
58
59 #[inline]
60 pub const fn merge(start: Self, end: Self) -> Span {
61 Self::new(start.start, end.end, start.source_id)
63 }
64
65 #[inline]
66 pub const fn width(&self) -> u32 {
67 self.end - self.start
68 }
69
70 pub fn coalesce_span(spans: &[Span]) -> Span {
71 let span = spans.first();
72 if let Some(span) = span {
73 let mut span = *span;
74 for s in spans {
75 if s.start() < span.start() {
76 span = Span::new(s.start(), span.end(), s.source_id);
77 }
78 if s.end() > span.end() {
79 span = Span::new(span.start(), s.end(), s.source_id);
80 }
81 }
82 span
83 } else {
84 Span::new(0, 0, None)
85 }
86 }
87}
88
89impl fmt::Debug for Span {
90 #[inline]
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 write!(f, "{}..{}", self.start, self.end)
93 }
94}
95
96impl From<Span> for Range<u32> {
97 fn from(span: Span) -> Self {
98 span.start..span.end
99 }
100}
101
102impl From<Span> for Range<usize> {
103 fn from(span: Span) -> Self {
104 span.start as usize..span.end as usize
105 }
106}
107
108impl From<Span> for (u32, u32) {
109 fn from(span: Span) -> Self {
110 (span.start, span.end)
111 }
112}
113
114impl From<Span> for [u32; 2] {
115 fn from(span: Span) -> Self {
116 [span.start, span.end]
117 }
118}