@@ -968,6 +968,8 @@ impl<'a> Tokenizer<'a> {
968968 line : 1 ,
969969 col : 1 ,
970970 } ;
971+ // Tokens, whitespace included, average about 2.5 input bytes each.
972+ buf. reserve ( self . query . len ( ) / 2 ) ;
971973
972974 let mut location = state. location ( ) ;
973975 while let Some ( token) = self . next_token ( & mut state, buf. last ( ) . map ( |t| & t. token ) ) ? {
@@ -1043,7 +1045,6 @@ impl<'a> Tokenizer<'a> {
10431045 chars : & mut State ,
10441046 ) -> Result < Option < Token > , TokenizerError > {
10451047 chars. next ( ) ; // consume the first char
1046- let ch: String = ch. into_iter ( ) . collect ( ) ;
10471048 let word = self . tokenize_word ( ch, chars) ;
10481049
10491050 // TODO: implement parsing of exponent here
@@ -1116,7 +1117,7 @@ impl<'a> Tokenizer<'a> {
11161117 }
11171118 _ => {
11181119 // regular identifier starting with an "b" or "B"
1119- let s = self . tokenize_word ( b , chars) ;
1120+ let s = self . tokenize_word ( [ b ] , chars) ;
11201121 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
11211122 }
11221123 }
@@ -1143,7 +1144,7 @@ impl<'a> Tokenizer<'a> {
11431144 ) ,
11441145 _ => {
11451146 // regular identifier starting with an "r" or "R"
1146- let s = self . tokenize_word ( b , chars) ;
1147+ let s = self . tokenize_word ( [ b ] , chars) ;
11471148 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
11481149 }
11491150 }
@@ -1168,13 +1169,13 @@ impl<'a> Tokenizer<'a> {
11681169 self . tokenize_quote_delimited_string ( chars, & [ n, q] )
11691170 . map ( |s| Some ( Token :: NationalQuoteDelimitedStringLiteral ( s) ) )
11701171 } else {
1171- let s = self . tokenize_word ( String :: from_iter ( [ n, q] ) , chars) ;
1172+ let s = self . tokenize_word ( [ n, q] , chars) ;
11721173 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
11731174 }
11741175 }
11751176 _ => {
11761177 // regular identifier starting with an "N"
1177- let s = self . tokenize_word ( n , chars) ;
1178+ let s = self . tokenize_word ( [ n ] , chars) ;
11781179 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
11791180 }
11801181 }
@@ -1185,7 +1186,7 @@ impl<'a> Tokenizer<'a> {
11851186 self . tokenize_quote_delimited_string ( chars, & [ q] )
11861187 . map ( |s| Some ( Token :: QuoteDelimitedStringLiteral ( s) ) )
11871188 } else {
1188- let s = self . tokenize_word ( q , chars) ;
1189+ let s = self . tokenize_word ( [ q ] , chars) ;
11891190 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
11901191 }
11911192 }
@@ -1201,7 +1202,7 @@ impl<'a> Tokenizer<'a> {
12011202 }
12021203 _ => {
12031204 // regular identifier starting with an "E" or "e"
1204- let s = self . tokenize_word ( x , chars) ;
1205+ let s = self . tokenize_word ( [ x ] , chars) ;
12051206 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
12061207 }
12071208 }
@@ -1220,7 +1221,7 @@ impl<'a> Tokenizer<'a> {
12201221 }
12211222 }
12221223 // regular identifier starting with an "U" or "u"
1223- let s = self . tokenize_word ( x , chars) ;
1224+ let s = self . tokenize_word ( [ x ] , chars) ;
12241225 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
12251226 }
12261227 // The spec only allows an uppercase 'X' to introduce a hex
@@ -1235,7 +1236,7 @@ impl<'a> Tokenizer<'a> {
12351236 }
12361237 _ => {
12371238 // regular identifier starting with an "X"
1238- let s = self . tokenize_word ( x , chars) ;
1239+ let s = self . tokenize_word ( [ x ] , chars) ;
12391240 Ok ( Some ( Token :: make_word_owned ( s, None ) ) )
12401241 }
12411242 }
@@ -2062,11 +2063,14 @@ impl<'a> Tokenizer<'a> {
20622063 }
20632064
20642065 /// Tokenize an identifier or keyword, after the first char is already consumed.
2065- fn tokenize_word ( & self , first_chars : impl Into < String > , chars : & mut State ) -> String {
2066- let mut s = first_chars. into ( ) ;
2067- s. push_str ( & peeking_take_while ( chars, |ch| {
2068- self . dialect . is_identifier_part ( ch)
2069- } ) ) ;
2066+ fn tokenize_word (
2067+ & self ,
2068+ first_chars : impl IntoIterator < Item = char > ,
2069+ chars : & mut State ,
2070+ ) -> String {
2071+ let mut s = String :: new ( ) ;
2072+ s. extend ( first_chars) ;
2073+ peeking_take_while_into ( chars, & mut s, |ch| self . dialect . is_identifier_part ( ch) ) ;
20702074 s
20712075 }
20722076
@@ -2415,17 +2419,25 @@ impl<'a> Tokenizer<'a> {
24152419/// Read from `chars` until `predicate` returns `false` or EOF is hit.
24162420/// Return the characters read as String, and keep the first non-matching
24172421/// char available as `chars.next()`.
2418- fn peeking_take_while ( chars : & mut State , mut predicate : impl FnMut ( char ) -> bool ) -> String {
2422+ fn peeking_take_while ( chars : & mut State , predicate : impl FnMut ( char ) -> bool ) -> String {
24192423 let mut s = String :: new ( ) ;
2424+ peeking_take_while_into ( chars, & mut s, predicate) ;
2425+ s
2426+ }
2427+
2428+ /// [`peeking_take_while`] appending into an existing buffer.
2429+ fn peeking_take_while_into (
2430+ chars : & mut State ,
2431+ s : & mut String ,
2432+ mut predicate : impl FnMut ( char ) -> bool ,
2433+ ) {
24202434 while let Some ( & ch) = chars. peek ( ) {
2421- if predicate ( ch) {
2422- chars. next ( ) ; // consume
2423- s. push ( ch) ;
2424- } else {
2435+ if !predicate ( ch) {
24252436 break ;
24262437 }
2438+ chars. next ( ) ; // consume
2439+ s. push ( ch) ;
24272440 }
2428- s
24292441}
24302442
24312443fn unescape_single_quoted_string ( chars : & mut State < ' _ > ) -> Option < String > {
0 commit comments