@@ -123,16 +123,24 @@ impl StrOrChar<'_> {
123123 }
124124 }
125125}
126- pub fn scanstring ( s : & str , end : usize , strict : bool ) -> Result < ( String , usize ) , DecodeError > {
127- let mut chunks: Vec < StrOrChar > = Vec :: new ( ) ;
126+ pub fn scanstring < ' a > (
127+ s : & ' a str ,
128+ end : usize ,
129+ strict : bool ,
130+ ) -> Result < ( String , usize ) , DecodeError > {
131+ let mut chunks: Vec < StrOrChar < ' a > > = Vec :: new ( ) ;
132+ let mut output_len = 0usize ;
133+ let mut push_chunk = |chunk : StrOrChar < ' a > | {
134+ output_len += chunk. len ( ) ;
135+ chunks. push ( chunk) ;
136+ } ;
128137 let mut chunk_start = end;
129138 let mut chars = s. char_indices ( ) . enumerate ( ) . skip ( end) . peekable ( ) ;
130139 while let Some ( ( char_i, ( i, c) ) ) = chars. next ( ) {
131140 match c {
132141 '"' => {
133- chunks. push ( StrOrChar :: Str ( & s[ chunk_start..i] ) ) ;
134- let len = chunks. iter ( ) . map ( |x| x. len ( ) ) . sum ( ) ;
135- let mut out = String :: with_capacity ( len) ;
142+ push_chunk ( StrOrChar :: Str ( & s[ chunk_start..i] ) ) ;
143+ let mut out = String :: with_capacity ( output_len) ;
136144 for x in chunks {
137145 match x {
138146 StrOrChar :: Str ( s) => out. push_str ( s) ,
@@ -158,7 +166,7 @@ pub fn scanstring(s: &str, end: usize, strict: bool) -> Result<(String, usize),
158166 't' => "\t " ,
159167 'u' => {
160168 let surrogate_err = || DecodeError :: new ( "unpaired surrogate" , char_i) ;
161- chunks . push ( StrOrChar :: Str ( & s[ chunk_start..i] ) ) ;
169+ push_chunk ( StrOrChar :: Str ( & s[ chunk_start..i] ) ) ;
162170 let mut uni = decode_unicode ( & mut chars, char_i) ?;
163171 chunk_start = char_i + 6 ;
164172 if ( 0xd800 ..=0xdbff ) . contains ( & uni) {
@@ -184,7 +192,7 @@ pub fn scanstring(s: &str, end: usize, strict: bool) -> Result<(String, usize),
184192 }
185193 }
186194 }
187- chunks . push ( StrOrChar :: Char (
195+ push_chunk ( StrOrChar :: Char (
188196 std:: char:: from_u32 ( uni) . ok_or_else ( surrogate_err) ?,
189197 ) ) ;
190198 continue ;
@@ -196,9 +204,9 @@ pub fn scanstring(s: &str, end: usize, strict: bool) -> Result<(String, usize),
196204 ) )
197205 }
198206 } ;
199- chunks . push ( StrOrChar :: Str ( & s[ chunk_start..i] ) ) ;
207+ push_chunk ( StrOrChar :: Str ( & s[ chunk_start..i] ) ) ;
200208 chunk_start = i + 2 ;
201- chunks . push ( StrOrChar :: Str ( esc) ) ;
209+ push_chunk ( StrOrChar :: Str ( esc) ) ;
202210 }
203211 '\x00' ..='\x1f' if strict => {
204212 return Err ( DecodeError :: new (
0 commit comments