@@ -56,7 +56,7 @@ pub(crate) enum ExprType {
5656
5757pub ( crate ) fn lit_ends_in_dot ( lit : & Lit , context : & RewriteContext < ' _ > ) -> bool {
5858 match lit. kind {
59- LitKind :: Float => do_rewrite_float_lit ( context, * lit) . ends_with ( '.' ) ,
59+ LitKind :: Float => rewrite_float_lit_inner ( context, * lit) . ends_with ( '.' ) ,
6060 _ => false ,
6161 }
6262}
@@ -1353,7 +1353,7 @@ fn rewrite_int_lit(
13531353 . max_width_error ( shape. width , span)
13541354}
13551355
1356- fn do_rewrite_float_lit ( context : & RewriteContext < ' _ > , token_lit : token:: Lit ) -> String {
1356+ fn rewrite_float_lit_inner ( context : & RewriteContext < ' _ > , token_lit : token:: Lit ) -> String {
13571357 let symbol = token_lit. symbol . as_str ( ) ;
13581358 let suffix = token_lit. suffix . as_ref ( ) . map ( |s| s. as_str ( ) ) ;
13591359
@@ -1364,14 +1364,15 @@ fn do_rewrite_float_lit(context: &RewriteContext<'_>, token_lit: token::Lit) ->
13641364 return format ! ( "{}{}" , symbol, suffix. unwrap_or( "" ) ) ;
13651365 }
13661366
1367+ let float_parts = parse_float_symbol ( symbol) . unwrap ( ) ;
13671368 let FloatSymbolParts {
13681369 integer_part,
13691370 fractional_part,
13701371 exponent,
1371- } = parse_float_symbol ( symbol ) ;
1372+ } = float_parts ;
13721373
13731374 let has_postfix = exponent. is_some ( ) || suffix. is_some ( ) ;
1374- let fractional_part_nonzero = fractional_part . map_or ( false , |s| ! is_zero_integer_literal ( s ) ) ;
1375+ let fractional_part_nonzero = !float_parts . is_fractional_part_zero ( ) ;
13751376
13761377 let ( include_period, include_fractional_part) =
13771378 match context. config . float_literal_trailing_zero ( ) {
@@ -1410,7 +1411,7 @@ fn rewrite_float_lit(
14101411 shape : Shape ,
14111412) -> RewriteResult {
14121413 wrap_str (
1413- do_rewrite_float_lit ( context, token_lit) ,
1414+ rewrite_float_lit_inner ( context, token_lit) ,
14141415 context. config . max_width ( ) ,
14151416 shape,
14161417 )
@@ -2342,29 +2343,40 @@ pub(crate) fn is_method_call(expr: &ast::Expr) -> bool {
23422343 }
23432344}
23442345
2346+ /// Indicates the parts of a float literal specified as a string.
23452347struct FloatSymbolParts < ' a > {
2348+ /// The integer part, e.g. `123` in `123.456e789`.
2349+ /// Always non-empty, because in Rust `.1` is not a valid floating-point literal:
2350+ /// <https://doc.rust-lang.org/reference/tokens.html#floating-point-literals>
23462351 integer_part : & ' a str ,
2352+ /// The fractional part excluding the decimal point, e.g. `456` in `123.456e789`.
23472353 fractional_part : Option < & ' a str > ,
2354+ /// The exponent part including the `e` or `E`, e.g. `e789` in `123.456e789`.
23482355 exponent : Option < & ' a str > ,
23492356}
23502357
2351- // Parses a float literal. The `symbol` must be a valid floating point literal without a type
2352- // suffix. Otherwise the function may panic or return wrong result.
2353- fn parse_float_symbol ( symbol : & str ) -> FloatSymbolParts < ' _ > {
2358+ impl FloatSymbolParts < ' _ > {
2359+ fn is_fractional_part_zero ( & self ) -> bool {
2360+ let zero_literal_regex = static_regex ! ( r"^[0_]+$" ) ;
2361+ self . fractional_part
2362+ . is_none_or ( |s| zero_literal_regex. is_match ( s) )
2363+ }
2364+ }
2365+
2366+ /// Parses a float literal. The `symbol` must be a valid floating point literal without a type
2367+ /// suffix. Otherwise the function may panic or return wrong result.
2368+ fn parse_float_symbol ( symbol : & str ) -> Result < FloatSymbolParts < ' _ > , & ' static str > {
23542369 // This regex may accept invalid float literals (such as `1`, `_` or `2.e3`). That's ok.
23552370 // We only use it to parse literals whose validity has already been established.
23562371 let float_literal_regex = static_regex ! ( r"^([0-9_]+)(?:\.([0-9_]+)?)?([eE][+-]?[0-9_]+)?$" ) ;
2357- let caps = float_literal_regex. captures ( symbol) . unwrap ( ) ;
2358- FloatSymbolParts {
2359- integer_part : caps. get ( 1 ) . unwrap ( ) . as_str ( ) ,
2372+ let caps = float_literal_regex
2373+ . captures ( symbol)
2374+ . ok_or ( "invalid float literal" ) ?;
2375+ Ok ( FloatSymbolParts {
2376+ integer_part : caps. get ( 1 ) . ok_or ( "missing integer part" ) ?. as_str ( ) ,
23602377 fractional_part : caps. get ( 2 ) . map ( |m| m. as_str ( ) ) ,
23612378 exponent : caps. get ( 3 ) . map ( |m| m. as_str ( ) ) ,
2362- }
2363- }
2364-
2365- fn is_zero_integer_literal ( symbol : & str ) -> bool {
2366- let zero_literal_regex = static_regex ! ( r"^[0_]+$" ) ;
2367- zero_literal_regex. is_match ( symbol)
2379+ } )
23682380}
23692381
23702382#[ cfg( test) ]
@@ -2394,55 +2406,55 @@ mod test {
23942406
23952407 #[ test]
23962408 fn test_parse_float_symbol ( ) {
2397- let parts = parse_float_symbol ( "123.456e789" ) ;
2409+ let parts = parse_float_symbol ( "123.456e789" ) . unwrap ( ) ;
23982410 assert_eq ! ( parts. integer_part, "123" ) ;
23992411 assert_eq ! ( parts. fractional_part, Some ( "456" ) ) ;
24002412 assert_eq ! ( parts. exponent, Some ( "e789" ) ) ;
24012413
2402- let parts = parse_float_symbol ( "123.456e+789" ) ;
2414+ let parts = parse_float_symbol ( "123.456e+789" ) . unwrap ( ) ;
24032415 assert_eq ! ( parts. integer_part, "123" ) ;
24042416 assert_eq ! ( parts. fractional_part, Some ( "456" ) ) ;
24052417 assert_eq ! ( parts. exponent, Some ( "e+789" ) ) ;
24062418
2407- let parts = parse_float_symbol ( "123.456e-789" ) ;
2419+ let parts = parse_float_symbol ( "123.456e-789" ) . unwrap ( ) ;
24082420 assert_eq ! ( parts. integer_part, "123" ) ;
24092421 assert_eq ! ( parts. fractional_part, Some ( "456" ) ) ;
24102422 assert_eq ! ( parts. exponent, Some ( "e-789" ) ) ;
24112423
2412- let parts = parse_float_symbol ( "123e789" ) ;
2424+ let parts = parse_float_symbol ( "123e789" ) . unwrap ( ) ;
24132425 assert_eq ! ( parts. integer_part, "123" ) ;
24142426 assert_eq ! ( parts. fractional_part, None ) ;
24152427 assert_eq ! ( parts. exponent, Some ( "e789" ) ) ;
24162428
2417- let parts = parse_float_symbol ( "123E789" ) ;
2429+ let parts = parse_float_symbol ( "123E789" ) . unwrap ( ) ;
24182430 assert_eq ! ( parts. integer_part, "123" ) ;
24192431 assert_eq ! ( parts. fractional_part, None ) ;
24202432 assert_eq ! ( parts. exponent, Some ( "E789" ) ) ;
24212433
2422- let parts = parse_float_symbol ( "123." ) ;
2434+ let parts = parse_float_symbol ( "123." ) . unwrap ( ) ;
24232435 assert_eq ! ( parts. integer_part, "123" ) ;
24242436 assert_eq ! ( parts. fractional_part, None ) ;
24252437 assert_eq ! ( parts. exponent, None ) ;
24262438 }
24272439
24282440 #[ test]
24292441 fn test_parse_float_symbol_with_underscores ( ) {
2430- let parts = parse_float_symbol ( "_123._456e_789" ) ;
2442+ let parts = parse_float_symbol ( "_123._456e_789" ) . unwrap ( ) ;
24312443 assert_eq ! ( parts. integer_part, "_123" ) ;
24322444 assert_eq ! ( parts. fractional_part, Some ( "_456" ) ) ;
24332445 assert_eq ! ( parts. exponent, Some ( "e_789" ) ) ;
24342446
2435- let parts = parse_float_symbol ( "123_.456_e789_" ) ;
2447+ let parts = parse_float_symbol ( "123_.456_e789_" ) . unwrap ( ) ;
24362448 assert_eq ! ( parts. integer_part, "123_" ) ;
24372449 assert_eq ! ( parts. fractional_part, Some ( "456_" ) ) ;
24382450 assert_eq ! ( parts. exponent, Some ( "e789_" ) ) ;
24392451
2440- let parts = parse_float_symbol ( "1_23.4_56e7_89" ) ;
2452+ let parts = parse_float_symbol ( "1_23.4_56e7_89" ) . unwrap ( ) ;
24412453 assert_eq ! ( parts. integer_part, "1_23" ) ;
24422454 assert_eq ! ( parts. fractional_part, Some ( "4_56" ) ) ;
24432455 assert_eq ! ( parts. exponent, Some ( "e7_89" ) ) ;
24442456
2445- let parts = parse_float_symbol ( "_1_23_._4_56_e_7_89_" ) ;
2457+ let parts = parse_float_symbol ( "_1_23_._4_56_e_7_89_" ) . unwrap ( ) ;
24462458 assert_eq ! ( parts. integer_part, "_1_23_" ) ;
24472459 assert_eq ! ( parts. fractional_part, Some ( "_4_56_" ) ) ;
24482460 assert_eq ! ( parts. exponent, Some ( "e_7_89_" ) ) ;
0 commit comments