@@ -3,6 +3,24 @@ use num_traits::Signed;
33use std:: cmp;
44use std:: str:: FromStr ;
55
6+ #[ derive( Debug , Copy , Clone , PartialEq ) ]
7+ pub enum FormatPreconversor {
8+ Str ,
9+ Repr ,
10+ Ascii ,
11+ }
12+
13+ impl FormatPreconversor {
14+ fn from_char ( c : char ) -> Option < FormatPreconversor > {
15+ match c {
16+ 's' => Some ( FormatPreconversor :: Str ) ,
17+ 'r' => Some ( FormatPreconversor :: Repr ) ,
18+ 'a' => Some ( FormatPreconversor :: Ascii ) ,
19+ _ => None ,
20+ }
21+ }
22+ }
23+
624#[ derive( Debug , Copy , Clone , PartialEq ) ]
725pub enum FormatAlign {
826 Left ,
@@ -56,6 +74,7 @@ pub enum FormatType {
5674
5775#[ derive( Debug , PartialEq ) ]
5876pub struct FormatSpec {
77+ preconversor : Option < FormatPreconversor > ,
5978 fill : Option < char > ,
6079 align : Option < FormatAlign > ,
6180 sign : Option < FormatSign > ,
@@ -75,6 +94,23 @@ fn get_num_digits(text: &str) -> usize {
7594 text. len ( )
7695}
7796
97+ fn parse_preconversor ( text : & str ) -> ( Option < FormatPreconversor > , & str ) {
98+ let mut chars = text. chars ( ) ;
99+ if chars. next ( ) != Some ( '!' ) {
100+ return ( None , text) ;
101+ }
102+
103+ match chars. next ( ) {
104+ None => ( None , text) , // Should fail instead?
105+ Some ( c) => {
106+ match FormatPreconversor :: from_char ( c) {
107+ Some ( preconversor) => ( Some ( preconversor) , chars. as_str ( ) ) ,
108+ None => ( None , text) , // Should fail instead?
109+ }
110+ } ,
111+ }
112+ }
113+
78114fn parse_align ( text : & str ) -> ( Option < FormatAlign > , & str ) {
79115 let mut chars = text. chars ( ) ;
80116 let maybe_align = chars. next ( ) . and_then ( FormatAlign :: from_char) ;
@@ -186,7 +222,8 @@ fn parse_format_type(text: &str) -> (Option<FormatType>, &str) {
186222}
187223
188224fn parse_format_spec ( text : & str ) -> FormatSpec {
189- let ( fill, align, after_align) = parse_fill_and_align ( text) ;
225+ let ( preconversor, after_preconversor) = parse_preconversor ( text) ;
226+ let ( fill, align, after_align) = parse_fill_and_align ( after_preconversor) ;
190227 let ( sign, after_sign) = parse_sign ( after_align) ;
191228 let ( alternate_form, after_alternate_form) = parse_alternate_form ( after_sign) ;
192229 let after_zero = parse_zero ( after_alternate_form) ;
@@ -196,6 +233,7 @@ fn parse_format_spec(text: &str) -> FormatSpec {
196233 let ( format_type, _) = parse_format_type ( after_precision) ;
197234
198235 FormatSpec {
236+ preconversor,
199237 fill,
200238 align,
201239 sign,
@@ -473,10 +511,11 @@ impl FormatString {
473511 let arg_part = parts[ 0 ] ;
474512
475513 let preconversor_spec = if parts. len ( ) > 1 {
476- parts [ 1 ] . to_string ( )
514+ "!" . to_string ( ) + parts [ 1 ]
477515 } else {
478516 String :: new ( )
479517 } ;
518+ let format_spec = preconversor_spec + & format_spec;
480519
481520 if arg_part. is_empty ( ) {
482521 return Ok ( FormatPart :: AutoSpec ( format_spec) ) ;
0 commit comments