1
1
use crate :: serde:: encode:: { Encode , Encoded } ;
2
2
use bigdecimal:: {
3
3
num_bigint:: { BigInt , Sign } ,
4
- BigDecimal , Signed , Zero ,
4
+ BigDecimal , Signed , Zero , num_traits :: ToBytes ,
5
5
} ;
6
6
7
7
const EXPONENT_BIAS : i64 = 101 ;
@@ -30,7 +30,7 @@ impl TryFrom<f32> for Decimal32 {
30
30
}
31
31
}
32
32
33
- #[ derive( thiserror:: Error , Debug ) ]
33
+ #[ derive( thiserror:: Error , Debug , PartialEq ) ]
34
34
pub enum Decimal32ConversionError {
35
35
#[ error( "Failed to parse f32 value to Decimal32 value." ) ]
36
36
ParseDecimal32Error ( #[ from] bigdecimal:: ParseBigDecimalError ) ,
@@ -59,25 +59,8 @@ fn encode_to_bytes(value: &BigDecimal) -> Result<Vec<u8>, Decimal32ConversionErr
59
59
60
60
61
61
let ( mut coeff, mut exp) = value. as_bigint_and_exponent ( ) ;
62
- verify_coefficient_not_too_large ( & coeff) ?;
63
- verify_exponent_below_max ( & exp) ?;
64
- let sign_bit = match coeff. sign ( ) {
65
- Sign :: Minus => 0x80 ,
66
- _ => 0 ,
67
- } ;
68
-
69
- let biased_exp = ( exp + EXPONENT_BIAS ) as u8 ;
70
- let coeff_bytes = coeff. abs ( ) . to_bytes_be ( ) . 1 ;
71
-
72
- verify_coefficient_scaling ( & coeff_bytes) ?;
73
-
74
- let mut result: [ u8 ; 4 ] = [ sign_bit | biased_exp, 0 , 0 , 0 ] ;
75
- let offset = 4 - coeff_bytes. len ( ) ;
76
- for ( i, & byte) in coeff_bytes. iter ( ) . enumerate ( ) {
77
- result[ offset + i] = byte;
78
- }
79
62
80
- Ok ( result. to_vec ( ) )
63
+ Ok ( result. to_be_bytes ( ) . to_vec ( ) )
81
64
}
82
65
83
66
fn set_sign_bit ( mut result : u32 , sign : Sign ) -> Result < u32 , ConversionError > {
@@ -94,37 +77,19 @@ fn set_sign_bit(mut result: u32, sign: Sign) -> Result<u32, ConversionError> {
94
77
}
95
78
}
96
79
97
- fn verify_coefficient_not_too_large ( coeff : & BigInt ) -> Result < ( ) , ConversionError > {
98
- if coeff. abs ( ) > COEFFICIENT_MAX . into ( ) {
99
- return Err ( Decimal32ConversionError :: CoefficientTooLarge ) ;
100
- }
101
- Ok ( ( ) )
102
- }
103
-
104
- fn verify_exponent_below_max ( exp : & i64 ) -> Result < ( ) , Decimal32ConversionError > {
105
- if exp > & EXPONENT_MAX {
106
- return Err ( Decimal32ConversionError :: ExponentOverflow ) ;
107
- }
108
- Ok ( ( ) )
109
- }
110
-
111
- fn verify_no_exponent_underflow ( exp : & i64 ) -> Result < ( ) , Decimal32ConversionError > {
112
- if exp < & EXPONENT_MIN {
113
- return Err ( Decimal32ConversionError :: ExponentUnderflow ) ;
80
+ fn set_exponent_bits ( mut result : u32 , exp : i64 ) -> Result < u32 , ConversionError > {
81
+ match exp {
82
+ _ if exp < EXPONENT_MIN => Err ( Decimal32ConversionError :: ExponentUnderflow ) ,
83
+ _ if exp > EXPONENT_MAX => Err ( Decimal32ConversionError :: ExponentOverflow ) ,
84
+ x => {
85
+ Ok ( result)
86
+ }
114
87
}
115
- Ok ( ( ) )
116
88
}
117
89
118
- fn verify_coefficient_scaling ( coeff_bytes : & Vec < u8 > ) -> Result < ( ) , Decimal32ConversionError > {
119
- if coeff_bytes. len ( ) > 3 {
120
- return Err ( Decimal32ConversionError :: CoefficientScalingFailedError ) ;
121
- }
122
- Ok ( ( ) )
123
- }
124
90
125
91
#[ cfg( test) ]
126
92
mod test {
127
- use bigdecimal:: num_traits:: ToBytes ;
128
93
129
94
use super :: * ;
130
95
@@ -148,4 +113,37 @@ mod test {
148
113
fn set_sign_bit_resturns_error_on_non_zero_base_number ( ) {
149
114
assert ! ( set_sign_bit( 4 , Sign :: Minus ) . is_err( ) ) ;
150
115
}
116
+
117
+ #[ test]
118
+ fn set_exponent_bits_if_exponent_too_large_returns_err ( ) {
119
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 100 ) , Err ( Decimal32ConversionError :: ExponentOverflow ) ) ;
120
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 97 ) , Err ( Decimal32ConversionError :: ExponentOverflow ) ) ;
121
+ }
122
+
123
+ #[ test]
124
+ fn set_exponent_bits_if_exponent_too_small_returns_err ( ) {
125
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -100 ) , Err ( Decimal32ConversionError :: ExponentUnderflow ) ) ;
126
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -96 ) , Err ( Decimal32ConversionError :: ExponentUnderflow ) ) ;
127
+ }
128
+
129
+ #[ test]
130
+ fn set_exponent_bits_works ( ) {
131
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 1 ) . unwrap( ) , 0x86600000 ) ;
132
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 2 ) . unwrap( ) , 0x86700000 ) ;
133
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 8 ) . unwrap( ) , 0x86D00000 ) ;
134
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 16 ) . unwrap( ) , 0x87500000 ) ;
135
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 32 ) . unwrap( ) , 0x88500000 ) ;
136
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 64 ) . unwrap( ) , 0x8A500000 ) ;
137
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 96 ) . unwrap( ) , 0x8C500000 ) ;
138
+ assert_eq ! ( set_exponent_bits( 0x80000000 , 0 ) . unwrap( ) , 0x86500000 ) ;
139
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -1 ) . unwrap( ) , 0x86400000 ) ;
140
+ // TODO continue here
141
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -2 ) . unwrap( ) , 0x86600000 ) ;
142
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -8 ) . unwrap( ) , 0x86600000 ) ;
143
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -16 ) . unwrap( ) , 0x86600000 ) ;
144
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -32 ) . unwrap( ) , 0x86600000 ) ;
145
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -64 ) . unwrap( ) , 0x86600000 ) ;
146
+ assert_eq ! ( set_exponent_bits( 0x80000000 , -95 ) . unwrap( ) , 0x86600000 ) ;
147
+ }
148
+
151
149
}
0 commit comments