@@ -1301,7 +1301,7 @@ where
13011301 neg_b = c == b'-' ;
13021302
13031303 if b. is_empty ( ) || ( neg_b && b. starts_with ( '-' ) ) {
1304- return Err ( ParseComplexError :: new ( ) ) ;
1304+ return Err ( ParseComplexError :: expr_error ( ) ) ;
13051305 }
13061306 break ;
13071307 }
@@ -1328,7 +1328,7 @@ where
13281328 im = b;
13291329 neg_im = neg_b;
13301330 } else {
1331- return Err ( ParseComplexError :: new ( ) ) ;
1331+ return Err ( ParseComplexError :: expr_error ( ) ) ;
13321332 }
13331333
13341334 // parse re
@@ -1367,7 +1367,25 @@ impl<T: Num + Clone> Num for Complex<T> {
13671367 type FromStrRadixErr = ParseComplexError < T :: FromStrRadixErr > ;
13681368
13691369 /// 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.
13701378 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+
13711389 from_str_generic ( s, |x| -> Result < T , T :: FromStrRadixErr > {
13721390 T :: from_str_radix ( x, radix)
13731391 } )
@@ -1446,15 +1464,22 @@ pub struct ParseComplexError<E> {
14461464enum ComplexErrorKind < E > {
14471465 ParseError ( E ) ,
14481466 ExprError ,
1467+ UnsupportedRadix ,
14491468}
14501469
14511470impl < E > ParseComplexError < E > {
1452- fn new ( ) -> Self {
1471+ fn expr_error ( ) -> Self {
14531472 ParseComplexError {
14541473 kind : ComplexErrorKind :: ExprError ,
14551474 }
14561475 }
14571476
1477+ fn unsupported_radix ( ) -> Self {
1478+ ParseComplexError {
1479+ kind : ComplexErrorKind :: UnsupportedRadix ,
1480+ }
1481+ }
1482+
14581483 fn from_error ( error : E ) -> Self {
14591484 ParseComplexError {
14601485 kind : ComplexErrorKind :: ParseError ( error) ,
@@ -1469,6 +1494,7 @@ impl<E: Error> Error for ParseComplexError<E> {
14691494 match self . kind {
14701495 ComplexErrorKind :: ParseError ( ref e) => e. description ( ) ,
14711496 ComplexErrorKind :: ExprError => "invalid or unsupported complex expression" ,
1497+ ComplexErrorKind :: UnsupportedRadix => "unsupported radix for conversion" ,
14721498 }
14731499 }
14741500}
@@ -1478,6 +1504,7 @@ impl<E: fmt::Display> fmt::Display for ParseComplexError<E> {
14781504 match self . kind {
14791505 ComplexErrorKind :: ParseError ( ref e) => e. fmt ( f) ,
14801506 ComplexErrorKind :: ExprError => "invalid or unsupported complex expression" . fmt ( f) ,
1507+ ComplexErrorKind :: UnsupportedRadix => "unsupported radix for conversion" . fmt ( f) ,
14811508 }
14821509 }
14831510}
@@ -1496,6 +1523,7 @@ mod test {
14961523 #![ allow( non_upper_case_globals) ]
14971524
14981525 use super :: { Complex , Complex64 } ;
1526+ use super :: { ComplexErrorKind , ParseComplexError } ;
14991527 use core:: f64;
15001528 use core:: str:: FromStr ;
15011529
@@ -2560,6 +2588,33 @@ mod test {
25602588 test ( Complex :: new ( 15.0 , 32.0 ) , "1111+100000i" , 2 ) ;
25612589 test ( Complex :: new ( -15.0 , -32.0 ) , "-F-20i" , 16 ) ;
25622590 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: Result < Complex64 , _ > = Num :: 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: Result < Complex64 , _ > = Num :: from_str_radix ( "1" , 37 ) ;
25632618 }
25642619
25652620 #[ test]
0 commit comments