1use crate::shell_error::generic::GenericError;
3use crate::{FromValue, IntoValue, ShellError, SpanId, Value, record};
4use miette::SourceSpan;
5use serde::{Deserialize, Serialize};
6use std::{fmt, ops::Deref};
7
8pub trait GetSpan {
9 fn get_span(&self, span_id: SpanId) -> Span;
10}
11
12#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
14pub struct Spanned<T> {
15 pub item: T,
16 pub span: Span,
17}
18
19impl<T> Spanned<T> {
20 pub fn as_ref(&self) -> Spanned<&T> {
22 Spanned {
23 item: &self.item,
24 span: self.span,
25 }
26 }
27
28 pub fn as_mut(&mut self) -> Spanned<&mut T> {
30 Spanned {
31 item: &mut self.item,
32 span: self.span,
33 }
34 }
35
36 pub fn as_deref(&self) -> Spanned<&<T as Deref>::Target>
40 where
41 T: Deref,
42 {
43 Spanned {
44 item: self.item.deref(),
45 span: self.span,
46 }
47 }
48
49 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanned<U> {
51 Spanned {
52 item: f(self.item),
53 span: self.span,
54 }
55 }
56}
57
58impl<T> Spanned<&T>
59where
60 T: ToOwned + ?Sized,
61{
62 pub fn to_owned(&self) -> Spanned<T::Owned> {
64 Spanned {
65 item: self.item.to_owned(),
66 span: self.span,
67 }
68 }
69}
70
71impl<T> Spanned<T>
72where
73 T: AsRef<str>,
74{
75 pub fn as_str(&self) -> Spanned<&str> {
77 Spanned {
78 item: self.item.as_ref(),
79 span: self.span,
80 }
81 }
82}
83
84impl<T, E> Spanned<Result<T, E>> {
85 pub fn transpose(self) -> Result<Spanned<T>, E> {
87 match self {
88 Spanned {
89 item: Ok(item),
90 span,
91 } => Ok(Spanned { item, span }),
92 Spanned {
93 item: Err(err),
94 span: _,
95 } => Err(err),
96 }
97 }
98}
99
100impl<T: fmt::Display> fmt::Display for Spanned<T> {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 fmt::Display::fmt(&self.item, f)
106 }
107}
108
109impl<T> From<Spanned<T>> for SourceSpan {
110 fn from(value: Spanned<T>) -> Self {
111 value.span.into()
112 }
113}
114
115pub trait IntoSpanned: Sized {
117 fn into_spanned(self, span: Span) -> Spanned<Self>;
129}
130
131impl<T> IntoSpanned for T {
132 fn into_spanned(self, span: Span) -> Spanned<Self> {
133 Spanned { item: self, span }
134 }
135}
136
137#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
141pub struct Span {
142 pub start: usize,
143 pub end: usize,
144}
145
146impl fmt::Debug for Span {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 const TEST_DATA: Span = Span::test_data();
149 const UNKNOWN: Span = Span::unknown();
150
151 match *self {
152 TEST_DATA => write!(f, "Span(TEST)"),
153 UNKNOWN => write!(f, "Span(UNKNOWN)"),
154 Span { start, end } => write!(f, "Span[{start}..{end}]"),
155 }
156 }
157}
158
159impl Span {
160 pub fn new(start: usize, end: usize) -> Self {
161 debug_assert!(
162 end >= start,
163 "Can't create a Span whose end < start, start={start}, end={end}"
164 );
165
166 Self { start, end }
167 }
168
169 pub const fn unknown() -> Self {
170 Self { start: 0, end: 0 }
171 }
172
173 pub const fn test_data() -> Self {
180 Self {
181 start: usize::MAX / 2,
182 end: usize::MAX / 2,
183 }
184 }
185
186 pub fn offset(&self, offset: usize) -> Self {
187 Self::new(self.start - offset, self.end - offset)
188 }
189
190 pub fn len(&self) -> usize {
192 self.end - self.start
193 }
194
195 pub fn is_empty(&self) -> bool {
197 self.start == self.end
198 }
199
200 pub fn subspan(&self, offset_start: usize, offset_end: usize) -> Option<Self> {
205 let len = self.len();
206
207 if offset_start > len || offset_end > len || offset_start > offset_end {
208 None
209 } else {
210 Some(Self::new(
211 self.start + offset_start,
212 self.start + offset_end,
213 ))
214 }
215 }
216
217 pub fn split_at(&self, offset: usize) -> Option<(Self, Self)> {
219 if offset < self.len() {
220 Some((
221 Self::new(self.start, self.start + offset),
222 Self::new(self.start + offset, self.end),
223 ))
224 } else {
225 None
226 }
227 }
228
229 pub fn contains(&self, pos: usize) -> bool {
230 self.start <= pos && pos < self.end
231 }
232
233 pub fn contains_span(&self, span: Self) -> bool {
234 self.start <= span.start && span.end <= self.end && span.end != 0
235 }
236
237 pub fn past(&self) -> Self {
239 Self {
240 start: self.end,
241 end: self.end,
242 }
243 }
244
245 pub fn from_row_column(row: usize, col: usize, contents: &str) -> Span {
247 let mut cur_row = 1;
248 let mut cur_col = 1;
249
250 for (offset, curr_byte) in contents.bytes().enumerate() {
251 if curr_byte == b'\n' {
252 cur_row += 1;
253 cur_col = 1;
254 } else if cur_row >= row && cur_col >= col {
255 return Span::new(offset, offset);
256 } else {
257 cur_col += 1;
258 }
259 }
260
261 Self {
262 start: contents.len(),
263 end: contents.len(),
264 }
265 }
266
267 pub fn append(self, after: Self) -> Self {
276 debug_assert!(
277 self.start <= after.start && self.end <= after.end,
278 "Can't merge two Spans that are not in order"
279 );
280 Self {
281 start: self.start,
282 end: after.end,
283 }
284 }
285
286 pub fn merge(self, other: Self) -> Self {
292 Self {
293 start: usize::min(self.start, other.start),
294 end: usize::max(self.end, other.end),
295 }
296 }
297
298 pub fn concat(spans: &[Self]) -> Self {
308 debug_assert!(spans.windows(2).all(|spans| {
311 let &[a, b] = spans else {
312 return false;
313 };
314 a.start <= b.start && a.end <= b.end
315 }));
316 Self {
317 start: spans.first().map(|s| s.start).unwrap_or(0),
318 end: spans.last().map(|s| s.end).unwrap_or(0),
319 }
320 }
321
322 pub fn merge_many(spans: impl IntoIterator<Item = Self>) -> Self {
328 spans
329 .into_iter()
330 .reduce(Self::merge)
331 .unwrap_or(Self::unknown())
332 }
333}
334
335impl IntoValue for Span {
336 fn into_value(self, span: Span) -> Value {
337 let record = record! {
338 "start" => Value::int(self.start as i64, self),
339 "end" => Value::int(self.end as i64, self),
340 };
341 record.into_value(span)
342 }
343}
344
345impl FromValue for Span {
346 fn from_value(value: Value) -> Result<Self, ShellError> {
347 let rec = value.as_record();
348 match rec {
349 Ok(val) => {
350 let Some(pre_start) = val.get("start") else {
351 return Err(ShellError::Generic(GenericError::new(
352 "Unable to parse Span.",
353 "`start` must be an `int`",
354 value.span(),
355 )));
356 };
357 let Some(pre_end) = val.get("end") else {
358 return Err(ShellError::Generic(GenericError::new(
359 "Unable to parse Span.",
360 "`end` must be an `int`",
361 value.span(),
362 )));
363 };
364 let start = pre_start.as_int()? as usize;
365 let end = pre_end.as_int()? as usize;
366 if start <= end {
367 Ok(Self::new(start, end))
368 } else {
369 Err(ShellError::Generic(GenericError::new(
370 "Unable to parse Span.",
371 "`end` must not be less than `start`",
372 value.span(),
373 )))
374 }
375 }
376 _ => Err(ShellError::TypeMismatch {
377 err_message: "Must be a record".into(),
378 span: value.span(),
379 }),
380 }
381 }
382}
383
384impl From<Span> for SourceSpan {
385 fn from(s: Span) -> Self {
386 Self::new(s.start.into(), s.end - s.start)
387 }
388}
389
390pub trait ErrSpan {
396 type Result;
397
398 fn err_span(self, span: Span) -> Self::Result;
400}
401
402impl<T, E> ErrSpan for Result<T, E> {
403 type Result = Result<T, Spanned<E>>;
404
405 fn err_span(self, span: Span) -> Self::Result {
406 self.map_err(|err| err.into_spanned(span))
407 }
408}