@@ -662,10 +662,12 @@ mod test {
662662 use std:: str:: FromStr ;
663663
664664 use crate :: format:: {
665- ExtendedBigDecimal ,
666- num_format:: { Case , ForceDecimal } ,
665+ ExtendedBigDecimal , Format ,
666+ num_format:: { Case , Float , ForceDecimal , UnsignedInt } ,
667667 } ;
668668
669+ use super :: { Formatter , SignedInt } ;
670+
669671 #[ test]
670672 fn unsigned_octal ( ) {
671673 use super :: { Formatter , NumberAlignment , Prefix , UnsignedInt , UnsignedIntVariant } ;
@@ -1025,4 +1027,166 @@ mod test {
10251027 assert_eq ! ( f( 0.00001 ) , "1e-05" ) ;
10261028 assert_eq ! ( f( 0.000001 ) , "1e-06" ) ;
10271029 }
1030+
1031+ // Wrapper function to get a string out of Format.fmt()
1032+ fn fmt < U , T > ( format : & Format < U , T > , n : T ) -> String
1033+ where
1034+ U : Formatter < T > ,
1035+ {
1036+ let mut v = Vec :: < u8 > :: new ( ) ;
1037+ format. fmt ( & mut v, n as T ) . unwrap ( ) ;
1038+ String :: from_utf8_lossy ( & v) . to_string ( )
1039+ }
1040+
1041+ // Some end-to-end tests, `printf` will also test some of those but it's easier to add more
1042+ // tests here. We mostly focus on padding, negative numbers, and format specifiers that are not
1043+ // covered above.
1044+ #[ test]
1045+ fn format_signed_int ( ) {
1046+ let format = Format :: < SignedInt , i64 > :: parse ( "%d" ) . unwrap ( ) ;
1047+ assert_eq ! ( fmt( & format, 123i64 ) , "123" ) ;
1048+ assert_eq ! ( fmt( & format, -123i64 ) , "-123" ) ;
1049+
1050+ let format = Format :: < SignedInt , i64 > :: parse ( "%i" ) . unwrap ( ) ;
1051+ assert_eq ! ( fmt( & format, 123i64 ) , "123" ) ;
1052+ assert_eq ! ( fmt( & format, -123i64 ) , "-123" ) ;
1053+
1054+ let format = Format :: < SignedInt , i64 > :: parse ( "%6d" ) . unwrap ( ) ;
1055+ assert_eq ! ( fmt( & format, 123i64 ) , " 123" ) ;
1056+ assert_eq ! ( fmt( & format, -123i64 ) , " -123" ) ;
1057+
1058+ let format = Format :: < SignedInt , i64 > :: parse ( "%06d" ) . unwrap ( ) ;
1059+ assert_eq ! ( fmt( & format, 123i64 ) , "000123" ) ;
1060+ assert_eq ! ( fmt( & format, -123i64 ) , "-00123" ) ;
1061+
1062+ let format = Format :: < SignedInt , i64 > :: parse ( "%+6d" ) . unwrap ( ) ;
1063+ assert_eq ! ( fmt( & format, 123i64 ) , " +123" ) ;
1064+ assert_eq ! ( fmt( & format, -123i64 ) , " -123" ) ;
1065+
1066+ let format = Format :: < SignedInt , i64 > :: parse ( "% d" ) . unwrap ( ) ;
1067+ assert_eq ! ( fmt( & format, 123i64 ) , " 123" ) ;
1068+ assert_eq ! ( fmt( & format, -123i64 ) , "-123" ) ;
1069+ }
1070+
1071+ #[ test]
1072+ #[ ignore = "Need issue #7509 to be fixed" ]
1073+ fn format_signed_int_precision_zero ( ) {
1074+ let format = Format :: < SignedInt , i64 > :: parse ( "%.0d" ) . unwrap ( ) ;
1075+ assert_eq ! ( fmt( & format, 123i64 ) , "123" ) ;
1076+ // From cppreference.com: "If both the converted value and the precision are 0 the conversion results in no characters."
1077+ assert_eq ! ( fmt( & format, 0i64 ) , "" ) ;
1078+ }
1079+
1080+ #[ test]
1081+ fn format_unsigned_int ( ) {
1082+ let f = |fmt_str : & str , n : u64 | {
1083+ let format = Format :: < UnsignedInt , u64 > :: parse ( fmt_str) . unwrap ( ) ;
1084+ fmt ( & format, n)
1085+ } ;
1086+
1087+ assert_eq ! ( f( "%u" , 123u64 ) , "123" ) ;
1088+ assert_eq ! ( f( "%o" , 123u64 ) , "173" ) ;
1089+ assert_eq ! ( f( "%#o" , 123u64 ) , "0173" ) ;
1090+ assert_eq ! ( f( "%6x" , 123u64 ) , " 7b" ) ;
1091+ assert_eq ! ( f( "%#6x" , 123u64 ) , " 0x7b" ) ;
1092+ assert_eq ! ( f( "%06X" , 123u64 ) , "00007B" ) ;
1093+ assert_eq ! ( f( "%+6u" , 123u64 ) , " 123" ) ; // '+' is ignored for unsigned numbers.
1094+ assert_eq ! ( f( "% u" , 123u64 ) , "123" ) ; // ' ' is ignored for unsigned numbers.
1095+ assert_eq ! ( f( "%#x" , 0 ) , "0" ) ; // No prefix for 0
1096+ }
1097+
1098+ #[ test]
1099+ #[ ignore = "Need issues #7509 and #7510 to be fixed" ]
1100+ fn format_unsigned_int_broken ( ) {
1101+ // TODO: Merge this back into format_unsigned_int.
1102+ let f = |fmt_str : & str , n : u64 | {
1103+ let format = Format :: < UnsignedInt , u64 > :: parse ( fmt_str) . unwrap ( ) ;
1104+ fmt ( & format, n)
1105+ } ;
1106+
1107+ // #7509
1108+ assert_eq ! ( f( "%.0o" , 0 ) , "" ) ;
1109+ assert_eq ! ( f( "%#0o" , 0 ) , "0" ) ; // Already correct, but probably an accident.
1110+ assert_eq ! ( f( "%.0x" , 0 ) , "" ) ;
1111+ // #7510
1112+ assert_eq ! ( f( "%#06x" , 123u64 ) , "0x007b" ) ;
1113+ }
1114+
1115+ #[ test]
1116+ fn format_float_decimal ( ) {
1117+ let format = Format :: < Float , & ExtendedBigDecimal > :: parse ( "%f" ) . unwrap ( ) ;
1118+ assert_eq ! ( fmt( & format, & 123.0 . into( ) ) , "123.000000" ) ;
1119+ assert_eq ! ( fmt( & format, & ( -123.0 ) . into( ) ) , "-123.000000" ) ;
1120+ assert_eq ! ( fmt( & format, & 123.15e-8 . into( ) ) , "0.000001" ) ;
1121+ assert_eq ! ( fmt( & format, & ( -123.15e8 ) . into( ) ) , "-12315000000.000000" ) ;
1122+ let zero_exp = |exp| ExtendedBigDecimal :: BigDecimal ( BigDecimal :: from_bigint ( 0 . into ( ) , exp) ) ;
1123+ // We've had issues with "0e10"/"0e-10" formatting, and our current workaround is in Format.fmt function.
1124+ assert_eq ! ( fmt( & format, & zero_exp( 0 ) ) , "0.000000" ) ;
1125+ assert_eq ! ( fmt( & format, & zero_exp( 10 ) ) , "0.000000" ) ;
1126+ assert_eq ! ( fmt( & format, & zero_exp( -10 ) ) , "0.000000" ) ;
1127+
1128+ let format = Format :: < Float , & ExtendedBigDecimal > :: parse ( "%12f" ) . unwrap ( ) ;
1129+ assert_eq ! ( fmt( & format, & 123.0 . into( ) ) , " 123.000000" ) ;
1130+ assert_eq ! ( fmt( & format, & ( -123.0 ) . into( ) ) , " -123.000000" ) ;
1131+ assert_eq ! ( fmt( & format, & 123.15e-8 . into( ) ) , " 0.000001" ) ;
1132+ assert_eq ! ( fmt( & format, & ( -123.15e8 ) . into( ) ) , "-12315000000.000000" ) ;
1133+ assert_eq ! (
1134+ fmt( & format, & ( ExtendedBigDecimal :: Infinity ) ) ,
1135+ " inf"
1136+ ) ;
1137+ assert_eq ! (
1138+ fmt( & format, & ( ExtendedBigDecimal :: MinusInfinity ) ) ,
1139+ " -inf"
1140+ ) ;
1141+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: Nan ) ) , " nan" ) ;
1142+ assert_eq ! (
1143+ fmt( & format, & ( ExtendedBigDecimal :: MinusNan ) ) ,
1144+ " -nan"
1145+ ) ;
1146+
1147+ let format = Format :: < Float , & ExtendedBigDecimal > :: parse ( "%+#.0f" ) . unwrap ( ) ;
1148+ assert_eq ! ( fmt( & format, & 123.0 . into( ) ) , "+123." ) ;
1149+ assert_eq ! ( fmt( & format, & ( -123.0 ) . into( ) ) , "-123." ) ;
1150+ assert_eq ! ( fmt( & format, & 123.15e-8 . into( ) ) , "+0." ) ;
1151+ assert_eq ! ( fmt( & format, & ( -123.15e8 ) . into( ) ) , "-12315000000." ) ;
1152+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: Infinity ) ) , "+inf" ) ;
1153+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: Nan ) ) , "+nan" ) ;
1154+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: MinusZero ) ) , "-0." ) ;
1155+
1156+ let format = Format :: < Float , & ExtendedBigDecimal > :: parse ( "%#06.0f" ) . unwrap ( ) ;
1157+ assert_eq ! ( fmt( & format, & 123.0 . into( ) ) , "00123." ) ;
1158+ assert_eq ! ( fmt( & format, & ( -123.0 ) . into( ) ) , "-0123." ) ;
1159+ assert_eq ! ( fmt( & format, & 123.15e-8 . into( ) ) , "00000." ) ;
1160+ assert_eq ! ( fmt( & format, & ( -123.15e8 ) . into( ) ) , "-12315000000." ) ;
1161+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: Infinity ) ) , " inf" ) ;
1162+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: MinusInfinity ) ) , " -inf" ) ;
1163+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: Nan ) ) , " nan" ) ;
1164+ assert_eq ! ( fmt( & format, & ( ExtendedBigDecimal :: MinusNan ) ) , " -nan" ) ;
1165+ }
1166+
1167+ #[ test]
1168+ fn format_float_others ( ) {
1169+ let f = |fmt_str : & str , n : & ExtendedBigDecimal | {
1170+ let format = Format :: < Float , & ExtendedBigDecimal > :: parse ( fmt_str) . unwrap ( ) ;
1171+ fmt ( & format, n)
1172+ } ;
1173+
1174+ assert_eq ! ( f( "%e" , & ( -123.0 ) . into( ) ) , "-1.230000e+02" ) ;
1175+ assert_eq ! ( f( "%#09.e" , & ( -100.0 ) . into( ) ) , "-001.e+02" ) ;
1176+ assert_eq ! ( f( "%# 9.E" , & 100.0 . into( ) ) , " 1.E+02" ) ;
1177+ assert_eq ! ( f( "% 12.2A" , & ( -100.0 ) . into( ) ) , " -0xC.80P+3" ) ;
1178+ }
1179+
1180+ #[ test]
1181+ #[ ignore = "Need issue #7510 to be fixed" ]
1182+ fn format_float_others_broken ( ) {
1183+ // TODO: Merge this back into format_float_others.
1184+ let f = |fmt_str : & str , n : & ExtendedBigDecimal | {
1185+ let format = Format :: < Float , & ExtendedBigDecimal > :: parse ( fmt_str) . unwrap ( ) ;
1186+ fmt ( & format, n)
1187+ } ;
1188+
1189+ // #7510
1190+ assert_eq ! ( f( "%012.2a" , & ( -100.0 ) . into( ) ) , "-0x00c.80p+3" ) ;
1191+ }
10281192}
0 commit comments