1use std::{fmt, ops::Deref};
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
44pub struct Span {
45 start: usize,
46 end: usize,
47}
48
49impl Span {
50 pub fn new(range: std::ops::Range<usize>) -> Self {
56 Self {
57 start: range.start,
58 end: range.end,
59 }
60 }
61
62 pub fn empty() -> Self {
64 Self::new(0..0)
65 }
66
67 pub fn start(&self) -> usize {
69 self.start
70 }
71
72 pub fn end(&self) -> usize {
74 self.end
75 }
76
77 pub fn len(&self) -> usize {
83 if self.end >= self.start {
84 self.end - self.start
85 } else {
86 panic!("Invalid span: end offset is less than start offset");
87 }
88 }
89
90 pub fn is_empty(&self) -> bool {
92 self.start == self.end
93 }
94
95 pub fn union(&self, other: Span) -> Span {
103 if self.is_empty() {
104 return other;
105 }
106 if other.is_empty() {
107 return *self;
108 }
109 Self {
110 start: self.start.min(other.start),
111 end: self.end.max(other.end),
112 }
113 }
114
115 pub fn shift(self, base: usize) -> Span {
124 Self {
125 start: self.start + base,
126 end: self.end + base,
127 }
128 }
129}
130
131impl Default for Span {
132 fn default() -> Self {
133 Self::empty()
134 }
135}
136
137impl From<std::ops::Range<usize>> for Span {
138 fn from(range: std::ops::Range<usize>) -> Self {
139 Self::new(range)
140 }
141}
142
143#[derive(Debug, Default, Clone, Eq)]
162pub struct Spanned<T> {
163 value: T,
165 span: Span,
167}
168
169impl<T> Spanned<T> {
170 pub fn new(value: T, span: Span) -> Self {
177 Self { value, span }
178 }
179
180 pub fn span(&self) -> Span {
182 self.span
183 }
184
185 pub fn map<F, U>(&self, f: F) -> Spanned<U>
191 where
192 F: FnOnce(&T) -> U,
193 {
194 Spanned {
195 value: f(&self.value),
196 span: self.span,
197 }
198 }
199
200 pub fn inner(&self) -> &T {
202 &self.value
203 }
204
205 #[allow(dead_code)]
207 pub fn into_inner(self) -> T {
208 self.value
209 }
210}
211
212impl<T> Deref for Spanned<T> {
214 type Target = T;
215
216 fn deref(&self) -> &Self::Target {
217 &self.value
218 }
219}
220
221impl<T: fmt::Display> fmt::Display for Spanned<T> {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 self.value.fmt(f)
225 }
226}
227
228impl<T: PartialEq> PartialEq for Spanned<T> {
230 fn eq(&self, other: &Self) -> bool {
231 self.value.eq(&other.value)
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238
239 #[test]
240 fn test_span_basic_functionality() {
241 let span = Span::new(5..10);
242 assert_eq!(span.start(), 5);
243 assert_eq!(span.end(), 10);
244 assert_eq!(span.len(), 5);
245 assert!(!span.is_empty());
246 }
247
248 #[test]
249 fn test_span_empty() {
250 let span = Span::new(5..5);
251 assert_eq!(span.len(), 0);
252 assert!(span.is_empty());
253 }
254
255 #[test]
256 fn test_span_union() {
257 let span1 = Span::new(5..10);
258 let span2 = Span::new(15..20);
259 let union = span1.union(span2);
260 assert_eq!(union.start(), 5);
261 assert_eq!(union.end(), 20);
262 }
263
264 #[test]
265 fn test_span_shift() {
266 let span = Span::new(5..10);
267 let shifted = span.shift(100);
268 assert_eq!(shifted.start(), 105);
269 assert_eq!(shifted.end(), 110);
270 assert_eq!(shifted.len(), 5);
271 }
272
273 #[test]
274 fn test_span_shift_zero_is_identity() {
275 let span = Span::new(5..10);
276 assert_eq!(span.shift(0), span);
277 }
278
279 #[test]
280 fn test_spanned_with_new_span() {
281 let span = Span::new(5..10);
282 let spanned = Spanned::new("test", span);
283 assert_eq!(spanned.span().start(), 5);
284 assert_eq!(spanned.span().len(), 5);
285 assert_eq!(*spanned.inner(), "test");
286 }
287
288 #[test]
289 fn test_span_empty_constructor() {
290 let span = Span::empty();
291 assert_eq!(span.start(), 0);
292 assert_eq!(span.end(), 0);
293 assert_eq!(span.len(), 0);
294 assert!(span.is_empty());
295 }
296
297 #[test]
298 fn test_span_default_is_empty() {
299 let span = Span::default();
300 assert_eq!(span, Span::empty());
301 assert!(span.is_empty());
302 }
303
304 #[test]
305 fn test_span_union_with_left_empty() {
306 let empty = Span::empty();
307 let span = Span::new(5..10);
308 let union = empty.union(span);
309 assert_eq!(union, span);
310 }
311
312 #[test]
313 fn test_span_union_with_right_empty() {
314 let span = Span::new(5..10);
315 let empty = Span::empty();
316 let union = span.union(empty);
317 assert_eq!(union, span);
318 }
319
320 #[test]
321 fn test_span_union_both_empty() {
322 let union = Span::empty().union(Span::empty());
323 assert!(union.is_empty());
324 }
325
326 #[test]
327 fn test_spanned_eq_ignores_span() {
328 let a = Spanned::new(42, Span::new(0..5));
329 let b = Spanned::new(42, Span::new(10..20));
330 assert_eq!(a, b);
331 }
332
333 #[test]
334 fn test_spanned_ne_different_values() {
335 let a = Spanned::new(1, Span::new(0..5));
336 let b = Spanned::new(2, Span::new(0..5));
337 assert_ne!(a, b);
338 }
339
340 #[test]
341 fn test_spanned_map() {
342 let spanned = Spanned::new(5, Span::new(0..10));
343 let mapped = spanned.map(|v| v * 2);
344 assert_eq!(*mapped.inner(), 10);
345 assert_eq!(mapped.span(), spanned.span());
346 }
347
348 #[test]
349 fn test_spanned_into_inner() {
350 let spanned = Spanned::new(String::from("hello"), Span::new(0..5));
351 let value = spanned.into_inner();
352 assert_eq!(value, "hello");
353 }
354
355 #[test]
356 fn test_spanned_deref() {
357 let spanned = Spanned::new(String::from("hello"), Span::new(0..5));
358 assert_eq!(spanned.len(), 5);
360 assert!(spanned.starts_with("he"));
361 }
362
363 #[test]
364 fn test_spanned_display() {
365 let spanned = Spanned::new(42, Span::new(0..5));
366 assert_eq!(format!("{spanned}"), "42");
367 }
368}