optimize str::iter::Chars::advance_by · rust-lang/rust@40cf1f9 (original) (raw)
`@@ -8,6 +8,7 @@ use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
`
8
8
`use crate::ops::Try;
`
9
9
`use crate::option;
`
10
10
`use crate::slice::{self, Split as SliceSplit};
`
``
11
`+
use core::num::NonZeroUsize;
`
11
12
``
12
13
`use super::from_utf8_unchecked;
`
13
14
`use super::pattern::Pattern;
`
`@@ -49,6 +50,55 @@ impl<'a> Iterator for Chars<'a> {
`
49
50
`super::count::count_chars(self.as_str())
`
50
51
`}
`
51
52
``
``
53
`+
#[inline]
`
``
54
`+
fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZeroUsize> {
`
``
55
`+
const CHUNK_SIZE: usize = 32;
`
``
56
+
``
57
`+
if remainder >= CHUNK_SIZE {
`
``
58
`+
let mut chunks = self.iter.as_slice().array_chunks::();
`
``
59
`+
let mut bytes_skipped: usize = 0;
`
``
60
+
``
61
`+
while remainder > CHUNK_SIZE
`
``
62
`+
&& let Some(chunk) = chunks.next()
`
``
63
`+
{
`
``
64
`+
bytes_skipped += CHUNK_SIZE;
`
``
65
+
``
66
`+
let mut start_bytes = [false; CHUNK_SIZE];
`
``
67
+
``
68
`+
for i in 0..CHUNK_SIZE {
`
``
69
`+
start_bytes[i] = !super::validations::utf8_is_cont_byte(chunk[i]);
`
``
70
`+
}
`
``
71
+
``
72
`+
remainder -= start_bytes.into_iter().map(|i| i as u8).sum::() as usize;
`
``
73
`+
}
`
``
74
+
``
75
`+
// SAFETY: The amount of bytes exists since we just iterated over them,
`
``
76
`+
// so advance_by will succeed.
`
``
77
`+
unsafe { self.iter.advance_by(bytes_skipped).unwrap_unchecked() };
`
``
78
+
``
79
`+
// skip trailing continuation bytes
`
``
80
`+
while self.iter.len() > 0 {
`
``
81
`+
let b = self.iter.as_slice()[0];
`
``
82
`+
if !super::validations::utf8_is_cont_byte(b) {
`
``
83
`+
break;
`
``
84
`+
}
`
``
85
`+
// SAFETY: We just peeked at the byte, therefore it exists
`
``
86
`+
unsafe { self.iter.advance_by(1).unwrap_unchecked() };
`
``
87
`+
}
`
``
88
`+
}
`
``
89
+
``
90
`+
while (remainder > 0) && (self.iter.len() > 0) {
`
``
91
`+
remainder -= 1;
`
``
92
`+
let b = self.iter.as_slice()[0];
`
``
93
`+
let slurp = super::validations::utf8_char_width(b);
`
``
94
`+
// SAFETY: utf8 validity requires that the string must contain
`
``
95
`+
// the continuation bytes (if any)
`
``
96
`+
unsafe { self.iter.advance_by(slurp).unwrap_unchecked() };
`
``
97
`+
}
`
``
98
+
``
99
`+
NonZeroUsize::new(remainder).map_or(Ok(()), Err)
`
``
100
`+
}
`
``
101
+
52
102
`#[inline]
`
53
103
`fn size_hint(&self) -> (usize, Option) {
`
54
104
`let len = self.iter.len();
`