@@ -697,6 +697,44 @@ impl Duration {
697
697
}
698
698
}
699
699
700
+ /// The checked version of [`from_secs_f64`].
701
+ ///
702
+ /// [`from_secs_f64`]: Duration::from_secs_f64
703
+ ///
704
+ /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
705
+ ///
706
+ /// # Examples
707
+ /// ```
708
+ /// #![feature(duration_checked_float)]
709
+ ///
710
+ /// use std::time::Duration;
711
+ ///
712
+ /// let dur = Duration::try_from_secs_f64(2.7);
713
+ /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
714
+ ///
715
+ /// let negative = Duration::try_from_secs_f64(-5.0);
716
+ /// assert!(negative.is_err());
717
+ /// ```
718
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
719
+ #[ inline]
720
+ pub const fn try_from_secs_f64 ( secs : f64 ) -> Result < Duration , FromSecsError > {
721
+ const MAX_NANOS_F64 : f64 = ( ( u64:: MAX as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f64 ;
722
+ let nanos = secs * ( NANOS_PER_SEC as f64 ) ;
723
+ if !nanos. is_finite ( ) {
724
+ Err ( FromSecsError { kind : FromSecsErrorKind :: NonFinite } )
725
+ } else if nanos >= MAX_NANOS_F64 {
726
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Overflow } )
727
+ } else if nanos < 0.0 {
728
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Underflow } )
729
+ } else {
730
+ let nanos = nanos as u128 ;
731
+ Ok ( Duration {
732
+ secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
733
+ nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
734
+ } )
735
+ }
736
+ }
737
+
700
738
/// Creates a new `Duration` from the specified number of seconds represented
701
739
/// as `f32`.
702
740
///
@@ -732,6 +770,44 @@ impl Duration {
732
770
}
733
771
}
734
772
773
+ /// The checked version of [`from_secs_f32`].
774
+ ///
775
+ /// [`from_secs_f32`]: Duration::from_secs_f32
776
+ ///
777
+ /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
778
+ ///
779
+ /// # Examples
780
+ /// ```
781
+ /// #![feature(duration_checked_float)]
782
+ ///
783
+ /// use std::time::Duration;
784
+ ///
785
+ /// let dur = Duration::try_from_secs_f32(2.7);
786
+ /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
787
+ ///
788
+ /// let negative = Duration::try_from_secs_f32(-5.0);
789
+ /// assert!(negative.is_err());
790
+ /// ```
791
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
792
+ #[ inline]
793
+ pub const fn try_from_secs_f32 ( secs : f32 ) -> Result < Duration , FromSecsError > {
794
+ const MAX_NANOS_F32 : f32 = ( ( u64:: MAX as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f32 ;
795
+ let nanos = secs * ( NANOS_PER_SEC as f32 ) ;
796
+ if !nanos. is_finite ( ) {
797
+ Err ( FromSecsError { kind : FromSecsErrorKind :: NonFinite } )
798
+ } else if nanos >= MAX_NANOS_F32 {
799
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Overflow } )
800
+ } else if nanos < 0.0 {
801
+ Err ( FromSecsError { kind : FromSecsErrorKind :: Underflow } )
802
+ } else {
803
+ let nanos = nanos as u128 ;
804
+ Ok ( Duration {
805
+ secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
806
+ nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
807
+ } )
808
+ }
809
+ }
810
+
735
811
/// Multiplies `Duration` by `f64`.
736
812
///
737
813
/// # Panics
@@ -1081,3 +1157,55 @@ impl fmt::Debug for Duration {
1081
1157
}
1082
1158
}
1083
1159
}
1160
+
1161
+ /// An error which can be returned when converting a floating-point value of seconds
1162
+ /// into a [`Duration`].
1163
+ ///
1164
+ /// This error is used as the error type for [`Duration::try_from_secs_f32`] and
1165
+ /// [`Duration::try_from_secs_f64`].
1166
+ ///
1167
+ /// # Example
1168
+ ///
1169
+ /// ```
1170
+ /// #![feature(duration_checked_float)]
1171
+ ///
1172
+ /// use std::time::Duration;
1173
+ ///
1174
+ /// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
1175
+ /// println!("Failed conversion to Duration: {}", e);
1176
+ /// }
1177
+ /// ```
1178
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
1179
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
1180
+ pub struct FromSecsError {
1181
+ kind : FromSecsErrorKind ,
1182
+ }
1183
+
1184
+ impl FromSecsError {
1185
+ const fn description ( & self ) -> & ' static str {
1186
+ match self . kind {
1187
+ FromSecsErrorKind :: NonFinite => {
1188
+ "got non-finite value when converting float to duration"
1189
+ }
1190
+ FromSecsErrorKind :: Overflow => "overflow when converting float to duration" ,
1191
+ FromSecsErrorKind :: Underflow => "underflow when converting float to duration" ,
1192
+ }
1193
+ }
1194
+ }
1195
+
1196
+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
1197
+ impl fmt:: Display for FromSecsError {
1198
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1199
+ fmt:: Display :: fmt ( self . description ( ) , f)
1200
+ }
1201
+ }
1202
+
1203
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
1204
+ enum FromSecsErrorKind {
1205
+ // Value is not a finite value (either infinity or NaN).
1206
+ NonFinite ,
1207
+ // Value is too large to store in a `Duration`.
1208
+ Overflow ,
1209
+ // Value is less than `0.0`.
1210
+ Underflow ,
1211
+ }
0 commit comments