efmt_core/
span.rs

1/// A procedural macro to derive [Span].
2pub use efmt_derive::Span;
3
4pub trait Span {
5    fn start_position(&self) -> Position;
6    fn end_position(&self) -> Position;
7
8    fn text<'a>(&self, s: &'a str) -> &'a str {
9        &s[self.start_position().offset()..self.end_position().offset()]
10    }
11
12    fn contains_newline(&self) -> bool {
13        self.start_position().line() != self.end_position().line()
14    }
15
16    fn contains(&self, position: Position) -> bool {
17        self.start_position().offset() <= position.offset()
18            && position.offset() < self.end_position().offset()
19    }
20}
21
22impl<T: Span + ?Sized> Span for &T {
23    fn start_position(&self) -> Position {
24        (**self).start_position()
25    }
26
27    fn end_position(&self) -> Position {
28        (**self).end_position()
29    }
30}
31
32impl<T: Span> Span for Box<T> {
33    fn start_position(&self) -> Position {
34        (**self).start_position()
35    }
36
37    fn end_position(&self) -> Position {
38        (**self).end_position()
39    }
40}
41
42impl Span for Position {
43    fn start_position(&self) -> Position {
44        *self
45    }
46
47    fn end_position(&self) -> Position {
48        *self
49    }
50}
51
52impl Span for std::ops::Range<Position> {
53    fn start_position(&self) -> Position {
54        self.start
55    }
56
57    fn end_position(&self) -> Position {
58        self.end
59    }
60}
61
62impl<A: Span, B: Span> Span for (A, B) {
63    fn start_position(&self) -> Position {
64        self.0.start_position()
65    }
66
67    fn end_position(&self) -> Position {
68        self.1.end_position()
69    }
70}
71
72impl<A: Span, B: Span, C: Span> Span for (A, B, C) {
73    fn start_position(&self) -> Position {
74        self.0.start_position()
75    }
76
77    fn end_position(&self) -> Position {
78        self.2.end_position()
79    }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
83pub struct Position {
84    offset: usize,
85    line: usize,
86    column: usize,
87}
88
89impl Position {
90    pub const fn new(offset: usize, line: usize, column: usize) -> Self {
91        Self {
92            offset,
93            line,
94            column,
95        }
96    }
97
98    pub const fn offset(self) -> usize {
99        self.offset
100    }
101
102    pub const fn line(self) -> usize {
103        self.line
104    }
105
106    pub const fn column(self) -> usize {
107        self.column
108    }
109}
110
111impl From<erl_tokenize::Position> for Position {
112    fn from(x: erl_tokenize::Position) -> Self {
113        Self::new(x.offset(), x.line(), x.column())
114    }
115}