@@ -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 :: < CHUNK_SIZE > ( ) ;
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 :: < u8 > ( ) 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 < usize > ) {
54
104
let len = self . iter . len ( ) ;
0 commit comments