Skip to main content

steel_parser/
span.rs

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        // TODO: If this doesn't seem to make sense with macros, we can revisit
62        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}