Skip to main content

rue_diagnostic/
line_col.rs

1use std::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
4pub struct LineCol {
5    pub line: usize,
6    pub col: usize,
7}
8
9impl LineCol {
10    /// Returns the line and column of the given index in the source.
11    /// Line and column numbers are from 0.
12    pub fn new(source: &str, index: usize) -> Self {
13        let mut line = 0;
14        let mut col = 0;
15
16        for (i, character) in source.chars().enumerate() {
17            if i == index {
18                break;
19            }
20
21            if character == '\n' {
22                line += 1;
23                col = 0;
24            } else {
25                col += 1;
26            }
27        }
28
29        Self { line, col }
30    }
31
32    pub fn index(&self, source: &str) -> usize {
33        let mut current_line = 0;
34        let mut current_col = 0;
35
36        for (i, c) in source.chars().enumerate() {
37            if current_line == self.line && current_col == self.col {
38                return i;
39            }
40
41            if c == '\n' {
42                current_line += 1;
43                current_col = 0;
44            } else {
45                current_col += 1;
46            }
47        }
48
49        // Handle position at end of file
50        if current_line == self.line && current_col == self.col {
51            return source.len();
52        }
53
54        // Return source length if position is out of bounds
55        source.len()
56    }
57}
58
59impl fmt::Display for LineCol {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        write!(f, "{}:{}", self.line + 1, self.col + 1)
62    }
63}