@@ -37,6 +37,7 @@ pub use self::Count::*;
37
37
38
38
use std:: str;
39
39
use std:: string;
40
+ use std:: iter;
40
41
41
42
/// A piece is a portion of the format string which represents the next part
42
43
/// to emit. These are emitted as a stream by the `Parser` class.
@@ -141,7 +142,7 @@ pub enum Count<'a> {
141
142
/// necessary there's probably lots of room for improvement performance-wise.
142
143
pub struct Parser < ' a > {
143
144
input : & ' a str ,
144
- cur : str:: CharIndices < ' a > ,
145
+ cur : iter :: Peekable < str:: CharIndices < ' a > > ,
145
146
/// Error messages accumulated during parsing
146
147
pub errors : Vec < string:: String > ,
147
148
}
@@ -150,28 +151,31 @@ impl<'a> Iterator for Parser<'a> {
150
151
type Item = Piece < ' a > ;
151
152
152
153
fn next ( & mut self ) -> Option < Piece < ' a > > {
153
- match self . cur . clone ( ) . next ( ) {
154
- Some ( ( pos, '{' ) ) => {
155
- self . cur . next ( ) ;
156
- if self . consume ( '{' ) {
157
- Some ( String ( self . string ( pos + 1 ) ) )
158
- } else {
159
- let ret = Some ( NextArgument ( self . argument ( ) ) ) ;
160
- self . must_consume ( '}' ) ;
161
- ret
154
+ if let Some ( & ( pos, c) ) = self . cur . peek ( ) {
155
+ match c {
156
+ '{' => {
157
+ self . cur . next ( ) ;
158
+ if self . consume ( '{' ) {
159
+ Some ( String ( self . string ( pos + 1 ) ) )
160
+ } else {
161
+ let ret = Some ( NextArgument ( self . argument ( ) ) ) ;
162
+ self . must_consume ( '}' ) ;
163
+ ret
164
+ }
162
165
}
163
- }
164
- Some ( ( pos , '}' ) ) => {
165
- self . cur . next ( ) ;
166
- if self . consume ( '}' ) {
167
- Some ( String ( self . string ( pos + 1 ) ) )
168
- } else {
169
- self . err ( "unmatched `}` found" ) ;
170
- None
166
+ '}' => {
167
+ self . cur . next ( ) ;
168
+ if self . consume ( '}' ) {
169
+ Some ( String ( self . string ( pos + 1 ) ) )
170
+ } else {
171
+ self . err ( "unmatched `}` found" ) ;
172
+ None
173
+ }
171
174
}
175
+ _ => Some ( String ( self . string ( pos) ) ) ,
172
176
}
173
- Some ( ( pos , _ ) ) => { Some ( String ( self . string ( pos ) ) ) }
174
- None => None
177
+ } else {
178
+ None
175
179
}
176
180
}
177
181
}
@@ -181,7 +185,7 @@ impl<'a> Parser<'a> {
181
185
pub fn new ( s : & ' a str ) -> Parser < ' a > {
182
186
Parser {
183
187
input : s,
184
- cur : s. char_indices ( ) ,
188
+ cur : s. char_indices ( ) . peekable ( ) ,
185
189
errors : vec ! ( ) ,
186
190
}
187
191
}
@@ -197,61 +201,47 @@ impl<'a> Parser<'a> {
197
201
/// the current position, then the current iterator isn't moved and false is
198
202
/// returned, otherwise the character is consumed and true is returned.
199
203
fn consume ( & mut self , c : char ) -> bool {
200
- match self . cur . clone ( ) . next ( ) {
201
- Some ( ( _, maybe) ) if c == maybe => {
202
- self . cur . next ( ) ;
203
- true
204
- }
205
- Some ( ..) | None => false ,
204
+ if let Some ( & ( _, maybe) ) = self . cur . peek ( ) {
205
+ if c == maybe { self . cur . next ( ) ; true } else { false }
206
+ } else {
207
+ false
206
208
}
207
209
}
208
210
209
211
/// Forces consumption of the specified character. If the character is not
210
212
/// found, an error is emitted.
211
213
fn must_consume ( & mut self , c : char ) {
212
214
self . ws ( ) ;
213
- match self . cur . clone ( ) . next ( ) {
214
- Some ( ( _ , maybe ) ) if c == maybe => {
215
+ if let Some ( & ( _ , maybe ) ) = self . cur . peek ( ) {
216
+ if c == maybe {
215
217
self . cur . next ( ) ;
218
+ } else {
219
+ self . err ( & format ! ( "expected `{:?}`, found `{:?}`" , c, maybe) ) ;
216
220
}
217
- Some ( ( _, other) ) => {
218
- self . err ( & format ! ( "expected `{:?}`, found `{:?}`" , c,
219
- other) ) ;
220
- }
221
- None => {
222
- self . err ( & format ! ( "expected `{:?}` but string was terminated" ,
223
- c) ) ;
224
- }
221
+ } else {
222
+ self . err ( & format ! ( "expected `{:?}` but string was terminated" , c) ) ;
225
223
}
226
224
}
227
225
228
226
/// Consumes all whitespace characters until the first non-whitespace
229
227
/// character
230
228
fn ws ( & mut self ) {
231
- loop {
232
- match self . cur . clone ( ) . next ( ) {
233
- Some ( ( _, c) ) if c. is_whitespace ( ) => { self . cur . next ( ) ; }
234
- Some ( ..) | None => { return }
235
- }
229
+ while let Some ( & ( _, c) ) = self . cur . peek ( ) {
230
+ if c. is_whitespace ( ) { self . cur . next ( ) ; } else { break }
236
231
}
237
232
}
238
233
239
234
/// Parses all of a string which is to be considered a "raw literal" in a
240
235
/// format string. This is everything outside of the braces.
241
236
fn string ( & mut self , start : usize ) -> & ' a str {
242
- loop {
243
- // we may not consume the character, so clone the iterator
244
- match self . cur . clone ( ) . next ( ) {
245
- Some ( ( pos, '}' ) ) | Some ( ( pos, '{' ) ) => {
246
- return & self . input [ start..pos] ;
247
- }
248
- Some ( ..) => { self . cur . next ( ) ; }
249
- None => {
250
- self . cur . next ( ) ;
251
- return & self . input [ start..self . input . len ( ) ] ;
252
- }
237
+ // we may not consume the character, peek the iterator
238
+ while let Some ( & ( pos, c) ) = self . cur . peek ( ) {
239
+ match c {
240
+ '{' | '}' => { return & self . input [ start..pos] ; }
241
+ _ => { self . cur . next ( ) ; }
253
242
}
254
243
}
244
+ & self . input [ start..self . input . len ( ) ]
255
245
}
256
246
257
247
/// Parses an Argument structure, or what's contained within braces inside
@@ -266,15 +256,14 @@ impl<'a> Parser<'a> {
266
256
/// Parses a positional argument for a format. This could either be an
267
257
/// integer index of an argument, a named argument, or a blank string.
268
258
fn position ( & mut self ) -> Position < ' a > {
269
- match self . integer ( ) {
270
- Some ( i) => { ArgumentIs ( i) }
271
- None => {
272
- match self . cur . clone ( ) . next ( ) {
273
- Some ( ( _, c) ) if c. is_alphabetic ( ) => {
274
- ArgumentNamed ( self . word ( ) )
275
- }
276
- _ => ArgumentNext
259
+ if let Some ( i) = self . integer ( ) {
260
+ ArgumentIs ( i)
261
+ } else {
262
+ match self . cur . peek ( ) {
263
+ Some ( & ( _, c) ) if c. is_alphabetic ( ) => {
264
+ ArgumentNamed ( self . word ( ) )
277
265
}
266
+ _ => ArgumentNext
278
267
}
279
268
}
280
269
}
@@ -293,17 +282,14 @@ impl<'a> Parser<'a> {
293
282
if !self . consume ( ':' ) { return spec }
294
283
295
284
// fill character
296
- match self . cur . clone ( ) . next ( ) {
297
- Some ( ( _, c) ) => {
298
- match self . cur . clone ( ) . skip ( 1 ) . next ( ) {
299
- Some ( ( _, '>' ) ) | Some ( ( _, '<' ) ) | Some ( ( _, '^' ) ) => {
300
- spec. fill = Some ( c) ;
301
- self . cur . next ( ) ;
302
- }
303
- Some ( ..) | None => { }
285
+ if let Some ( & ( _, c) ) = self . cur . peek ( ) {
286
+ match self . cur . clone ( ) . skip ( 1 ) . next ( ) {
287
+ Some ( ( _, '>' ) ) | Some ( ( _, '<' ) ) | Some ( ( _, '^' ) ) => {
288
+ spec. fill = Some ( c) ;
289
+ self . cur . next ( ) ;
304
290
}
291
+ _ => { }
305
292
}
306
- None => { }
307
293
}
308
294
// Alignment
309
295
if self . consume ( '<' ) {
@@ -360,29 +346,20 @@ impl<'a> Parser<'a> {
360
346
/// for 'CountIsNextParam' because that is only used in precision, not
361
347
/// width.
362
348
fn count ( & mut self ) -> Count < ' a > {
363
- match self . integer ( ) {
364
- Some ( i) => {
349
+ if let Some ( i) = self . integer ( ) {
350
+ if self . consume ( '$' ) { CountIsParam ( i) } else { CountIs ( i) }
351
+ } else {
352
+ let tmp = self . cur . clone ( ) ;
353
+ let word = self . word ( ) ;
354
+ if word. is_empty ( ) {
355
+ self . cur = tmp;
356
+ CountImplied
357
+ } else {
365
358
if self . consume ( '$' ) {
366
- CountIsParam ( i )
359
+ CountIsName ( word )
367
360
} else {
368
- CountIs ( i)
369
- }
370
- }
371
- None => {
372
- let tmp = self . cur . clone ( ) ;
373
- match self . word ( ) {
374
- word if !word. is_empty ( ) => {
375
- if self . consume ( '$' ) {
376
- CountIsName ( word)
377
- } else {
378
- self . cur = tmp;
379
- CountImplied
380
- }
381
- }
382
- _ => {
383
- self . cur = tmp;
384
- CountImplied
385
- }
361
+ self . cur = tmp;
362
+ CountImplied
386
363
}
387
364
}
388
365
}
@@ -392,32 +369,26 @@ impl<'a> Parser<'a> {
392
369
/// be an alphabetic character followed by any number of alphanumeric
393
370
/// characters.
394
371
fn word ( & mut self ) -> & ' a str {
395
- let start = match self . cur . clone ( ) . next ( ) {
396
- Some ( ( pos, c) ) if c. is_xid_start ( ) => {
397
- self . cur . next ( ) ;
398
- pos
399
- }
400
- Some ( ..) | None => { return & self . input [ ..0 ] ; }
372
+ let start = match self . cur . peek ( ) {
373
+ Some ( & ( pos, c) ) if c. is_xid_start ( ) => { self . cur . next ( ) ; pos }
374
+ _ => { return & self . input [ ..0 ] ; }
401
375
} ;
402
- let end;
403
- loop {
404
- match self . cur . clone ( ) . next ( ) {
405
- Some ( ( _, c) ) if c. is_xid_continue ( ) => {
406
- self . cur . next ( ) ;
407
- }
408
- Some ( ( pos, _) ) => { end = pos; break }
409
- None => { end = self . input . len ( ) ; break }
376
+ while let Some ( & ( pos, c) ) = self . cur . peek ( ) {
377
+ if c. is_xid_continue ( ) {
378
+ self . cur . next ( ) ;
379
+ } else {
380
+ return & self . input [ start..pos] ;
410
381
}
411
382
}
412
- & self . input [ start..end ]
383
+ & self . input [ start..self . input . len ( ) ]
413
384
}
414
385
415
386
/// Optionally parses an integer at the current position. This doesn't deal
416
387
/// with overflow at all, it's just accumulating digits.
417
388
fn integer ( & mut self ) -> Option < usize > {
418
389
let mut cur = 0 ;
419
390
let mut found = false ;
420
- while let Some ( ( _, c) ) = self . cur . clone ( ) . next ( ) {
391
+ while let Some ( & ( _, c) ) = self . cur . peek ( ) {
421
392
if let Some ( i) = c. to_digit ( 10 ) {
422
393
cur = cur * 10 + i as usize ;
423
394
found = true ;
@@ -426,11 +397,7 @@ impl<'a> Parser<'a> {
426
397
break
427
398
}
428
399
}
429
- if found {
430
- Some ( cur)
431
- } else {
432
- None
433
- }
400
+ if found { Some ( cur) } else { None }
434
401
}
435
402
}
436
403
0 commit comments