@@ -56,7 +56,7 @@ pub(crate) enum ExprType {
56
56
57
57
pub ( crate ) fn lit_ends_in_dot ( lit : & Lit , context : & RewriteContext < ' _ > ) -> bool {
58
58
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 ( '.' ) ,
60
60
_ => false ,
61
61
}
62
62
}
@@ -1353,7 +1353,7 @@ fn rewrite_int_lit(
1353
1353
. max_width_error ( shape. width , span)
1354
1354
}
1355
1355
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 {
1357
1357
let symbol = token_lit. symbol . as_str ( ) ;
1358
1358
let suffix = token_lit. suffix . as_ref ( ) . map ( |s| s. as_str ( ) ) ;
1359
1359
@@ -1364,14 +1364,15 @@ fn do_rewrite_float_lit(context: &RewriteContext<'_>, token_lit: token::Lit) ->
1364
1364
return format ! ( "{}{}" , symbol, suffix. unwrap_or( "" ) ) ;
1365
1365
}
1366
1366
1367
+ let float_parts = parse_float_symbol ( symbol) . unwrap ( ) ;
1367
1368
let FloatSymbolParts {
1368
1369
integer_part,
1369
1370
fractional_part,
1370
1371
exponent,
1371
- } = parse_float_symbol ( symbol ) ;
1372
+ } = float_parts ;
1372
1373
1373
1374
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 ( ) ;
1375
1376
1376
1377
let ( include_period, include_fractional_part) =
1377
1378
match context. config . float_literal_trailing_zero ( ) {
@@ -1410,7 +1411,7 @@ fn rewrite_float_lit(
1410
1411
shape : Shape ,
1411
1412
) -> RewriteResult {
1412
1413
wrap_str (
1413
- do_rewrite_float_lit ( context, token_lit) ,
1414
+ rewrite_float_lit_inner ( context, token_lit) ,
1414
1415
context. config . max_width ( ) ,
1415
1416
shape,
1416
1417
)
@@ -2342,29 +2343,40 @@ pub(crate) fn is_method_call(expr: &ast::Expr) -> bool {
2342
2343
}
2343
2344
}
2344
2345
2346
+ /// Indicates the parts of a float literal specified as a string.
2345
2347
struct 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
2346
2351
integer_part : & ' a str ,
2352
+ /// The fractional part excluding the decimal point, e.g. `456` in `123.456e789`.
2347
2353
fractional_part : Option < & ' a str > ,
2354
+ /// The exponent part including the `e` or `E`, e.g. `e789` in `123.456e789`.
2348
2355
exponent : Option < & ' a str > ,
2349
2356
}
2350
2357
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 > {
2354
2369
// This regex may accept invalid float literals (such as `1`, `_` or `2.e3`). That's ok.
2355
2370
// We only use it to parse literals whose validity has already been established.
2356
2371
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 ( ) ,
2360
2377
fractional_part : caps. get ( 2 ) . map ( |m| m. as_str ( ) ) ,
2361
2378
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
+ } )
2368
2380
}
2369
2381
2370
2382
#[ cfg( test) ]
@@ -2394,55 +2406,55 @@ mod test {
2394
2406
2395
2407
#[ test]
2396
2408
fn test_parse_float_symbol ( ) {
2397
- let parts = parse_float_symbol ( "123.456e789" ) ;
2409
+ let parts = parse_float_symbol ( "123.456e789" ) . unwrap ( ) ;
2398
2410
assert_eq ! ( parts. integer_part, "123" ) ;
2399
2411
assert_eq ! ( parts. fractional_part, Some ( "456" ) ) ;
2400
2412
assert_eq ! ( parts. exponent, Some ( "e789" ) ) ;
2401
2413
2402
- let parts = parse_float_symbol ( "123.456e+789" ) ;
2414
+ let parts = parse_float_symbol ( "123.456e+789" ) . unwrap ( ) ;
2403
2415
assert_eq ! ( parts. integer_part, "123" ) ;
2404
2416
assert_eq ! ( parts. fractional_part, Some ( "456" ) ) ;
2405
2417
assert_eq ! ( parts. exponent, Some ( "e+789" ) ) ;
2406
2418
2407
- let parts = parse_float_symbol ( "123.456e-789" ) ;
2419
+ let parts = parse_float_symbol ( "123.456e-789" ) . unwrap ( ) ;
2408
2420
assert_eq ! ( parts. integer_part, "123" ) ;
2409
2421
assert_eq ! ( parts. fractional_part, Some ( "456" ) ) ;
2410
2422
assert_eq ! ( parts. exponent, Some ( "e-789" ) ) ;
2411
2423
2412
- let parts = parse_float_symbol ( "123e789" ) ;
2424
+ let parts = parse_float_symbol ( "123e789" ) . unwrap ( ) ;
2413
2425
assert_eq ! ( parts. integer_part, "123" ) ;
2414
2426
assert_eq ! ( parts. fractional_part, None ) ;
2415
2427
assert_eq ! ( parts. exponent, Some ( "e789" ) ) ;
2416
2428
2417
- let parts = parse_float_symbol ( "123E789" ) ;
2429
+ let parts = parse_float_symbol ( "123E789" ) . unwrap ( ) ;
2418
2430
assert_eq ! ( parts. integer_part, "123" ) ;
2419
2431
assert_eq ! ( parts. fractional_part, None ) ;
2420
2432
assert_eq ! ( parts. exponent, Some ( "E789" ) ) ;
2421
2433
2422
- let parts = parse_float_symbol ( "123." ) ;
2434
+ let parts = parse_float_symbol ( "123." ) . unwrap ( ) ;
2423
2435
assert_eq ! ( parts. integer_part, "123" ) ;
2424
2436
assert_eq ! ( parts. fractional_part, None ) ;
2425
2437
assert_eq ! ( parts. exponent, None ) ;
2426
2438
}
2427
2439
2428
2440
#[ test]
2429
2441
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 ( ) ;
2431
2443
assert_eq ! ( parts. integer_part, "_123" ) ;
2432
2444
assert_eq ! ( parts. fractional_part, Some ( "_456" ) ) ;
2433
2445
assert_eq ! ( parts. exponent, Some ( "e_789" ) ) ;
2434
2446
2435
- let parts = parse_float_symbol ( "123_.456_e789_" ) ;
2447
+ let parts = parse_float_symbol ( "123_.456_e789_" ) . unwrap ( ) ;
2436
2448
assert_eq ! ( parts. integer_part, "123_" ) ;
2437
2449
assert_eq ! ( parts. fractional_part, Some ( "456_" ) ) ;
2438
2450
assert_eq ! ( parts. exponent, Some ( "e789_" ) ) ;
2439
2451
2440
- let parts = parse_float_symbol ( "1_23.4_56e7_89" ) ;
2452
+ let parts = parse_float_symbol ( "1_23.4_56e7_89" ) . unwrap ( ) ;
2441
2453
assert_eq ! ( parts. integer_part, "1_23" ) ;
2442
2454
assert_eq ! ( parts. fractional_part, Some ( "4_56" ) ) ;
2443
2455
assert_eq ! ( parts. exponent, Some ( "e7_89" ) ) ;
2444
2456
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 ( ) ;
2446
2458
assert_eq ! ( parts. integer_part, "_1_23_" ) ;
2447
2459
assert_eq ! ( parts. fractional_part, Some ( "_4_56_" ) ) ;
2448
2460
assert_eq ! ( parts. exponent, Some ( "e_7_89_" ) ) ;
0 commit comments