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();

`