1use std::{
5 cmp,
6 cmp::Ordering,
7 fmt,
8 fmt::{Display, Formatter},
9 ops::Deref,
10 sync::Arc,
11};
12
13use serde::{Deserialize, Serialize};
14
15#[repr(transparent)]
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
18pub struct StatementColumn(pub u32);
19
20impl Deref for StatementColumn {
21 type Target = u32;
22
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28impl PartialEq<i32> for StatementColumn {
29 fn eq(&self, other: &i32) -> bool {
30 self.0 == *other as u32
31 }
32}
33
34#[repr(transparent)]
35#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
36pub struct StatementLine(pub u32);
37
38impl Deref for StatementLine {
39 type Target = u32;
40
41 fn deref(&self) -> &Self::Target {
42 &self.0
43 }
44}
45
46impl PartialEq<i32> for StatementLine {
47 fn eq(&self, other: &i32) -> bool {
48 self.0 == *other as u32
49 }
50}
51
52#[derive(Debug, Clone, PartialEq, Hash, Serialize, Deserialize)]
54pub enum Fragment {
55 None,
57
58 Statement {
60 text: Arc<str>,
61 line: StatementLine,
62 column: StatementColumn,
63 },
64
65 Internal {
67 text: Arc<str>,
68 },
69}
70
71impl Fragment {
72 pub fn text(&self) -> &str {
74 match self {
75 Fragment::None => "",
76 Fragment::Statement {
77 text,
78 ..
79 }
80 | Fragment::Internal {
81 text,
82 ..
83 } => text,
84 }
85 }
86
87 pub fn line(&self) -> StatementLine {
89 match self {
90 Fragment::Statement {
91 line,
92 ..
93 } => *line,
94 _ => StatementLine(1),
95 }
96 }
97
98 pub fn column(&self) -> StatementColumn {
100 match self {
101 Fragment::Statement {
102 column,
103 ..
104 } => *column,
105 _ => StatementColumn(0),
106 }
107 }
108
109 pub fn sub_fragment(&self, offset: usize, length: usize) -> Fragment {
112 let text = self.text();
113 let end = cmp::min(offset + length, text.len());
114 let sub_text = if offset < text.len() {
115 &text[offset..end]
116 } else {
117 ""
118 };
119
120 match self {
121 Fragment::None => Fragment::None,
122 Fragment::Statement {
123 line,
124 column,
125 ..
126 } => Fragment::Statement {
127 text: Arc::from(sub_text),
128 line: *line,
129 column: StatementColumn(column.0 + offset as u32),
130 },
131 Fragment::Internal {
132 ..
133 } => Fragment::Internal {
134 text: Arc::from(sub_text),
135 },
136 }
137 }
138
139 pub fn with_text(&self, text: impl Into<String>) -> Fragment {
141 let text = Arc::from(text.into());
142 match self {
143 Fragment::Statement {
144 line,
145 column,
146 ..
147 } => Fragment::Statement {
148 text,
149 line: *line,
150 column: *column,
151 },
152 Fragment::Internal {
153 ..
154 } => Fragment::Internal {
155 text,
156 },
157 Fragment::None => Fragment::Internal {
158 text,
159 },
160 }
161 }
162}
163
164impl Fragment {
165 pub fn internal(text: impl Into<String>) -> Self {
168 Fragment::Internal {
169 text: Arc::from(text.into()),
170 }
171 }
172
173 pub fn testing(text: impl Into<String>) -> Self {
176 Fragment::Statement {
177 text: Arc::from(text.into()),
178 line: StatementLine(1),
179 column: StatementColumn(0),
180 }
181 }
182
183 pub fn testing_empty() -> Self {
185 Self::testing("")
186 }
187
188 pub fn merge_all(fragments: impl IntoIterator<Item = Fragment>) -> Fragment {
191 let mut fragments: Vec<Fragment> = fragments.into_iter().collect();
192 assert!(!fragments.is_empty());
193
194 fragments.sort();
195
196 let first = fragments.first().unwrap();
197
198 let mut text = String::with_capacity(fragments.iter().map(|f| f.text().len()).sum());
199 for fragment in &fragments {
200 text.push_str(fragment.text());
201 }
202
203 match first {
204 Fragment::None => Fragment::None,
205 Fragment::Statement {
206 line,
207 column,
208 ..
209 } => Fragment::Statement {
210 text: Arc::from(text),
211 line: *line,
212 column: *column,
213 },
214 Fragment::Internal {
215 ..
216 } => Fragment::Internal {
217 text: Arc::from(text),
218 },
219 }
220 }
221
222 pub fn fragment(&self) -> &str {
224 self.text()
225 }
226}
227
228impl Default for Fragment {
229 fn default() -> Self {
230 Fragment::None
231 }
232}
233
234impl AsRef<str> for Fragment {
235 fn as_ref(&self) -> &str {
236 self.text()
237 }
238}
239
240impl Display for Fragment {
241 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
242 Display::fmt(self.text(), f)
243 }
244}
245
246impl PartialOrd for Fragment {
247 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
248 Some(self.cmp(other))
249 }
250}
251
252impl Ord for Fragment {
253 fn cmp(&self, other: &Self) -> Ordering {
254 self.column().cmp(&other.column()).then(self.line().cmp(&other.line()))
255 }
256}
257
258impl Eq for Fragment {}
259
260impl From<String> for Fragment {
262 fn from(s: String) -> Self {
263 Fragment::Internal {
264 text: Arc::from(s),
265 }
266 }
267}
268
269impl From<&str> for Fragment {
270 fn from(s: &str) -> Self {
271 Fragment::Internal {
272 text: Arc::from(s),
273 }
274 }
275}
276
277impl Fragment {
278 pub fn statement(text: impl Into<String>, line: u32, column: u32) -> Self {
280 Fragment::Statement {
281 text: Arc::from(text.into()),
282 line: StatementLine(line),
283 column: StatementColumn(column),
284 }
285 }
286
287 pub fn none() -> Self {
289 Fragment::None
290 }
291}
292
293impl PartialEq<str> for Fragment {
295 fn eq(&self, other: &str) -> bool {
296 self.text() == other
297 }
298}
299
300impl PartialEq<&str> for Fragment {
301 fn eq(&self, other: &&str) -> bool {
302 self.text() == *other
303 }
304}
305
306impl PartialEq<String> for Fragment {
307 fn eq(&self, other: &String) -> bool {
308 self.text() == other.as_str()
309 }
310}
311
312impl PartialEq<String> for &Fragment {
313 fn eq(&self, other: &String) -> bool {
314 self.text() == other.as_str()
315 }
316}
317
318pub trait LazyFragment {
320 fn fragment(&self) -> Fragment;
321}
322
323impl<F> LazyFragment for F
324where
325 F: Fn() -> Fragment,
326{
327 fn fragment(&self) -> Fragment {
328 self()
329 }
330}
331
332impl LazyFragment for &Fragment {
333 fn fragment(&self) -> Fragment {
334 (*self).clone()
335 }
336}
337
338impl LazyFragment for Fragment {
339 fn fragment(&self) -> Fragment {
340 self.clone()
341 }
342}