knave_expand/source/
span.rs1use 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}