diff --git a/sway-types/Cargo.toml b/sway-types/Cargo.toml index f0d1ecf7ff8..bf8cf13cac1 100644 --- a/sway-types/Cargo.toml +++ b/sway-types/Cargo.toml @@ -9,6 +9,7 @@ license.workspace = true repository.workspace = true [dependencies] +bytecount = "0.6" fuel-asm = { workspace = true } fuel-crypto = { workspace = true } fuel-tx = { workspace = true } diff --git a/sway-types/src/span.rs b/sway-types/src/span.rs index e852c2e4fdc..b78ad7b1e72 100644 --- a/sway-types/src/span.rs +++ b/sway-types/src/span.rs @@ -21,17 +21,24 @@ impl<'a> Position<'a> { input.get(pos..).map(|_| Position { input, pos }) } - #[inline] pub fn line_col(&self) -> (usize, usize) { if self.pos > self.input.len() { panic!("position out of bounds"); } - let slice = &self.input[..self.pos]; - let lines = slice.split('\n').collect::>(); - let line_count = lines.len(); - let last_line_len = lines.last().unwrap_or(&"").chars().count() + 1; - (line_count, last_line_len) + // This is performance critical, so we use bytecount instead of a naive implementation. + let newlines_up_to_pos = bytecount::count(&self.input.as_bytes()[..self.pos], b'\n'); + let line = newlines_up_to_pos + 1; + + // Find the last newline character before the position + let last_newline_pos = match self.input[..self.pos].rfind('\n') { + Some(pos) => pos + 1, // Start after the newline + None => 0, // If no newline, start is at the beginning + }; + + // Column number should start from 1, not 0 + let col = self.pos - last_newline_pos + 1; + (line, col) } }