1use crate::{FromValue, IntoValue, ShellError, SpanId, Value, record};
3use miette::SourceSpan;
4use serde::{Deserialize, Serialize};
5use std::{fmt, ops::Deref};
6
7pub trait GetSpan {
8 fn get_span(&self, span_id: SpanId) -> Span;
9}
10
11#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
13pub struct Spanned<T> {
14 pub item: T,
15 pub span: Span,
16}
17
18impl<T> Spanned<T> {
19 pub fn as_ref(&self) -> Spanned<&T> {
21 Spanned {
22 item: &self.item,
23 span: self.span,
24 }
25 }
26
27 pub fn as_mut(&mut self) -> Spanned<&mut T> {
29 Spanned {
30 item: &mut self.item,
31 span: self.span,
32 }
33 }
34
35 pub fn as_deref(&self) -> Spanned<&<T as Deref>::Target>
39 where
40 T: Deref,
41 {
42 Spanned {
43 item: self.item.deref(),
44 span: self.span,
45 }
46 }
47
48 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanned<U> {
50 Spanned {
51 item: f(self.item),
52 span: self.span,
53 }
54 }
55}
56
57impl<T> Spanned<&T>
58where
59 T: ToOwned + ?Sized,
60{
61 pub fn to_owned(&self) -> Spanned<T::Owned> {
63 Spanned {
64 item: self.item.to_owned(),
65 span: self.span,
66 }
67 }
68}
69
70impl<T> Spanned<T>
71where
72 T: AsRef<str>,
73{
74 pub fn as_str(&self) -> Spanned<&str> {
76 Spanned {
77 item: self.item.as_ref(),
78 span: self.span,
79 }
80 }
81}
82
83impl<T, E> Spanned<Result<T, E>> {
84 pub fn transpose(self) -> Result<Spanned<T>, E> {
86 match self {
87 Spanned {
88 item: Ok(item),
89 span,
90 } => Ok(Spanned { item, span }),
91 Spanned {
92 item: Err(err),
93 span: _,
94 } => Err(err),
95 }
96 }
97}
98
99impl<T: fmt::Display> fmt::Display for Spanned<T> {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 fmt::Display::fmt(&self.item, f)
105 }
106}
107
108impl<T> From<Spanned<T>> for SourceSpan {
109 fn from(value: Spanned<T>) -> Self {
110 value.span.into()
111 }
112}
113
114pub trait IntoSpanned: Sized {
116 fn into_spanned(self, span: Span) -> Spanned<Self>;
128}
129
130impl<T> IntoSpanned for T {
131 fn into_spanned(self, span: Span) -> Spanned<Self> {
132 Spanned { item: self, span }
133 }
134}
135
136#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
140pub struct Span {
141 pub start: usize,
142 pub end: usize,
143}
144
145impl Span {
146 pub fn new(start: usize, end: usize) -> Self {
147 debug_assert!(
148 end >= start,
149 "Can't create a Span whose end < start, start={start}, end={end}"
150 );
151
152 Self { start, end }
153 }
154
155 pub const fn unknown() -> Self {
156 Self { start: 0, end: 0 }
157 }
158
159 pub const fn test_data() -> Self {
166 Self {
167 start: usize::MAX / 2,
168 end: usize::MAX / 2,
169 }
170 }
171
172 pub fn offset(&self, offset: usize) -> Self {
173 Self::new(self.start - offset, self.end - offset)
174 }
175
176 pub fn len(&self) -> usize {
178 self.end - self.start
179 }
180
181 pub fn is_empty(&self) -> bool {
183 self.start == self.end
184 }
185
186 pub fn subspan(&self, offset_start: usize, offset_end: usize) -> Option<Self> {
191 let len = self.len();
192
193 if offset_start > len || offset_end > len || offset_start > offset_end {
194 None
195 } else {
196 Some(Self::new(
197 self.start + offset_start,
198 self.start + offset_end,
199 ))
200 }
201 }
202
203 pub fn split_at(&self, offset: usize) -> Option<(Self, Self)> {
205 if offset < self.len() {
206 Some((
207 Self::new(self.start, self.start + offset),
208 Self::new(self.start + offset, self.end),
209 ))
210 } else {
211 None
212 }
213 }
214
215 pub fn contains(&self, pos: usize) -> bool {
216 self.start <= pos && pos < self.end
217 }
218
219 pub fn contains_span(&self, span: Self) -> bool {
220 self.start <= span.start && span.end <= self.end && span.end != 0
221 }
222
223 pub fn past(&self) -> Self {
225 Self {
226 start: self.end,
227 end: self.end,
228 }
229 }
230
231 pub fn from_row_column(row: usize, col: usize, contents: &str) -> Span {
233 let mut cur_row = 1;
234 let mut cur_col = 1;
235
236 for (offset, curr_byte) in contents.bytes().enumerate() {
237 if curr_byte == b'\n' {
238 cur_row += 1;
239 cur_col = 1;
240 } else if cur_row >= row && cur_col >= col {
241 return Span::new(offset, offset);
242 } else {
243 cur_col += 1;
244 }
245 }
246
247 Self {
248 start: contents.len(),
249 end: contents.len(),
250 }
251 }
252
253 pub fn append(self, after: Self) -> Self {
262 debug_assert!(
263 self.start <= after.start && self.end <= after.end,
264 "Can't merge two Spans that are not in order"
265 );
266 Self {
267 start: self.start,
268 end: after.end,
269 }
270 }
271
272 pub fn merge(self, other: Self) -> Self {
278 Self {
279 start: usize::min(self.start, other.start),
280 end: usize::max(self.end, other.end),
281 }
282 }
283
284 pub fn concat(spans: &[Self]) -> Self {
294 debug_assert!(spans.windows(2).all(|spans| {
297 let &[a, b] = spans else {
298 return false;
299 };
300 a.start <= b.start && a.end <= b.end
301 }));
302 Self {
303 start: spans.first().map(|s| s.start).unwrap_or(0),
304 end: spans.last().map(|s| s.end).unwrap_or(0),
305 }
306 }
307
308 pub fn merge_many(spans: impl IntoIterator<Item = Self>) -> Self {
314 spans
315 .into_iter()
316 .reduce(Self::merge)
317 .unwrap_or(Self::unknown())
318 }
319}
320
321impl IntoValue for Span {
322 fn into_value(self, span: Span) -> Value {
323 let record = record! {
324 "start" => Value::int(self.start as i64, self),
325 "end" => Value::int(self.end as i64, self),
326 };
327 record.into_value(span)
328 }
329}
330
331impl FromValue for Span {
332 fn from_value(value: Value) -> Result<Self, ShellError> {
333 let rec = value.as_record();
334 match rec {
335 Ok(val) => {
336 let Some(pre_start) = val.get("start") else {
337 return Err(ShellError::GenericError {
338 error: "Unable to parse Span.".into(),
339 msg: "`start` must be an `int`".into(),
340 span: Some(value.span()),
341 help: None,
342 inner: vec![],
343 });
344 };
345 let Some(pre_end) = val.get("end") else {
346 return Err(ShellError::GenericError {
347 error: "Unable to parse Span.".into(),
348 msg: "`end` must be an `int`".into(),
349 span: Some(value.span()),
350 help: None,
351 inner: vec![],
352 });
353 };
354 let start = pre_start.as_int()? as usize;
355 let end = pre_end.as_int()? as usize;
356 if start <= end {
357 Ok(Self::new(start, end))
358 } else {
359 Err(ShellError::GenericError {
360 error: "Unable to parse Span.".into(),
361 msg: "`end` must not be less than `start`".into(),
362 span: Some(value.span()),
363 help: None,
364 inner: vec![],
365 })
366 }
367 }
368 _ => Err(ShellError::TypeMismatch {
369 err_message: "Must be a record".into(),
370 span: value.span(),
371 }),
372 }
373 }
374}
375
376impl From<Span> for SourceSpan {
377 fn from(s: Span) -> Self {
378 Self::new(s.start.into(), s.end - s.start)
379 }
380}
381
382pub trait ErrSpan {
388 type Result;
389
390 fn err_span(self, span: Span) -> Self::Result;
392}
393
394impl<T, E> ErrSpan for Result<T, E> {
395 type Result = Result<T, Spanned<E>>;
396
397 fn err_span(self, span: Span) -> Self::Result {
398 self.map_err(|err| err.into_spanned(span))
399 }
400}