1use std::ops::Range;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq)]
7pub struct Span {
8 pub start: usize,
9 pub end: usize,
10}
11
12impl Span {
13 pub fn new(start: usize, end: usize) -> Self {
14 if start > end {
15 panic!("{} > {}", start, end);
16 }
17 Self { start, end }
18 }
19
20 pub fn new_with_len(start: usize, len: usize) -> Self {
21 Self {
22 start,
23 end: start + len,
24 }
25 }
26
27 pub fn len(&self) -> usize {
28 self.end - self.start
29 }
30
31 pub fn is_empty(&self) -> bool {
32 self.len() == 0
33 }
34
35 pub fn contains(&self, idx: usize) -> bool {
36 assert!(self.start <= self.end);
37
38 self.start <= idx && idx < self.end
39 }
40
41 pub fn overlaps_with(&self, other: Self) -> bool {
42 (self.start < other.end) && (other.start < self.end)
43 }
44
45 pub fn try_get_content<'a>(&self, source: &'a [char]) -> Option<&'a [char]> {
48 if (self.start > self.end) || (self.start >= source.len()) || (self.end > source.len()) {
49 if self.is_empty() {
50 return Some(&source[0..0]);
51 }
52 return None;
53 }
54
55 Some(&source[self.start..self.end])
56 }
57
58 pub fn get_content<'a>(&self, source: &'a [char]) -> &'a [char] {
60 self.try_get_content(source).unwrap()
61 }
62
63 pub fn get_content_string(&self, source: &[char]) -> String {
64 String::from_iter(self.get_content(source))
65 }
66
67 pub fn set_len(&mut self, length: usize) {
68 self.end = self.start + length;
69 }
70
71 pub fn with_len(&self, length: usize) -> Self {
72 let mut cloned = *self;
73 cloned.set_len(length);
74 cloned
75 }
76
77 pub fn push_by(&mut self, by: usize) {
79 self.start += by;
80 self.end += by;
81 }
82
83 pub fn pull_by(&mut self, by: usize) {
85 self.start -= by;
86 self.end -= by;
87 }
88
89 pub fn pushed_by(&self, by: usize) -> Self {
91 let mut clone = *self;
92 clone.start += by;
93 clone.end += by;
94 clone
95 }
96
97 pub fn pulled_by(&self, by: usize) -> Option<Self> {
99 if by > self.start {
100 return None;
101 }
102
103 let mut clone = *self;
104 clone.start -= by;
105 clone.end -= by;
106 Some(clone)
107 }
108
109 pub fn with_offset(&self, by: usize) -> Self {
111 let mut clone = *self;
112 clone.push_by(by);
113 clone
114 }
115}
116
117impl From<Range<usize>> for Span {
118 fn from(value: Range<usize>) -> Self {
119 Self::new(value.start, value.end)
120 }
121}
122
123impl From<Span> for Range<usize> {
124 fn from(value: Span) -> Self {
125 value.start..value.end
126 }
127}
128
129impl IntoIterator for Span {
130 type Item = usize;
131
132 type IntoIter = Range<usize>;
133
134 fn into_iter(self) -> Self::IntoIter {
135 self.start..self.end
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use crate::Span;
142
143 #[test]
144 fn overlaps() {
145 assert!(Span::new(0, 5).overlaps_with(Span::new(3, 6)));
146 assert!(Span::new(0, 5).overlaps_with(Span::new(2, 3)));
147 assert!(Span::new(0, 5).overlaps_with(Span::new(4, 5)));
148 assert!(Span::new(0, 5).overlaps_with(Span::new(4, 4)));
149
150 assert!(!Span::new(0, 3).overlaps_with(Span::new(3, 5)));
151 }
152}