1use core::fmt::Display;
11use core::num::NonZeroU16;
12use std::fmt::{Debug, Formatter};
13use std::sync::Mutex;
14
15pub type Index = u32;
16pub type IndexOffset = i64;
17pub type Range = std::ops::Range<Index>;
18pub type LineNumber = u16;
19
20#[derive(Copy, Clone, Debug)]
21enum SpanData {
22 LargeSpan,
24 Length(NonZeroU16),
25}
26lazy_static! {
27 static ref INTERNER: Mutex<SpanInterner> = Mutex::new(SpanInterner::new());
28}
29struct SpanInterner {
30 data: Vec<(u32, u32)>,
31}
32impl SpanInterner {
33 fn new() -> Self {
34 Self {
35 data: Vec::with_capacity(64),
36 }
37 }
38 fn add(&mut self, start: u32, end: u32) -> usize {
39 let idx = self.data.len();
40 self.data.push((start, end));
41 idx
42 }
43 fn get(&self, idx: usize) -> (u32, u32) {
44 unsafe { *self.data.get_unchecked(idx) }
45 }
46}
47
48#[derive(Copy, Clone, Debug)]
49pub struct Span {
50 start_or_idx: Index,
51 data: SpanData,
52}
53impl Span {
54 #[inline]
55 pub fn new(start: Index, end: Index) -> Self {
56 Self::new_with_length(start, end - start)
57 }
58
59 const U16_MAX_U32: u32 = std::u16::MAX as u32;
60 #[inline]
61 pub fn new_with_length(start: Index, len: Index) -> Self {
62 match len {
63 0 if start < (1 << 31) => Self {
64 start_or_idx: (start << 1) | 1,
65 data: SpanData::LargeSpan,
66 },
67 len @ 1..=Self::U16_MAX_U32 => Self {
68 start_or_idx: start,
69 data: SpanData::Length(unsafe { NonZeroU16::new_unchecked(len as u16) }),
70 },
71 len => {
72 debug_assert!(len == 0 || len > std::u16::MAX as u32);
73 Self {
74 start_or_idx: (INTERNER.lock().unwrap().add(start, start + len) as u32) << 1,
75 data: SpanData::LargeSpan,
76 }
77 }
78 }
79 }
80
81 #[inline]
82 pub const fn new_short_span(start: Index, len: NonZeroU16) -> Self {
83 Self {
84 start_or_idx: start,
85 data: SpanData::Length(len),
86 }
87 }
88 #[inline]
89 pub fn new_empty_span(start: Index) -> Self {
90 if start < 1 << 31 {
91 Self {
92 start_or_idx: (start << 1) | 1,
93 data: SpanData::LargeSpan,
94 }
95 } else {
96 Self {
97 start_or_idx: (INTERNER.lock().unwrap().add(start, start) as u32) << 1,
98 data: SpanData::LargeSpan,
99 }
100 }
101 }
102 #[inline]
103 pub const fn new_short_empty_span(start: u16) -> Self {
104 Self {
105 start_or_idx: ((start as u32) << 1) | 1,
106 data: SpanData::LargeSpan,
107 }
108 }
109
110 #[inline]
111 pub fn get_start(self) -> Index {
112 match self.data {
113 SpanData::Length(_) => self.start_or_idx,
114 SpanData::LargeSpan if self.start_or_idx & 1 == 1 => self.start_or_idx >> 1,
115 SpanData::LargeSpan => {
116 INTERNER
117 .lock()
118 .unwrap()
119 .get((self.start_or_idx >> 1) as usize)
120 .0
121 }
122 }
123 }
124
125 #[inline]
126 pub fn get_end(self) -> Index {
127 match self.data {
128 SpanData::Length(length) => self.start_or_idx + (length.get() as u32),
129 SpanData::LargeSpan if self.start_or_idx & 1 == 1 => self.start_or_idx >> 1,
130 SpanData::LargeSpan => {
131 INTERNER
132 .lock()
133 .unwrap()
134 .get((self.start_or_idx >> 1) as usize)
135 .1
136 }
137 }
138 }
139
140 pub fn get_len(self) -> Index {
141 match self.data {
142 SpanData::Length(length) => length.get() as Index,
143 SpanData::LargeSpan if self.start_or_idx & 1 == 1 => 0,
144 SpanData::LargeSpan => {
145 let (start, end) = INTERNER
146 .lock()
147 .unwrap()
148 .get((self.start_or_idx >> 1) as usize);
149 end - start
150 }
151 }
152 }
153 pub fn offset(mut self, offset: Index) -> Self {
154 match self.data {
155 SpanData::Length(_) => self.start_or_idx += offset,
156 SpanData::LargeSpan if (self.start_or_idx & 1) == 1 => {
157 let new_start = (self.start_or_idx >> 1) + offset;
158 if new_start + offset <= (1 << 31) - 1 {
159 self.start_or_idx = new_start
160 } else {
161 self.start_or_idx =
162 (INTERNER.lock().unwrap().add(new_start, new_start) as u32) << 1
163 }
164 }
165 SpanData::LargeSpan => {
166 let mut inter = INTERNER.lock().unwrap();
167 let (start, end) = inter.get((self.start_or_idx >> 1) as usize);
168 self.start_or_idx = inter.add(start + offset, end + offset) as u32;
169 }
170 }
171 self
172 }
173 pub fn signed_offset(self, offset: IndexOffset) -> Self {
174 if offset < 0 {
175 self.negative_offset(-offset as Index)
176 } else {
177 self.offset(offset as Index)
178 }
179 }
180 pub fn negative_offset(mut self, offset: Index) -> Self {
181 match self.data {
182 SpanData::LargeSpan if self.start_or_idx & 1 == 1 => {
183 let new_start = (self.start_or_idx >> 1) - offset;
184 if new_start + offset <= (1 << 31) - 1 {
185 self.start_or_idx = new_start
186 } else {
187 self.start_or_idx =
188 (INTERNER.lock().unwrap().add(new_start, new_start) as u32) << 1
189 }
190 }
191 SpanData::LargeSpan => {
192 let mut inter = INTERNER.lock().unwrap();
193 let (start, end) = inter.get((self.start_or_idx >> 1) as usize);
194 self.start_or_idx = inter.add(start - offset, end - offset) as u32;
195 }
196 SpanData::Length(_) => self.start_or_idx -= offset,
197 }
198 self
199 }
200 pub fn extend(self, to: Self) -> Self {
201 if to.get_end() > self.get_start() {
202 Self::new(self.get_start(), to.get_end())
203 } else {
204 self
205 }
206 }
207}
208impl From<Range> for Span {
209 fn from(range: Range) -> Self {
210 Self::new(range.start, range.end)
211 }
212}
213impl Into<Range> for Span {
214 fn into(self) -> Range {
215 Range {
216 start: self.get_start(),
217 end: self.get_end(),
218 }
219 }
220}
221impl Into<std::ops::Range<usize>> for Span {
222 fn into(self) -> std::ops::Range<usize> {
223 std::ops::Range {
224 start: self.get_start() as usize,
225 end: self.get_end() as usize,
226 }
227 }
228}
229impl Display for Span {
230 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
231 f.write_fmt(format_args!(" [{},{}]", self.get_start(), self.get_end()))
232 }
233}
234impl Eq for Span {}
235impl PartialEq for Span {
236 fn eq(&self, other: &Self) -> bool {
237 self.get_start() == other.get_start() && self.get_end() == other.get_end()
238 }
239}