@@ -7,7 +7,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
77use std:: str:: FromStr ;
88use thiserror:: Error ;
99
10- use crate :: errors:: StdError ;
10+ use crate :: errors:: { CheckedMultiplyRatioError , StdError } ;
1111use crate :: { OverflowError , Uint512 } ;
1212
1313use super :: Fraction ;
@@ -130,16 +130,30 @@ impl Decimal256 {
130130
131131 /// Returns the ratio (numerator / denominator) as a Decimal256
132132 pub fn from_ratio ( numerator : impl Into < Uint256 > , denominator : impl Into < Uint256 > ) -> Self {
133+ match Decimal256 :: checked_from_ratio ( numerator, denominator) {
134+ Ok ( value) => value,
135+ Err ( CheckedMultiplyRatioError :: DivideByZero ) => {
136+ panic ! ( "Denominator must not be zero" )
137+ }
138+ Err ( CheckedMultiplyRatioError :: Overflow ) => panic ! ( "Multiplication overflow" ) ,
139+ }
140+ }
141+
142+ /// Returns the ratio (numerator / denominator) as a Decimal256
143+ pub fn checked_from_ratio (
144+ numerator : impl Into < Uint256 > ,
145+ denominator : impl Into < Uint256 > ,
146+ ) -> Result < Self , CheckedMultiplyRatioError > {
133147 let numerator: Uint256 = numerator. into ( ) ;
134148 let denominator: Uint256 = denominator. into ( ) ;
135149 if denominator. is_zero ( ) {
136- panic ! ( "Denominator must not be zero" ) ;
150+ return Err ( CheckedMultiplyRatioError :: DivideByZero ) ;
137151 }
138152
139- Self (
153+ Ok ( Self (
140154 // numerator * DECIMAL_FRACTIONAL / denominator
141- numerator. multiply_ratio ( Self :: DECIMAL_FRACTIONAL , denominator) ,
142- )
155+ numerator. checked_multiply_ratio ( Self :: DECIMAL_FRACTIONAL , denominator) ? ,
156+ ) )
143157 }
144158
145159 pub const fn is_zero ( & self ) -> bool {
@@ -690,6 +704,19 @@ mod tests {
690704 Decimal256 :: from_ratio ( 1u128 , 0u128 ) ;
691705 }
692706
707+ #[ test]
708+ fn decimal256_checked_from_ratio_does_not_panic ( ) {
709+ assert_eq ! (
710+ Decimal256 :: checked_from_ratio( 1u128 , 0u128 ) ,
711+ Err ( CheckedMultiplyRatioError :: DivideByZero )
712+ ) ;
713+
714+ assert_eq ! (
715+ Decimal256 :: checked_from_ratio( Uint256 :: MAX , 1u128 ) ,
716+ Err ( CheckedMultiplyRatioError :: Overflow )
717+ ) ;
718+ }
719+
693720 #[ test]
694721 fn decimal256_implements_fraction ( ) {
695722 let fraction = Decimal256 :: from_str ( "1234.567" ) . unwrap ( ) ;
0 commit comments