1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::{FileName, SpanFile};
use language_reporting as l_r;
use lark_debug_derive::DebugWith;
use lark_string::Text;
use std::ops::Index;
#[derive(Copy, Clone, Debug, DebugWith, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ByteIndex(crate usize);
impl ByteIndex {
pub fn to_usize(self) -> usize {
self.0
}
}
impl From<usize> for ByteIndex {
fn from(u: usize) -> ByteIndex {
ByteIndex(u)
}
}
#[derive(Copy, Clone, Debug, DebugWith, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ByteSize(crate usize);
impl<File: SpanFile> Index<Span<File>> for str {
type Output = str;
fn index(&self, range: Span<File>) -> &str {
&self[range.start.0..range.end.0]
}
}
#[derive(Copy, Clone, Debug, DebugWith, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Span<File: SpanFile> {
file: File,
crate start: ByteIndex,
crate end: ByteIndex,
}
#[derive(Copy, Clone, Debug, DebugWith, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CurrentFile;
#[derive(Copy, Clone, Debug, DebugWith, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CurrentEntity;
impl<File: SpanFile> Span<File> {
pub fn new(file: File, start: impl Into<ByteIndex>, end: impl Into<ByteIndex>) -> Self {
let start = start.into();
let end = end.into();
assert!(end.0 >= start.0);
Span { file, start, end }
}
pub fn initial(file: File) -> Self {
Span::new(file, 0, 0)
}
pub fn eof(file: File, text: &Text) -> Self {
let len = text.len();
Span::new(file, len, len)
}
pub fn extended_until_end_of(self, other_span: Span<File>) -> Span<File> {
assert_eq!(self.file, other_span.file);
assert!(self.start <= other_span.end);
Span::new(self.file, self.start, other_span.end)
}
pub fn file(&self) -> File {
self.file
}
pub fn start(&self) -> ByteIndex {
self.start
}
pub fn end(&self) -> ByteIndex {
self.end
}
pub fn in_file<NewFile: SpanFile>(self, file: NewFile) -> Span<NewFile> {
Span::new(file, self.start, self.end)
}
pub fn in_file_named(self, file: FileName) -> Span<FileName> {
Span::new(file, self.start, self.end)
}
pub fn contains(self, span: Span<File>) -> bool {
self.start >= span.start && self.end < span.end
}
pub fn contains_index(self, index: ByteIndex) -> bool {
self.start <= index && index < self.end
}
pub fn len(&self) -> ByteSize {
ByteSize(self.end.0 - self.start.0)
}
pub fn relative_to_entity(self, entity_span: Span<File>) -> Span<CurrentEntity> {
assert!(entity_span.contains(self));
let len = self.len();
let start = self.start.0 - entity_span.start.0;
Span::new(CurrentEntity, start, start + len.0)
}
}
impl<F: SpanFile> l_r::ReportingSpan for Span<F> {
fn with_start(&self, start: usize) -> Self {
Self {
start: ByteIndex::from(start),
..*self
}
}
fn with_end(&self, end: usize) -> Self {
Self {
end: ByteIndex::from(end),
..*self
}
}
fn start(&self) -> usize {
self.start.to_usize()
}
fn end(&self) -> usize {
self.end.to_usize()
}
}