Skip to content

Commit 3759186

Browse files
committed
Avoid checking long strings for matching against whitespace
Previously, the string was checked for starting with newlines and ending with spaces, then ensuring that the length of those substrings were short enough to use our constant. Instead, only do the check for as many items as we have in the WS constant. In the worst case, this avoids an O(n) check if the input is a long string of `\n`, possibly followed by a long string of spaces.
1 parent 19ee1b8 commit 3759186

File tree

1 file changed

+18
-5
lines changed
  • src/tools/rust-analyzer/lib/smol_str/src

1 file changed

+18
-5
lines changed

src/tools/rust-analyzer/lib/smol_str/src/lib.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
use std::{borrow::Borrow, cmp::Ordering, fmt, hash, iter, ops::Deref, sync::Arc};
1+
use std::{
2+
borrow::Borrow,
3+
cmp::{self, Ordering},
4+
fmt, hash, iter,
5+
ops::Deref,
6+
sync::Arc,
7+
};
28

39
/// A `SmolStr` is a string type that has the following properties:
410
///
@@ -358,10 +364,17 @@ impl Repr {
358364
};
359365
}
360366

361-
let newlines = text.bytes().take_while(|&b| b == b'\n').count();
362-
if text[newlines..].bytes().all(|b| b == b' ') {
363-
let spaces = len - newlines;
364-
if newlines <= N_NEWLINES && spaces <= N_SPACES {
367+
if len <= N_NEWLINES + N_SPACES {
368+
let bytes = text.as_bytes();
369+
let possible_newline_count = cmp::min(len, N_NEWLINES);
370+
let newlines = bytes[..possible_newline_count]
371+
.iter()
372+
.take_while(|&&b| b == b'\n')
373+
.count();
374+
let possible_space_count = len - newlines;
375+
if possible_space_count <= N_SPACES && bytes[newlines..].iter().all(|&b| b == b' ')
376+
{
377+
let spaces = possible_space_count;
365378
return Repr::Substring { newlines, spaces };
366379
}
367380
}

0 commit comments

Comments
 (0)