@@ -1301,7 +1301,7 @@ where
1301
1301
neg_b = c == b'-' ;
1302
1302
1303
1303
if b. is_empty ( ) || ( neg_b && b. starts_with ( '-' ) ) {
1304
- return Err ( ParseComplexError :: new ( ) ) ;
1304
+ return Err ( ParseComplexError :: expr_error ( ) ) ;
1305
1305
}
1306
1306
break ;
1307
1307
}
@@ -1328,7 +1328,7 @@ where
1328
1328
im = b;
1329
1329
neg_im = neg_b;
1330
1330
} else {
1331
- return Err ( ParseComplexError :: new ( ) ) ;
1331
+ return Err ( ParseComplexError :: expr_error ( ) ) ;
1332
1332
}
1333
1333
1334
1334
// parse re
@@ -1367,7 +1367,25 @@ impl<T: Num + Clone> Num for Complex<T> {
1367
1367
type FromStrRadixErr = ParseComplexError < T :: FromStrRadixErr > ;
1368
1368
1369
1369
/// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T`
1370
+ ///
1371
+ /// `radix` must be <= 18; larger radix would include *i* and *j* as digits,
1372
+ /// which cannot be supported.
1373
+ ///
1374
+ /// The conversion returns an error if 18 <= radix <= 36; it panics if radix > 36.
1375
+ ///
1376
+ /// The elements of `T` are parsed using `Num::from_str_radix` too, and errors
1377
+ /// (or panics) from that are reflected here as well.
1370
1378
fn from_str_radix ( s : & str , radix : u32 ) -> Result < Self , Self :: FromStrRadixErr > {
1379
+ assert ! (
1380
+ radix <= 36 ,
1381
+ "from_str_radix: radix is too high (maximum 36)"
1382
+ ) ;
1383
+
1384
+ // larger radix would include 'i' and 'j' as digits, which cannot be supported
1385
+ if radix > 18 {
1386
+ return Err ( ParseComplexError :: unsupported_radix ( ) ) ;
1387
+ }
1388
+
1371
1389
from_str_generic ( s, |x| -> Result < T , T :: FromStrRadixErr > {
1372
1390
T :: from_str_radix ( x, radix)
1373
1391
} )
@@ -1446,15 +1464,22 @@ pub struct ParseComplexError<E> {
1446
1464
enum ComplexErrorKind < E > {
1447
1465
ParseError ( E ) ,
1448
1466
ExprError ,
1467
+ UnsupportedRadix ,
1449
1468
}
1450
1469
1451
1470
impl < E > ParseComplexError < E > {
1452
- fn new ( ) -> Self {
1471
+ fn expr_error ( ) -> Self {
1453
1472
ParseComplexError {
1454
1473
kind : ComplexErrorKind :: ExprError ,
1455
1474
}
1456
1475
}
1457
1476
1477
+ fn unsupported_radix ( ) -> Self {
1478
+ ParseComplexError {
1479
+ kind : ComplexErrorKind :: UnsupportedRadix ,
1480
+ }
1481
+ }
1482
+
1458
1483
fn from_error ( error : E ) -> Self {
1459
1484
ParseComplexError {
1460
1485
kind : ComplexErrorKind :: ParseError ( error) ,
@@ -1469,6 +1494,7 @@ impl<E: Error> Error for ParseComplexError<E> {
1469
1494
match self . kind {
1470
1495
ComplexErrorKind :: ParseError ( ref e) => e. description ( ) ,
1471
1496
ComplexErrorKind :: ExprError => "invalid or unsupported complex expression" ,
1497
+ ComplexErrorKind :: UnsupportedRadix => "unsupported radix for conversion" ,
1472
1498
}
1473
1499
}
1474
1500
}
@@ -1478,6 +1504,7 @@ impl<E: fmt::Display> fmt::Display for ParseComplexError<E> {
1478
1504
match self . kind {
1479
1505
ComplexErrorKind :: ParseError ( ref e) => e. fmt ( f) ,
1480
1506
ComplexErrorKind :: ExprError => "invalid or unsupported complex expression" . fmt ( f) ,
1507
+ ComplexErrorKind :: UnsupportedRadix => "unsupported radix for conversion" . fmt ( f) ,
1481
1508
}
1482
1509
}
1483
1510
}
@@ -1496,6 +1523,7 @@ mod test {
1496
1523
#![ allow( non_upper_case_globals) ]
1497
1524
1498
1525
use super :: { Complex , Complex64 } ;
1526
+ use super :: { ComplexErrorKind , ParseComplexError } ;
1499
1527
use core:: f64;
1500
1528
use core:: str:: FromStr ;
1501
1529
@@ -2560,6 +2588,33 @@ mod test {
2560
2588
test ( Complex :: new ( 15.0 , 32.0 ) , "1111+100000i" , 2 ) ;
2561
2589
test ( Complex :: new ( -15.0 , -32.0 ) , "-F-20i" , 16 ) ;
2562
2590
test ( Complex :: new ( -15.0 , -32.0 ) , "-1111-100000i" , 2 ) ;
2591
+
2592
+ fn test_error ( s : & str , radix : u32 ) -> ParseComplexError < <f64 as Num >:: FromStrRadixErr > {
2593
+ let res = Complex64 :: from_str_radix ( s, radix) ;
2594
+
2595
+ res. expect_err ( & format ! ( "Expected failure on input {:?}" , s) )
2596
+ }
2597
+
2598
+ let err = test_error ( "1ii" , 19 ) ;
2599
+ if let ComplexErrorKind :: UnsupportedRadix = err. kind {
2600
+ /* pass */
2601
+ } else {
2602
+ panic ! ( "Expected failure on invalid radix, got {:?}" , err) ;
2603
+ }
2604
+
2605
+ let err = test_error ( "1 + 0" , 16 ) ;
2606
+ if let ComplexErrorKind :: ExprError = err. kind {
2607
+ /* pass */
2608
+ } else {
2609
+ panic ! ( "Expected failure on expr error, got {:?}" , err) ;
2610
+ }
2611
+ }
2612
+
2613
+ #[ test]
2614
+ #[ should_panic( expected = "radix is too high" ) ]
2615
+ fn test_from_str_radix_fail ( ) {
2616
+ // ensure we preserve the underlying panic on radix > 36
2617
+ let _complex = Complex64 :: from_str_radix ( "1" , 37 ) ;
2563
2618
}
2564
2619
2565
2620
#[ test]
0 commit comments