1pub 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}