Skip to main content

knave_expand/source/
span.rs

1use std::ops::Range;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
4pub struct SourceId(u32);
5
6impl SourceId {
7    const PINNED: u32 = 1 << 31;
8
9    pub fn new(index: usize) -> Self {
10        let id = u32::try_from(index).expect("fewer than 2^31 source files");
11        assert!(id < Self::PINNED, "fewer than 2^31 source files");
12        Self(id)
13    }
14
15    pub fn pinned(self) -> Self {
16        Self(self.0 | Self::PINNED)
17    }
18
19    pub fn is_pinned(self) -> bool {
20        self.0 & Self::PINNED != 0
21    }
22
23    pub fn index(self) -> usize {
24        (self.0 & !Self::PINNED) as usize
25    }
26}
27
28#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
29pub struct Span {
30    source: SourceId,
31    start: u32,
32    end: u32,
33}
34
35impl Span {
36    pub fn new(source: SourceId, range: Range<usize>) -> Self {
37        Self {
38            source,
39            start: Self::offset(range.start),
40            end: Self::offset(range.end),
41        }
42    }
43
44    pub fn is_pinned(self) -> bool {
45        self.source.is_pinned()
46    }
47
48    pub fn source(self) -> SourceId {
49        self.source
50    }
51
52    pub fn range(self) -> Range<usize> {
53        self.start as usize..self.end as usize
54    }
55
56    pub fn start(self) -> Span {
57        Span::new(self.source(), self.range().start..self.range().start)
58    }
59
60    pub fn end(self) -> Span {
61        Span::new(self.source(), self.range().end..self.range().end)
62    }
63
64    pub fn contains(self, inner: Span) -> bool {
65        self.source == inner.source && self.start <= inner.start && inner.end <= self.end
66    }
67
68    fn offset(position: usize) -> u32 {
69        u32::try_from(position).expect("source files are smaller than 4 GiB")
70    }
71}