1use serde::{Deserialize, Serialize};
11
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub struct Span {
18 pub start: u32,
20 pub end: u32,
22}
23
24impl Span {
25 #[inline]
27 #[must_use]
28 pub const fn new(start: u32, end: u32) -> Self {
29 Self { start, end }
30 }
31
32 #[inline]
34 #[must_use]
35 pub const fn at(pos: u32) -> Self {
36 Self {
37 start: pos,
38 end: pos,
39 }
40 }
41
42 #[inline]
44 #[must_use]
45 pub const fn from_len(start: u32, len: u32) -> Self {
46 Self {
47 start,
48 end: start + len,
49 }
50 }
51
52 #[inline]
54 #[must_use]
55 pub const fn dummy() -> Self {
56 Self {
57 start: u32::MAX,
58 end: u32::MAX,
59 }
60 }
61
62 #[inline]
64 #[must_use]
65 pub const fn is_dummy(&self) -> bool {
66 self.start == u32::MAX && self.end == u32::MAX
67 }
68
69 #[inline]
71 #[must_use]
72 pub const fn len(&self) -> u32 {
73 self.end.saturating_sub(self.start)
74 }
75
76 #[inline]
78 #[must_use]
79 pub const fn is_empty(&self) -> bool {
80 self.start == self.end
81 }
82
83 #[inline]
85 #[must_use]
86 pub const fn contains(&self, offset: u32) -> bool {
87 offset >= self.start && offset < self.end
88 }
89
90 #[inline]
92 #[must_use]
93 pub const fn contains_span(&self, other: Self) -> bool {
94 other.start >= self.start && other.end <= self.end
95 }
96
97 #[inline]
99 #[must_use]
100 pub const fn overlaps(&self, other: Self) -> bool {
101 self.start < other.end && other.start < self.end
102 }
103
104 #[inline]
106 #[must_use]
107 pub const fn merge(&self, other: Self) -> Self {
108 let start = if self.start < other.start {
109 self.start
110 } else {
111 other.start
112 };
113 let end = if self.end > other.end {
114 self.end
115 } else {
116 other.end
117 };
118 Self { start, end }
119 }
120
121 #[inline]
123 #[must_use]
124 pub fn intersect(&self, other: Self) -> Option<Self> {
125 let start = self.start.max(other.start);
126 let end = self.end.min(other.end);
127 (start < end).then_some(Self { start, end })
128 }
129
130 #[inline]
132 #[must_use]
133 pub const fn shrink_start(&self, amount: u32) -> Self {
134 let new_start = self.start + amount;
135 Self {
136 start: if new_start > self.end {
137 self.end
138 } else {
139 new_start
140 },
141 end: self.end,
142 }
143 }
144
145 #[inline]
147 #[must_use]
148 pub const fn shrink_end(&self, amount: u32) -> Self {
149 let new_end = self.end.saturating_sub(amount);
150 Self {
151 start: self.start,
152 end: if new_end < self.start {
153 self.start
154 } else {
155 new_end
156 },
157 }
158 }
159
160 #[inline]
162 #[must_use]
163 pub const fn first_byte(&self) -> Self {
164 Self {
165 start: self.start,
166 end: if self.end > self.start {
167 self.start + 1
168 } else {
169 self.end
170 },
171 }
172 }
173
174 #[inline]
176 #[must_use]
177 pub const fn last_byte(&self) -> Self {
178 Self {
179 start: if self.end > self.start {
180 self.end - 1
181 } else {
182 self.start
183 },
184 end: self.end,
185 }
186 }
187
188 #[inline]
190 #[must_use]
191 pub fn slice<'a>(&self, text: &'a str) -> &'a str {
192 let start = self.start as usize;
193 let end = self.end as usize;
194 text.get(start..end).unwrap_or("")
195 }
196
197 #[inline]
199 #[must_use]
200 pub fn slice_safe<'a>(&self, text: &'a str) -> &'a str {
201 let start = (self.start as usize).min(text.len());
202 let end = (self.end as usize).min(text.len());
203 if start <= end {
204 text.get(start..end).unwrap_or("")
205 } else {
206 ""
207 }
208 }
209}
210
211impl From<(u32, u32)> for Span {
212 fn from((start, end): (u32, u32)) -> Self {
213 Self::new(start, end)
214 }
215}
216
217impl From<Span> for (u32, u32) {
218 fn from(span: Span) -> Self {
219 (span.start, span.end)
220 }
221}
222
223impl std::fmt::Display for Span {
224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225 write!(f, "{}..{}", self.start, self.end)
226 }
227}
228
229pub trait Spanned {
235 fn span(&self) -> Span;
237
238 fn start(&self) -> u32 {
240 self.span().start
241 }
242
243 fn end(&self) -> u32 {
245 self.span().end
246 }
247
248 fn len(&self) -> u32 {
250 self.span().len()
251 }
252
253 fn is_empty(&self) -> bool {
255 self.span().is_empty()
256 }
257}
258
259impl Spanned for Span {
260 fn span(&self) -> Span {
261 *self
262 }
263}
264
265#[derive(Clone, Copy, Debug)]
278pub struct SpanBuilder {
279 start: u32,
280}
281
282impl SpanBuilder {
283 #[inline]
285 #[must_use]
286 pub const fn start(pos: u32) -> Self {
287 Self { start: pos }
288 }
289
290 #[inline]
292 #[must_use]
293 pub const fn end(&self, pos: u32) -> Span {
294 Span::new(self.start, pos)
295 }
296
297 #[inline]
299 #[must_use]
300 pub const fn start_pos(&self) -> u32 {
301 self.start
302 }
303}
304
305#[derive(Clone, Copy, Debug)]
313pub struct ByteSpan<'a> {
314 pub text: &'a str,
316 pub span: Span,
318}
319
320impl<'a> ByteSpan<'a> {
321 #[must_use]
323 pub const fn new(text: &'a str, span: Span) -> Self {
324 ByteSpan { text, span }
325 }
326
327 #[must_use]
329 pub fn as_str(&self) -> &'a str {
330 self.span.slice(self.text)
331 }
332
333 #[must_use]
335 pub const fn len(&self) -> u32 {
336 self.span.len()
337 }
338
339 #[must_use]
341 pub const fn is_empty(&self) -> bool {
342 self.span.is_empty()
343 }
344}
345
346impl Spanned for ByteSpan<'_> {
347 fn span(&self) -> Span {
348 self.span
349 }
350}
351
352impl std::fmt::Display for ByteSpan<'_> {
353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354 write!(f, "{}", self.as_str())
355 }
356}
357
358#[cfg(test)]
363#[path = "../tests/span.rs"]
364mod tests;