Skip to content

Commit f896f50

Browse files
committed
optimize str::iter::Chars::advance_by
this avoids part of the char decoding work by not looking at utf8 continuation bytes
1 parent 9847c64 commit f896f50

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

library/core/src/str/iter.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
88
use crate::ops::Try;
99
use crate::option;
1010
use crate::slice::{self, Split as SliceSplit};
11+
use core::num::NonZeroUsize;
1112

1213
use super::from_utf8_unchecked;
1314
use super::pattern::Pattern;
@@ -49,6 +50,22 @@ impl<'a> Iterator for Chars<'a> {
4950
super::count::count_chars(self.as_str())
5051
}
5152

53+
#[inline]
54+
fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZeroUsize> {
55+
let bytes = &mut self.iter;
56+
57+
while (remainder > 0) && (bytes.len() > 0) {
58+
remainder -= 1;
59+
let b = bytes.as_slice()[0];
60+
let slurped = super::validations::utf8_char_width(b);
61+
// SAFETY: utf8-validity guarantees that the continuation bytes must be present
62+
// and therefore we can skip this amount of bytes.
63+
unsafe { bytes.advance_by(slurped).unwrap_unchecked() };
64+
}
65+
66+
NonZeroUsize::new(remainder).map_or(Ok(()), Err)
67+
}
68+
5269
#[inline]
5370
fn size_hint(&self) -> (usize, Option<usize>) {
5471
let len = self.iter.len();

0 commit comments

Comments
 (0)