@@ -304,12 +304,22 @@ impl TryFrom<&str> for Duration {
304304 . unwrap_or ( 0 ) ;
305305 let nanos = nanos
306306 . map ( |s| {
307- let pad = "000000000" ;
308- format ! ( "{s}{}" , & pad[ s. len( ) ..] )
307+ if s. is_empty ( ) || !s. chars ( ) . all ( |c| c. is_ascii_digit ( ) ) {
308+ return Err ( DurationError :: Deserialize (
309+ format ! ( "nanos are not a number [{s}]" ) . into ( ) ,
310+ ) ) ;
311+ }
312+ let len = s. len ( ) ;
313+ let ( digits, power) = if len > 9 { ( & s[ ..9 ] , 0 ) } else { ( s, 9 - len) } ;
314+ let mut val = digits
315+ . parse :: < i32 > ( )
316+ . map_err ( |e| DurationError :: Deserialize ( e. into ( ) ) ) ?;
317+ if power > 0 {
318+ val *= 10_i32 . pow ( power as u32 )
319+ }
320+ Ok ( val)
309321 } )
310- . map ( |s| s. parse :: < i32 > ( ) )
311- . transpose ( )
312- . map_err ( |e| DurationError :: Deserialize ( e. into ( ) ) ) ?
322+ . transpose ( ) ?
313323 . unwrap_or ( 0 ) ;
314324
315325 Duration :: new ( sign * seconds, sign as i32 * nanos)
@@ -678,6 +688,8 @@ mod tests {
678688 #[ test_case( "1a.0s" ; "seconds are not a number [1a]" ) ]
679689 #[ test_case( "1.aaas" ; "nanos are not a number [aaa]" ) ]
680690 #[ test_case( "1.0as" ; "nanos are not a number [0a]" ) ]
691+ #[ test_case( "1.1234567890as" ; "nanos with trailing chars [1234567890a]" ) ]
692+ #[ test_case( "1.s" ; "empty nanos" ) ]
681693 fn parse_detect_bad_input ( input : & str ) -> Result {
682694 let got = Duration :: try_from ( input) ;
683695 assert ! ( got. is_err( ) , "{got:?}" ) ;
@@ -689,6 +701,28 @@ mod tests {
689701 Ok ( ( ) )
690702 }
691703
704+ #[ test]
705+ fn fractional_seconds_exceed_9_digits ( ) -> Result {
706+ let d = Duration :: try_from ( "1.1234567890s" ) ?;
707+ assert_eq ! ( d, Duration :: new( 1 , 123_456_789 ) ?) ;
708+
709+ let d = Duration :: try_from ( "1.123456789012s" ) ?;
710+ assert_eq ! ( d, Duration :: new( 1 , 123_456_789 ) ?) ;
711+
712+ let d: Duration = serde_json:: from_str ( r#""1.1234567890s""# ) ?;
713+ assert_eq ! ( d, Duration :: new( 1 , 123_456_789 ) ?) ;
714+
715+ let d: Duration = serde_json:: from_str ( r#""1.123456789012s""# ) ?;
716+ assert_eq ! ( d, Duration :: new( 1 , 123_456_789 ) ?) ;
717+
718+ let d = Duration :: try_from ( "-1.1234567890s" ) ?;
719+ assert_eq ! ( d, Duration :: new( -1 , -123_456_789 ) ?) ;
720+
721+ let d: Duration = serde_json:: from_str ( r#""-1.123456789012s""# ) ?;
722+ assert_eq ! ( d, Duration :: new( -1 , -123_456_789 ) ?) ;
723+ Ok ( ( ) )
724+ }
725+
692726 #[ test]
693727 fn deserialize_unexpected_input_type ( ) -> Result {
694728 let got = serde_json:: from_value :: < Duration > ( serde_json:: json!( { } ) ) ;
0 commit comments