1use chumsky::span::SimpleSpan;
2use std::ops::Deref;
3
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct Span {
6 pub start: usize,
8 pub end: usize,
10}
11
12impl Span {
13 pub fn whole_str(s: &str) -> Self {
14 Self {
15 start: 0,
16 end: s.len(),
17 }
18 }
19
20 pub fn join(self, other: Self) -> Self {
21 Self {
22 start: self.start.min(other.start),
23 end: self.end.max(other.end),
24 }
25 }
26
27 pub fn test_span() -> Self {
28 Self { start: 0, end: 0 }
29 }
30
31 pub fn is_test(self) -> bool {
32 self.start == 0 && self.end == 0
33 }
34}
35
36impl From<SimpleSpan> for Span {
37 fn from(value: SimpleSpan) -> Self {
38 Self {
39 start: value.start,
40 end: value.end,
41 }
42 }
43}
44
45#[derive(Debug, Clone)]
46pub struct Spanned<T>(T, Span);
47
48impl<T: PartialEq> PartialEq for Spanned<T> {
49 fn eq(&self, other: &Self) -> bool {
50 **self == **other
51 && (self.span() == other.span()
52 || self.span().is_test()
53 || other.span().is_test())
54 }
55}
56
57impl<T> Deref for Spanned<T> {
58 type Target = T;
59 fn deref(&self) -> &Self::Target {
60 &self.0
61 }
62}
63
64impl<T> Spanned<T> {
65 pub fn span(&self) -> Span {
66 self.1
67 }
68}
69
70pub trait WithSpan: Sized {
71 fn with_span(self, span: impl Into<Span>) -> Spanned<Self> {
72 Spanned(self, span.into())
73 }
74
75 fn test_span(self) -> Spanned<Self> {
76 self.with_span(Span::test_span())
77 }
78}
79
80impl<T> WithSpan for T {}