@@ -80,8 +80,6 @@ pub struct FormatSpec<'a> {
8080/// Enum describing where an argument for a format can be located.
8181#[ derive( Copy , Clone , PartialEq ) ]
8282pub enum Position < ' a > {
83- /// The argument will be in the next position. This is the default.
84- ArgumentNext ,
8583 /// The argument is located at a specific index.
8684 ArgumentIs ( usize ) ,
8785 /// The argument has a name.
@@ -127,8 +125,6 @@ pub enum Count<'a> {
127125 CountIsName ( & ' a str ) ,
128126 /// The count is specified by the argument at the given index.
129127 CountIsParam ( usize ) ,
130- /// The count is specified by the next parameter.
131- CountIsNextParam ,
132128 /// The count is implied and cannot be explicitly specified.
133129 CountImplied ,
134130}
@@ -144,6 +140,8 @@ pub struct Parser<'a> {
144140 cur : iter:: Peekable < str:: CharIndices < ' a > > ,
145141 /// Error messages accumulated during parsing
146142 pub errors : Vec < string:: String > ,
143+ /// Current position of implicit positional argument pointer
144+ curarg : usize ,
147145}
148146
149147impl < ' a > Iterator for Parser < ' a > {
@@ -186,6 +184,7 @@ impl<'a> Parser<'a> {
186184 input : s,
187185 cur : s. char_indices ( ) . peekable ( ) ,
188186 errors : vec ! [ ] ,
187+ curarg : 0 ,
189188 }
190189 }
191190
@@ -259,21 +258,40 @@ impl<'a> Parser<'a> {
259258 /// Parses an Argument structure, or what's contained within braces inside
260259 /// the format string
261260 fn argument ( & mut self ) -> Argument < ' a > {
261+ let pos = self . position ( ) ;
262+ let format = self . format ( ) ;
263+
264+ // Resolve position after parsing format spec.
265+ let pos = match pos {
266+ Some ( position) => position,
267+ None => {
268+ let i = self . curarg ;
269+ self . curarg += 1 ;
270+ ArgumentIs ( i)
271+ }
272+ } ;
273+
262274 Argument {
263- position : self . position ( ) ,
264- format : self . format ( ) ,
275+ position : pos ,
276+ format : format,
265277 }
266278 }
267279
268280 /// Parses a positional argument for a format. This could either be an
269281 /// integer index of an argument, a named argument, or a blank string.
270- fn position ( & mut self ) -> Position < ' a > {
282+ /// Returns `Some(parsed_position)` if the position is not implicitly
283+ /// consuming a macro argument, `None` if it's the case.
284+ fn position ( & mut self ) -> Option < Position < ' a > > {
271285 if let Some ( i) = self . integer ( ) {
272- ArgumentIs ( i)
286+ Some ( ArgumentIs ( i) )
273287 } else {
274288 match self . cur . peek ( ) {
275- Some ( & ( _, c) ) if c. is_alphabetic ( ) => ArgumentNamed ( self . word ( ) ) ,
276- _ => ArgumentNext ,
289+ Some ( & ( _, c) ) if c. is_alphabetic ( ) => Some ( ArgumentNamed ( self . word ( ) ) ) ,
290+
291+ // This is an `ArgumentNext`.
292+ // Record the fact and do the resolution after parsing the
293+ // format spec, to make things like `{:.*}` work.
294+ _ => None ,
277295 }
278296 }
279297 }
@@ -340,7 +358,11 @@ impl<'a> Parser<'a> {
340358 }
341359 if self . consume ( '.' ) {
342360 if self . consume ( '*' ) {
343- spec. precision = CountIsNextParam ;
361+ // Resolve `CountIsNextParam`.
362+ // We can do this immediately as `position` is resolved later.
363+ let i = self . curarg ;
364+ self . curarg += 1 ;
365+ spec. precision = CountIsParam ( i) ;
344366 } else {
345367 spec. precision = self . count ( ) ;
346368 }
@@ -487,7 +509,7 @@ mod tests {
487509 fn format_nothing ( ) {
488510 same ( "{}" ,
489511 & [ NextArgument ( Argument {
490- position : ArgumentNext ,
512+ position : ArgumentIs ( 0 ) ,
491513 format : fmtdflt ( ) ,
492514 } ) ] ) ;
493515 }
@@ -565,7 +587,7 @@ mod tests {
565587 fn format_counts ( ) {
566588 same ( "{:10s}" ,
567589 & [ NextArgument ( Argument {
568- position : ArgumentNext ,
590+ position : ArgumentIs ( 0 ) ,
569591 format : FormatSpec {
570592 fill : None ,
571593 align : AlignUnknown ,
@@ -577,7 +599,7 @@ mod tests {
577599 } ) ] ) ;
578600 same ( "{:10$.10s}" ,
579601 & [ NextArgument ( Argument {
580- position : ArgumentNext ,
602+ position : ArgumentIs ( 0 ) ,
581603 format : FormatSpec {
582604 fill : None ,
583605 align : AlignUnknown ,
@@ -589,19 +611,19 @@ mod tests {
589611 } ) ] ) ;
590612 same ( "{:.*s}" ,
591613 & [ NextArgument ( Argument {
592- position : ArgumentNext ,
614+ position : ArgumentIs ( 1 ) ,
593615 format : FormatSpec {
594616 fill : None ,
595617 align : AlignUnknown ,
596618 flags : 0 ,
597- precision : CountIsNextParam ,
619+ precision : CountIsParam ( 0 ) ,
598620 width : CountImplied ,
599621 ty : "s" ,
600622 } ,
601623 } ) ] ) ;
602624 same ( "{:.10$s}" ,
603625 & [ NextArgument ( Argument {
604- position : ArgumentNext ,
626+ position : ArgumentIs ( 0 ) ,
605627 format : FormatSpec {
606628 fill : None ,
607629 align : AlignUnknown ,
@@ -613,7 +635,7 @@ mod tests {
613635 } ) ] ) ;
614636 same ( "{:a$.b$s}" ,
615637 & [ NextArgument ( Argument {
616- position : ArgumentNext ,
638+ position : ArgumentIs ( 0 ) ,
617639 format : FormatSpec {
618640 fill : None ,
619641 align : AlignUnknown ,
@@ -628,7 +650,7 @@ mod tests {
628650 fn format_flags ( ) {
629651 same ( "{:-}" ,
630652 & [ NextArgument ( Argument {
631- position : ArgumentNext ,
653+ position : ArgumentIs ( 0 ) ,
632654 format : FormatSpec {
633655 fill : None ,
634656 align : AlignUnknown ,
@@ -640,7 +662,7 @@ mod tests {
640662 } ) ] ) ;
641663 same ( "{:+#}" ,
642664 & [ NextArgument ( Argument {
643- position : ArgumentNext ,
665+ position : ArgumentIs ( 0 ) ,
644666 format : FormatSpec {
645667 fill : None ,
646668 align : AlignUnknown ,
0 commit comments