Store line_end directly in NewlinePositions

This saves a second lookup in the positions array, improving
performance considerably. The lookup code is hot.
better_inline
Wilfred Hughes 2022-01-20 09:37:12 +07:00
parent ff9c272a35
commit dc8e52f52a
1 changed files with 14 additions and 22 deletions

@ -1,8 +1,6 @@
//! Manipulate lines of text and groups of lines.
use crate::positions::SingleLineSpan;
use lazy_static::lazy_static;
use regex::Regex;
use std::{cmp::max, fmt};
/// A distinct number type for line numbers, to prevent confusion with
@ -50,23 +48,23 @@ struct LinePosition {
/// line-relative positions.
#[derive(Debug)]
pub struct NewlinePositions {
/// A vector of the start positions of all the lines in `s`.
positions: Vec<usize>,
str_length: usize,
/// A vector of the start and end positions of all the lines in
/// `s`. Positions include the newline character itself.
positions: Vec<(usize, usize)>,
}
impl From<&str> for NewlinePositions {
fn from(s: &str) -> Self {
lazy_static! {
static ref NEWLINE_RE: Regex = Regex::new("\n").unwrap();
let mut line_start = 0;
let mut positions = vec![];
for line in s.split('\n') {
let line_end = line_start + line.len() + "\n".len();
// TODO: this assumes lines terminate with \n, not \r\n.
positions.push((line_start, line_end - 1));
line_start = line_end;
}
let mut positions: Vec<_> = NEWLINE_RE.find_iter(s).map(|mat| mat.end()).collect();
positions.insert(0, 0);
NewlinePositions {
positions,
str_length: s.len(),
}
NewlinePositions { positions }
}
}
@ -78,14 +76,8 @@ impl NewlinePositions {
let mut res = vec![];
// TODO: Use std::slice::binary_search here instead.
for (line_num, line_start) in self.positions.iter().enumerate() {
let line_end = match self.positions.get(line_num + 1) {
// TODO: this assumes lines terminate with \n, not \r\n.
Some(v) => *v - 1,
None => self.str_length,
};
if region_start > line_end {
for (line_num, (line_start, line_end)) in self.positions.iter().enumerate() {
if region_start > *line_end {
continue;
}
if *line_start > region_end {
@ -99,7 +91,7 @@ impl NewlinePositions {
} else {
region_start - line_start
},
end_col: if region_end < line_end {
end_col: if region_end < *line_end {
region_end - line_start
} else {
line_end - line_start