sentience_tokenize/
span.rs

1use crate::Span;
2
3pub struct LineMap {
4    starts: Vec<usize>,
5}
6
7impl LineMap {
8    pub fn new(src: &str) -> Self {
9        let mut starts = Vec::with_capacity(128);
10        starts.push(0);
11        for (i, b) in src.bytes().enumerate() {
12            if b == b'\n' {
13                starts.push(i + 1);
14            }
15        }
16        Self { starts }
17    }
18
19    pub fn to_line_col(&self, byte: usize) -> (usize, usize) {
20        let i = match self.starts.binary_search(&byte) {
21            Ok(k) => k,
22            Err(k) => k.saturating_sub(1),
23        };
24        (i + 1, byte.saturating_sub(self.starts[i]) + 1)
25    }
26
27    pub fn span_lines(&self, span: Span) -> ((usize, usize), (usize, usize)) {
28        (self.to_line_col(span.start), self.to_line_col(span.end))
29    }
30
31    pub fn line_count(&self) -> usize {
32        self.starts.len()
33    }
34}