Skip to main content

rustyfi_syntax/
span.rs

1/// A source location. `line` is 1-based, `col` is a 0-based character column,
2/// `byte` is the byte offset into the source.
3#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
4pub struct Loc {
5    pub line: u32,
6    pub col: u32,
7    pub byte: usize,
8}
9
10/// A half-open source range `[start, end)`.
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
12pub struct Span {
13    pub start: Loc,
14    pub end: Loc,
15}
16
17impl Span {
18    pub(crate) fn new(start: Loc, end: Loc) -> Self {
19        Span { start, end }
20    }
21
22    /// The smallest span covering both `self` and `other` (Range.unite).
23    pub fn unite(self, other: Span) -> Span {
24        let dummy = Span::default();
25        if self == dummy {
26            return other;
27        }
28        if other == dummy {
29            return self;
30        }
31        let start = if self.start.byte <= other.start.byte {
32            self.start
33        } else {
34            other.start
35        };
36        let end = if self.end.byte >= other.end.byte {
37            self.end
38        } else {
39            other.end
40        };
41        Span { start, end }
42    }
43}
44
45impl syan::span::Span for Span {
46    fn migrate(self, other: Self) -> Self {
47        self.unite(other)
48    }
49}
50
51impl std::fmt::Display for Span {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        if self.start.line == self.end.line {
54            write!(
55                f,
56                "line {}, characters {}-{}",
57                self.start.line, self.start.col, self.end.col
58            )
59        } else {
60            write!(
61                f,
62                "line {}, character {} to line {}, character {}",
63                self.start.line, self.start.col, self.end.line, self.end.col
64            )
65        }
66    }
67}