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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
use std::ops::{Index, IndexMut, Range};

/// Range of bytes in a source file.
///
/// This is very similar to the [`Range<usize>`] type unless it is not an iterator
/// and implements the `Copy` trait.
#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct Span {
	/// Start byte (included).
	start: usize,

	/// End byte (excluded).
	end: usize,
}

impl Span {
	/// Creates a new `Span` by providing the index of its starting byte (included) and ending byte (excluded).
	///
	/// If the `end` position is lower than the `start` position,
	/// then the `start` position is used as ending position instead.
	#[inline(always)]
	pub fn new(start: usize, end: usize) -> Self {
		Self {
			start,
			end: std::cmp::max(start, end),
		}
	}

	/// Size of the span in bytes.
	#[inline(always)]
	pub fn len(&self) -> usize {
		self.end - self.start
	}

	/// Checks if the span is empty.
	///
	/// Returns `true` if the start position is equal to the end position,
	/// and `false` otherwise.
	/// The end position can never be lower than the start position.
	#[inline(always)]
	pub fn is_empty(&self) -> bool {
		self.end == self.start
	}

	/// Returns the index of the first byte in the span.
	#[inline(always)]
	pub fn start(&self) -> usize {
		self.start
	}

	/// Returns the index of the first byte *after* the span.
	///
	/// This can never be lower than [`Self::start`].
	#[inline(always)]
	pub fn end(&self) -> usize {
		self.end
	}

	/// Returns the range of bytes inside the span.
	#[inline(always)]
	pub fn range(&self) -> Range<usize> {
		self.start..self.end
	}

	/// Checks if the given byte index if included in the span.
	#[inline(always)]
	pub fn contains(&self, index: usize) -> bool {
		self.start >= index && index < self.end
	}

	/// Sets the index of the first byte in the span.
	///
	/// If the end position of the span is lower that `start`,
	/// then it is also changed into `start`.
	#[inline(always)]
	pub fn set_start(&mut self, start: usize) {
		self.start = start;
		self.end = std::cmp::max(start, self.end);
	}

	/// Sets the index of the first byte *after* the span.
	///
	/// If `end` is lower that the start position, the start position is used instead.
	#[inline(always)]
	pub fn set_end(&mut self, end: usize) {
		self.end = std::cmp::max(self.start, end);
	}

	/// Computes the union of two spans.
	///
	/// If the two spans do not overlap,
	/// all the positions in between will be included in the resulting span.
	#[inline(always)]
	pub fn union(&self, other: Self) -> Self {
		Self {
			start: std::cmp::min(self.start, other.start),
			end: std::cmp::max(self.end, other.end),
		}
	}

	/// Extend this span to include `other`.
	///
	/// This is the *in-place* version of [`union`](Self::union).
	#[inline(always)]
	pub fn append(&mut self, other: Self) {
		self.start = std::cmp::min(self.start, other.start);
		self.end = std::cmp::max(self.end, other.end)
	}

	/// Computes the intersection of two spans.
	///
	/// If the two spans do not overlap,
	/// then the empty span located at the start of the most advanced span
	/// (maximum of the start of the two spans) is returned.
	#[inline(always)]
	pub fn inter(&self, other: Self) -> Self {
		let start = std::cmp::max(self.start, other.start);
		Self {
			start,
			end: std::cmp::max(start, std::cmp::min(self.end, other.end)),
		}
	}

	/// Clear the span by moving its start position to its end position.
	#[inline(always)]
	pub fn clear(&mut self) {
		self.start = self.end
	}

	/// Return the "next" span: the empty span starting at the end of this one.
	#[inline(always)]
	pub fn next(&self) -> Self {
		self.end.into()
	}

	/// Push `count` bytes to the span.
	///
	/// Move its end position by `count`.
	#[inline(always)]
	pub fn push(&mut self, count: usize) {
		self.end += count
	}
}

impl From<usize> for Span {
	fn from(pos: usize) -> Self {
		Self::new(pos, pos)
	}
}

impl From<Range<usize>> for Span {
	fn from(range: Range<usize>) -> Self {
		Self::new(range.start, range.end)
	}
}

impl From<Span> for Range<usize> {
	fn from(span: Span) -> Self {
		Self {
			start: span.start,
			end: span.end,
		}
	}
}

impl IntoIterator for Span {
	type Item = usize;
	type IntoIter = Range<usize>;

	fn into_iter(self) -> Self::IntoIter {
		self.range()
	}
}

impl<'a> IntoIterator for &'a Span {
	type Item = usize;
	type IntoIter = Range<usize>;

	fn into_iter(self) -> Self::IntoIter {
		self.range()
	}
}

impl Index<Span> for str {
	type Output = str;

	fn index(&self, span: Span) -> &str {
		self.index(span.range())
	}
}

impl IndexMut<Span> for str {
	fn index_mut(&mut self, span: Span) -> &mut str {
		self.index_mut(span.range())
	}
}

impl Index<Span> for String {
	type Output = str;

	fn index(&self, span: Span) -> &str {
		self.index(span.range())
	}
}

impl IndexMut<Span> for String {
	fn index_mut(&mut self, span: Span) -> &mut str {
		self.index_mut(span.range())
	}
}