udled_tokenizers/
utils.rs1use udled::Span;
2
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub struct Position {
6 pub line: usize,
7 pub character: usize,
8}
9
10impl Position {
11 pub fn new(line: usize, character: usize) -> Position {
12 Position { line, character }
13 }
14
15 pub fn into_span(self, source: &str) -> Option<Span> {
16 let mut line = 0;
17
18 if self.line == 0 {
19 return Some(Span::new(
20 self.character as usize,
21 (self.character as usize) + 1,
22 ));
23 }
24
25 for (idx, v) in source.bytes().enumerate() {
26 if (v as char) == '\n' {
27 line += 1;
28 }
29
30 if line == self.line {
31 let idx = idx + self.character as usize;
32 return Some(Span::new(idx, idx + 1));
33 }
34 }
35
36 None
37 }
38}
39
40#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct Range {
43 pub start: Position,
44 pub end: Position,
45}
46
47impl Range {
48 pub fn new(start: Position, end: Position) -> Range {
49 Range { start, end }
50 }
51
52 pub fn from_span(source: &str, span: Span) -> Option<Range> {
53 let mut s_line = 0;
54 let mut s_col = 0;
55 for (k, v) in source.bytes().enumerate() {
56 if k == span.start {
57 break;
58 }
59 if (v as char) == '\n' {
60 s_line += 1;
61 s_col = 0;
62 } else {
63 s_col += 1;
64 }
65 }
66
67 let mut e_line = s_line;
68 let mut e_col = s_col;
69
70 for (k, v) in source.bytes().enumerate().skip(span.start) {
71 if k == span.end {
72 return Some(Range::new(
73 Position::new(s_line, s_col),
74 Position::new(e_line, e_col),
75 ));
76 }
77 if (v as char) == '\n' {
78 e_line += 1;
79 e_col = 0;
80 } else {
81 e_col += 1;
82 }
83 }
84
85 None
86 }
87
88 pub fn into_span(self, source: &str) -> Option<Span> {
89 let start = self.start.into_span(source)?;
90 let end = self.end.into_span(source)?;
91 Some(start + end)
92 }
93}