@@ -137,6 +137,28 @@ pub enum FormatType {
137
137
Percentage ,
138
138
}
139
139
140
+ impl From < & FormatType > for char {
141
+ fn from ( from : & FormatType ) -> char {
142
+ match from {
143
+ FormatType :: String => 's' ,
144
+ FormatType :: Binary => 'b' ,
145
+ FormatType :: Character => 'c' ,
146
+ FormatType :: Decimal => 'd' ,
147
+ FormatType :: Octal => 'o' ,
148
+ FormatType :: HexLower => 'x' ,
149
+ FormatType :: HexUpper => 'X' ,
150
+ FormatType :: Number => 'n' ,
151
+ FormatType :: ExponentLower => 'e' ,
152
+ FormatType :: ExponentUpper => 'E' ,
153
+ FormatType :: GeneralFormatLower => 'g' ,
154
+ FormatType :: GeneralFormatUpper => 'G' ,
155
+ FormatType :: FixedPointLower => 'f' ,
156
+ FormatType :: FixedPointUpper => 'F' ,
157
+ FormatType :: Percentage => '%' ,
158
+ }
159
+ }
160
+ }
161
+
140
162
impl FormatParse for FormatType {
141
163
fn parse ( text : & str ) -> ( Option < Self > , & str ) {
142
164
let mut chars = text. chars ( ) ;
@@ -337,6 +359,33 @@ impl FormatSpec {
337
359
magnitude_str
338
360
}
339
361
362
+ fn validate_format ( & self , default_format_type : FormatType ) -> Result < ( ) , String > {
363
+ let format_type = self . format_type . as_ref ( ) . unwrap_or ( & default_format_type) ;
364
+ match ( & self . grouping_option , format_type) {
365
+ (
366
+ Some ( FormatGrouping :: Comma ) ,
367
+ FormatType :: String
368
+ | FormatType :: Character
369
+ | FormatType :: Binary
370
+ | FormatType :: Octal
371
+ | FormatType :: HexLower
372
+ | FormatType :: HexUpper
373
+ | FormatType :: Number ,
374
+ ) => {
375
+ let ch = char:: from ( format_type) ;
376
+ Err ( format ! ( "Cannot specify ',' with '{}'." , ch) )
377
+ }
378
+ (
379
+ Some ( FormatGrouping :: Underscore ) ,
380
+ FormatType :: String | FormatType :: Character | FormatType :: Number ,
381
+ ) => {
382
+ let ch = char:: from ( format_type) ;
383
+ Err ( format ! ( "Cannot specify '_' with '{}'." , ch) )
384
+ }
385
+ _ => Ok ( ( ) ) ,
386
+ }
387
+ }
388
+
340
389
fn get_separator_interval ( & self ) -> usize {
341
390
match self . format_type {
342
391
Some ( FormatType :: Binary ) => 4 ,
@@ -467,14 +516,15 @@ impl FormatSpec {
467
516
}
468
517
469
518
#[ inline]
470
- fn format_int_radix ( & self , magnitude : BigInt , radix : u32 ) -> Result < String , & ' static str > {
519
+ fn format_int_radix ( & self , magnitude : BigInt , radix : u32 ) -> Result < String , String > {
471
520
match self . precision {
472
- Some ( _) => Err ( "Precision not allowed in integer format specifier" ) ,
521
+ Some ( _) => Err ( "Precision not allowed in integer format specifier" . to_owned ( ) ) ,
473
522
None => Ok ( magnitude. to_str_radix ( radix) ) ,
474
523
}
475
524
}
476
525
477
- pub fn format_int ( & self , num : & BigInt ) -> Result < String , & ' static str > {
526
+ pub fn format_int ( & self , num : & BigInt ) -> Result < String , String > {
527
+ self . validate_format ( FormatType :: Decimal ) ?;
478
528
let magnitude = num. abs ( ) ;
479
529
let prefix = if self . alternate_form {
480
530
match self . format_type {
@@ -487,30 +537,34 @@ impl FormatSpec {
487
537
} else {
488
538
""
489
539
} ;
490
- let raw_magnitude_str: Result < String , & ' static str > = match self . format_type {
540
+ let raw_magnitude_str: Result < String , String > = match self . format_type {
491
541
Some ( FormatType :: Binary ) => self . format_int_radix ( magnitude, 2 ) ,
492
542
Some ( FormatType :: Decimal ) => self . format_int_radix ( magnitude, 10 ) ,
493
543
Some ( FormatType :: Octal ) => self . format_int_radix ( magnitude, 8 ) ,
494
544
Some ( FormatType :: HexLower ) => self . format_int_radix ( magnitude, 16 ) ,
495
545
Some ( FormatType :: HexUpper ) => match self . precision {
496
- Some ( _) => Err ( "Precision not allowed in integer format specifier" ) ,
546
+ Some ( _) => Err ( "Precision not allowed in integer format specifier" . to_owned ( ) ) ,
497
547
None => {
498
548
let mut result = magnitude. to_str_radix ( 16 ) ;
499
549
result. make_ascii_uppercase ( ) ;
500
550
Ok ( result)
501
551
}
502
552
} ,
503
553
Some ( FormatType :: Number ) => self . format_int_radix ( magnitude, 10 ) ,
504
- Some ( FormatType :: String ) => Err ( "Unknown format code 's' for object of type 'int'" ) ,
554
+ Some ( FormatType :: String ) => {
555
+ Err ( "Unknown format code 's' for object of type 'int'" . to_owned ( ) )
556
+ }
505
557
Some ( FormatType :: Character ) => match ( self . sign , self . alternate_form ) {
506
- ( Some ( _) , _) => Err ( "Sign not allowed with integer format specifier 'c'" ) ,
507
- ( _, true ) => {
508
- Err ( "Alternate form (#) not allowed with integer format specifier 'c'" )
558
+ ( Some ( _) , _) => {
559
+ Err ( "Sign not allowed with integer format specifier 'c'" . to_owned ( ) )
509
560
}
561
+ ( _, true ) => Err (
562
+ "Alternate form (#) not allowed with integer format specifier 'c'" . to_owned ( ) ,
563
+ ) ,
510
564
( _, _) => match num. to_u32 ( ) {
511
565
Some ( n) if n <= 0x10ffff => Ok ( std:: char:: from_u32 ( n) . unwrap ( ) . to_string ( ) ) ,
512
566
// TODO: raise OverflowError
513
- Some ( _) | None => Err ( "%c arg not in range(0x110000)" ) ,
567
+ Some ( _) | None => Err ( "%c arg not in range(0x110000)" . to_owned ( ) ) ,
514
568
} ,
515
569
} ,
516
570
Some ( FormatType :: GeneralFormatUpper )
@@ -520,8 +574,8 @@ impl FormatSpec {
520
574
| Some ( FormatType :: ExponentUpper )
521
575
| Some ( FormatType :: ExponentLower )
522
576
| Some ( FormatType :: Percentage ) => match num. to_f64 ( ) {
523
- Some ( float) => return self . format_float ( float) ,
524
- _ => Err ( "Unable to convert int to float" ) ,
577
+ Some ( float) => return self . format_float ( float) . map_err ( |msg| msg . to_owned ( ) ) ,
578
+ _ => Err ( "Unable to convert int to float" . to_owned ( ) ) ,
525
579
} ,
526
580
None => self . format_int_radix ( magnitude, 10 ) ,
527
581
} ;
@@ -537,6 +591,7 @@ impl FormatSpec {
537
591
let sign_prefix = format ! ( "{}{}" , sign_str, prefix) ;
538
592
let magnitude_str = self . add_magnitude_separators ( raw_magnitude_str?, & sign_prefix) ;
539
593
self . format_sign_and_align ( & magnitude_str, & sign_prefix, FormatAlign :: Right )
594
+ . map_err ( |msg| msg. to_owned ( ) )
540
595
}
541
596
542
597
pub fn format_string ( & self , s : & str ) -> Result < String , & ' static str > {
0 commit comments