typed_eval/
span.rs

1use chumsky::span::SimpleSpan;
2use std::ops::Deref;
3
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct Span {
6    // inclusive
7    pub start: usize,
8    // exclusive
9    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 {}