@@ -466,6 +466,9 @@ macro_rules! impl_from_int {
466466 $(
467467 impl From <$t> for Decimal {
468468 fn from( val: $t) -> Self {
469+ // Integer conversion is infallible - always produces valid decimal bytes.
470+ // Uses string conversion internally since the byte encoding is designed
471+ // around decimal string parsing (BCD encoding of digit pairs).
469472 Decimal :: from_str( & val. to_string( ) ) . expect( "Integer is always valid" )
470473 }
471474 }
@@ -475,6 +478,49 @@ macro_rules! impl_from_int {
475478
476479impl_from_int ! ( i8 , i16 , i32 , i64 , i128 , u8 , u16 , u32 , u64 , u128 ) ;
477480
481+ impl TryFrom < f64 > for Decimal {
482+ type Error = DecimalError ;
483+
484+ /// Converts an f64 to a Decimal.
485+ ///
486+ /// Special values are handled:
487+ /// - `f64::NAN` → `Decimal::nan()`
488+ /// - `f64::INFINITY` → `Decimal::infinity()`
489+ /// - `f64::NEG_INFINITY` → `Decimal::neg_infinity()`
490+ ///
491+ /// Note: Due to f64's limited precision (~15-17 significant digits),
492+ /// very precise decimal values may lose precision when converted from f64.
493+ /// For exact decimal representation, use `Decimal::from_str()` instead.
494+ ///
495+ /// # Example
496+ ///
497+ /// ```
498+ /// use decimal_bytes::Decimal;
499+ ///
500+ /// let d: Decimal = 123.456f64.try_into().unwrap();
501+ /// assert_eq!(d.to_string(), "123.456");
502+ ///
503+ /// let inf: Decimal = f64::INFINITY.try_into().unwrap();
504+ /// assert!(inf.is_pos_infinity());
505+ ///
506+ /// let nan: Decimal = f64::NAN.try_into().unwrap();
507+ /// assert!(nan.is_nan());
508+ /// ```
509+ fn try_from ( val : f64 ) -> Result < Self , Self :: Error > {
510+ if val. is_nan ( ) {
511+ return Ok ( Decimal :: nan ( ) ) ;
512+ }
513+ if val. is_infinite ( ) {
514+ return Ok ( if val. is_sign_positive ( ) {
515+ Decimal :: infinity ( )
516+ } else {
517+ Decimal :: neg_infinity ( )
518+ } ) ;
519+ }
520+ Decimal :: from_str ( & val. to_string ( ) )
521+ }
522+ }
523+
478524impl Default for Decimal {
479525 fn default ( ) -> Self {
480526 Decimal {
@@ -705,6 +751,29 @@ mod tests {
705751 assert_eq ! ( d. to_string( ) , "-100" ) ;
706752 }
707753
754+ #[ test]
755+ fn test_from_f64 ( ) {
756+ // Normal f64 values
757+ let d: Decimal = 123.456f64 . try_into ( ) . unwrap ( ) ;
758+ assert_eq ! ( d. to_string( ) , "123.456" ) ;
759+
760+ let d: Decimal = ( -99.5f64 ) . try_into ( ) . unwrap ( ) ;
761+ assert_eq ! ( d. to_string( ) , "-99.5" ) ;
762+
763+ let d: Decimal = 0.0f64 . try_into ( ) . unwrap ( ) ;
764+ assert ! ( d. is_zero( ) ) ;
765+
766+ // Special values
767+ let inf: Decimal = f64:: INFINITY . try_into ( ) . unwrap ( ) ;
768+ assert ! ( inf. is_pos_infinity( ) ) ;
769+
770+ let neg_inf: Decimal = f64:: NEG_INFINITY . try_into ( ) . unwrap ( ) ;
771+ assert ! ( neg_inf. is_neg_infinity( ) ) ;
772+
773+ let nan: Decimal = f64:: NAN . try_into ( ) . unwrap ( ) ;
774+ assert ! ( nan. is_nan( ) ) ;
775+ }
776+
708777 #[ test]
709778 fn test_serialization ( ) {
710779 let d = Decimal :: from_str ( "123.456" ) . unwrap ( ) ;
0 commit comments