1use std::cmp::{max, min};
2use std::cmp::{Ord, Ordering, PartialOrd};
3use std::ops::{Add, Range};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub struct Span {
7 start: u32,
8 len: u32,
9}
10
11impl Span {
12 #[inline]
13 pub(crate) fn new(s: logos::Span) -> Self {
14 Self {
15 start: s.start as u32,
16 len: (s.end - s.start) as u32,
17 }
18 }
19
20 #[inline]
21 pub fn byte_range(&self) -> Range<usize> {
22 self.start as usize..(self.start + self.len) as usize
23 }
24
25 #[inline]
26 pub fn merge(&self, other: &Self) -> Self {
27 let start = min(self.start, other.start);
28 let end = max(self.start + self.len, other.start + other.len);
29 Self {
30 start,
31 len: end - start,
32 }
33 }
34}
35
36impl From<Span> for Range<usize> {
37 fn from(val: Span) -> Self {
38 val.byte_range()
39 }
40}
41
42impl From<logos::Span> for Span {
43 #[inline]
44 fn from(value: logos::Span) -> Self {
45 Self::new(value)
46 }
47}
48
49impl Add<usize> for Span {
50 type Output = Self;
51
52 fn add(self, rhs: usize) -> Self::Output {
53 Self {
54 start: self.start + rhs as u32,
55 len: self.len,
56 }
57 }
58}
59
60impl Ord for Span {
61 fn cmp(&self, other: &Self) -> Ordering {
62 self.start.cmp(&other.start)
63 }
64}
65
66impl PartialOrd for Span {
67 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
68 Some(self.cmp(other))
69 }
70}
71
72pub trait HasSpan {
73 fn span(&self) -> &Span;
74}