styx_parse/
span.rs

1//! Span tracking for source locations.
2
3/// A span representing a range in the source text.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5#[cfg_attr(feature = "facet", derive(facet::Facet))]
6pub struct Span {
7    /// Byte offset of the start (inclusive)
8    pub start: u32,
9    /// Byte offset of the end (exclusive)
10    pub end: u32,
11}
12
13impl Span {
14    /// Create a new span from start and end byte offsets.
15    #[inline]
16    pub fn new(start: u32, end: u32) -> Self {
17        debug_assert!(start <= end);
18        Self { start, end }
19    }
20
21    /// Create an empty span at a position.
22    #[inline]
23    pub fn empty(pos: u32) -> Self {
24        Self {
25            start: pos,
26            end: pos,
27        }
28    }
29
30    /// Length of this span in bytes.
31    #[inline]
32    pub fn len(&self) -> u32 {
33        self.end - self.start
34    }
35
36    /// Whether this span is empty.
37    #[inline]
38    pub fn is_empty(&self) -> bool {
39        self.start == self.end
40    }
41
42    /// Extend this span to include another span.
43    #[inline]
44    pub fn extend(&self, other: Span) -> Span {
45        Span {
46            start: self.start.min(other.start),
47            end: self.end.max(other.end),
48        }
49    }
50
51    /// Get the source text for this span.
52    #[inline]
53    pub fn slice<'a>(&self, source: &'a str) -> &'a str {
54        &source[self.start as usize..self.end as usize]
55    }
56}
57
58impl From<std::ops::Range<u32>> for Span {
59    fn from(range: std::ops::Range<u32>) -> Self {
60        Span::new(range.start, range.end)
61    }
62}
63
64impl From<Span> for std::ops::Range<usize> {
65    fn from(span: Span) -> Self {
66        span.start as usize..span.end as usize
67    }
68}