@@ -687,21 +687,47 @@ impl Duration {
687
687
#[ inline]
688
688
#[ rustc_const_unstable( feature = "duration_consts_2" , issue = "72440" ) ]
689
689
pub const fn from_secs_f64 ( secs : f64 ) -> Duration {
690
+ match Duration :: try_from_secs_f64 ( secs) {
691
+ Ok ( v) => v,
692
+ Err ( e) => crate :: panicking:: panic ( e. description ( ) ) ,
693
+ }
694
+ }
695
+
696
+ /// The checked version of [`from_secs_f64`].
697
+ ///
698
+ /// [`from_secs_f64`]: Duration::from_secs_f64
699
+ ///
700
+ /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
701
+ ///
702
+ /// # Examples
703
+ /// ```
704
+ /// #![feature(duration_checked_float)]
705
+ ///
706
+ /// use std::time::Duration;
707
+ ///
708
+ /// let dur = Duration::try_from_secs_f64(2.7);
709
+ /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
710
+ ///
711
+ /// let negative = Duration::try_from_secs_f64(-5.0);
712
+ /// assert!(negative.is_err());
713
+ /// ```
714
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
715
+ #[ inline]
716
+ pub const fn try_from_secs_f64 ( secs : f64 ) -> Result < Duration , FromSecsError > {
690
717
const MAX_NANOS_F64 : f64 = ( ( u64:: MAX as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f64 ;
691
718
let nanos = secs * ( NANOS_PER_SEC as f64 ) ;
692
719
if !nanos. is_finite ( ) {
693
- panic ! ( "got non-finite value when converting float to duration" ) ;
694
- }
695
- if nanos >= MAX_NANOS_F64 {
696
- panic ! ( "overflow when converting float to duration" ) ;
697
- }
698
- if nanos < 0.0 {
699
- panic ! ( "underflow when converting float to duration" ) ;
700
- }
701
- let nanos = nanos as u128 ;
702
- Duration {
703
- secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
704
- nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
720
+ Err ( FromSecsError { kind : FromSecsErrorKind :: NonFinite } )
721
+ } else if nanos >= MAX_NANOS_F64 {
722
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Overflow } )
723
+ } else if nanos < 0.0 {
724
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Underflow } )
725
+ } else {
726
+ let nanos = nanos as u128 ;
727
+ Ok ( Duration {
728
+ secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
729
+ nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
730
+ } )
705
731
}
706
732
}
707
733
@@ -722,21 +748,47 @@ impl Duration {
722
748
#[ inline]
723
749
#[ rustc_const_unstable( feature = "duration_consts_2" , issue = "72440" ) ]
724
750
pub const fn from_secs_f32 ( secs : f32 ) -> Duration {
751
+ match Duration :: try_from_secs_f32 ( secs) {
752
+ Ok ( v) => v,
753
+ Err ( e) => crate :: panicking:: panic ( e. description ( ) ) ,
754
+ }
755
+ }
756
+
757
+ /// The checked version of [`from_secs_f32`].
758
+ ///
759
+ /// [`from_secs_f32`]: Duration::from_secs_f32
760
+ ///
761
+ /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
762
+ ///
763
+ /// # Examples
764
+ /// ```
765
+ /// #![feature(duration_checked_float)]
766
+ ///
767
+ /// use std::time::Duration;
768
+ ///
769
+ /// let dur = Duration::try_from_secs_f32(2.7);
770
+ /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
771
+ ///
772
+ /// let negative = Duration::try_from_secs_f32(-5.0);
773
+ /// assert!(negative.is_err());
774
+ /// ```
775
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
776
+ #[ inline]
777
+ pub const fn try_from_secs_f32 ( secs : f32 ) -> Result < Duration , FromSecsError > {
725
778
const MAX_NANOS_F32 : f32 = ( ( u64:: MAX as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f32 ;
726
779
let nanos = secs * ( NANOS_PER_SEC as f32 ) ;
727
780
if !nanos. is_finite ( ) {
728
- panic ! ( "got non-finite value when converting float to duration" ) ;
729
- }
730
- if nanos >= MAX_NANOS_F32 {
731
- panic ! ( "overflow when converting float to duration" ) ;
732
- }
733
- if nanos < 0.0 {
734
- panic ! ( "underflow when converting float to duration" ) ;
735
- }
736
- let nanos = nanos as u128 ;
737
- Duration {
738
- secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
739
- nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
781
+ Err ( FromSecsError { kind : FromSecsErrorKind :: NonFinite } )
782
+ } else if nanos >= MAX_NANOS_F32 {
783
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Overflow } )
784
+ } else if nanos < 0.0 {
785
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Underflow } )
786
+ } else {
787
+ let nanos = nanos as u128 ;
788
+ Ok ( Duration {
789
+ secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
790
+ nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
791
+ } )
740
792
}
741
793
}
742
794
@@ -1099,3 +1151,55 @@ impl fmt::Debug for Duration {
1099
1151
}
1100
1152
}
1101
1153
}
1154
+
1155
+ /// An error which can be returned when converting a floating-point value of seconds
1156
+ /// into a [`Duration`].
1157
+ ///
1158
+ /// This error is used as the error type for [`Duration::try_from_secs_f32`] and
1159
+ /// [`Duration::try_from_secs_f64`].
1160
+ ///
1161
+ /// # Example
1162
+ ///
1163
+ /// ```
1164
+ /// #![feature(duration_checked_float)]
1165
+ ///
1166
+ /// use std::time::Duration;
1167
+ ///
1168
+ /// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
1169
+ /// println!("Failed conversion to Duration: {}", e);
1170
+ /// }
1171
+ /// ```
1172
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
1173
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
1174
+ pub struct FromSecsError {
1175
+ kind : FromSecsErrorKind ,
1176
+ }
1177
+
1178
+ impl FromSecsError {
1179
+ const fn description ( & self ) -> & ' static str {
1180
+ match self . kind {
1181
+ FromSecsErrorKind :: NonFinite => {
1182
+ "got non-finite value when converting float to duration"
1183
+ }
1184
+ FromSecsErrorKind :: Overflow => "overflow when converting float to duration" ,
1185
+ FromSecsErrorKind :: Underflow => "underflow when converting float to duration" ,
1186
+ }
1187
+ }
1188
+ }
1189
+
1190
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
1191
+ impl fmt:: Display for FromSecsError {
1192
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1193
+ fmt:: Display :: fmt ( self . description ( ) , f)
1194
+ }
1195
+ }
1196
+
1197
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
1198
+ enum FromSecsErrorKind {
1199
+ // Value is not a finite value (either infinity or NaN).
1200
+ NonFinite ,
1201
+ // Value is too large to store in a `Duration`.
1202
+ Overflow ,
1203
+ // Value is less than `0.0`.
1204
+ Underflow ,
1205
+ }
0 commit comments