@@ -37,6 +37,7 @@ pub use self::Count::*;
3737
3838use std:: str;
3939use std:: string;
40+ use std:: iter;
4041
4142/// A piece is a portion of the format string which represents the next part
4243/// to emit. These are emitted as a stream by the `Parser` class.
@@ -141,7 +142,7 @@ pub enum Count<'a> {
141142/// necessary there's probably lots of room for improvement performance-wise.
142143pub struct Parser < ' a > {
143144 input : & ' a str ,
144- cur : str:: CharIndices < ' a > ,
145+ cur : iter :: Peekable < str:: CharIndices < ' a > > ,
145146 /// Error messages accumulated during parsing
146147 pub errors : Vec < string:: String > ,
147148}
@@ -150,28 +151,31 @@ impl<'a> Iterator for Parser<'a> {
150151 type Item = Piece < ' a > ;
151152
152153 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+ }
162165 }
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+ }
171174 }
175+ _ => Some ( String ( self . string ( pos) ) ) ,
172176 }
173- Some ( ( pos , _ ) ) => { Some ( String ( self . string ( pos ) ) ) }
174- None => None
177+ } else {
178+ None
175179 }
176180 }
177181}
@@ -181,7 +185,7 @@ impl<'a> Parser<'a> {
181185 pub fn new ( s : & ' a str ) -> Parser < ' a > {
182186 Parser {
183187 input : s,
184- cur : s. char_indices ( ) ,
188+ cur : s. char_indices ( ) . peekable ( ) ,
185189 errors : vec ! ( ) ,
186190 }
187191 }
@@ -197,61 +201,47 @@ impl<'a> Parser<'a> {
197201 /// the current position, then the current iterator isn't moved and false is
198202 /// returned, otherwise the character is consumed and true is returned.
199203 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
206208 }
207209 }
208210
209211 /// Forces consumption of the specified character. If the character is not
210212 /// found, an error is emitted.
211213 fn must_consume ( & mut self , c : char ) {
212214 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 {
215217 self . cur . next ( ) ;
218+ } else {
219+ self . err ( & format ! ( "expected `{:?}`, found `{:?}`" , c, maybe) ) ;
216220 }
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) ) ;
225223 }
226224 }
227225
228226 /// Consumes all whitespace characters until the first non-whitespace
229227 /// character
230228 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 }
236231 }
237232 }
238233
239234 /// Parses all of a string which is to be considered a "raw literal" in a
240235 /// format string. This is everything outside of the braces.
241236 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 ( ) ; }
253242 }
254243 }
244+ & self . input [ start..self . input . len ( ) ]
255245 }
256246
257247 /// Parses an Argument structure, or what's contained within braces inside
@@ -266,15 +256,14 @@ impl<'a> Parser<'a> {
266256 /// Parses a positional argument for a format. This could either be an
267257 /// integer index of an argument, a named argument, or a blank string.
268258 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 ( ) )
277265 }
266+ _ => ArgumentNext
278267 }
279268 }
280269 }
@@ -293,17 +282,14 @@ impl<'a> Parser<'a> {
293282 if !self . consume ( ':' ) { return spec }
294283
295284 // 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 ( ) ;
304290 }
291+ _ => { }
305292 }
306- None => { }
307293 }
308294 // Alignment
309295 if self . consume ( '<' ) {
@@ -360,29 +346,20 @@ impl<'a> Parser<'a> {
360346 /// for 'CountIsNextParam' because that is only used in precision, not
361347 /// width.
362348 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 {
365358 if self . consume ( '$' ) {
366- CountIsParam ( i )
359+ CountIsName ( word )
367360 } 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
386363 }
387364 }
388365 }
@@ -392,32 +369,26 @@ impl<'a> Parser<'a> {
392369 /// be an alphabetic character followed by any number of alphanumeric
393370 /// characters.
394371 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 ] ; }
401375 } ;
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] ;
410381 }
411382 }
412- & self . input [ start..end ]
383+ & self . input [ start..self . input . len ( ) ]
413384 }
414385
415386 /// Optionally parses an integer at the current position. This doesn't deal
416387 /// with overflow at all, it's just accumulating digits.
417388 fn integer ( & mut self ) -> Option < usize > {
418389 let mut cur = 0 ;
419390 let mut found = false ;
420- while let Some ( ( _, c) ) = self . cur . clone ( ) . next ( ) {
391+ while let Some ( & ( _, c) ) = self . cur . peek ( ) {
421392 if let Some ( i) = c. to_digit ( 10 ) {
422393 cur = cur * 10 + i as usize ;
423394 found = true ;
@@ -426,11 +397,7 @@ impl<'a> Parser<'a> {
426397 break
427398 }
428399 }
429- if found {
430- Some ( cur)
431- } else {
432- None
433- }
400+ if found { Some ( cur) } else { None }
434401 }
435402}
436403
0 commit comments