Skip to content

Commit 93aab46

Browse files
implemented encode and decode for decimal64
1 parent 1406316 commit 93aab46

File tree

2 files changed

+93
-88
lines changed

2 files changed

+93
-88
lines changed

amqp-type/src/fixed_width/decimal32.rs

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl Encode for Decimal32 {
1515
fn encode(&self) -> Encoded {
1616
Encoded::new_fixed(
1717
DEFAULT_CONSTR,
18-
encode_to_bytes(&self.0).to_be_bytes().to_vec(),
18+
self.0.to_be_bytes().to_vec(),
1919
)
2020
}
2121
}
@@ -68,10 +68,6 @@ impl From<f32> for Decimal32 {
6868
}
6969
}
7070

71-
fn encode_to_bytes(value: &f32) -> u32 {
72-
value.to_bits()
73-
}
74-
7571
#[cfg(test)]
7672
mod test {
7773
use bytes::BufMut;
@@ -83,76 +79,6 @@ mod test {
8379
assert_eq!(val.encode().constructor(), 0x74);
8480
}
8581

86-
#[test]
87-
fn test_positive_number() {
88-
let decimal = 0.15625;
89-
let encoded = encode_to_bytes(&decimal);
90-
let expected = 0b00111110001000000000000000000000;
91-
assert_eq!(encoded, expected);
92-
}
93-
94-
#[test]
95-
fn test_negative_number() {
96-
let decimal = -0.15625;
97-
let encoded = encode_to_bytes(&decimal);
98-
let expected = 0b10111110001000000000000000000000;
99-
assert_eq!(encoded, expected);
100-
}
101-
102-
#[test]
103-
fn test_large_number() {
104-
let decimal = f32::MAX; // Max value for f32
105-
let encoded = encode_to_bytes(&decimal);
106-
assert_eq!(encoded, decimal.to_bits());
107-
}
108-
109-
#[test]
110-
fn test_small_number() {
111-
let decimal = f32::MIN; // Max value for f32
112-
let encoded = encode_to_bytes(&decimal);
113-
assert_eq!(encoded, decimal.to_bits());
114-
}
115-
116-
#[test]
117-
fn test_small_subnormal_number() {
118-
let decimal = 1E-45; // Smallest subnormal in f32
119-
let encoded = encode_to_bytes(&decimal);
120-
let expected = 0b00000000000000000000000000000001;
121-
assert_eq!(encoded, expected);
122-
}
123-
124-
#[test]
125-
fn test_zero() {
126-
let decimal = 0f32;
127-
let encoded = encode_to_bytes(&decimal);
128-
let expected = 0b00000000000000000000000000000000;
129-
assert_eq!(encoded, expected);
130-
}
131-
132-
#[test]
133-
fn test_one() {
134-
let decimal = 1f32;
135-
let encoded = encode_to_bytes(&decimal);
136-
let expected = 0b00111111100000000000000000000000;
137-
assert_eq!(encoded, expected);
138-
}
139-
140-
#[test]
141-
fn test_infinity() {
142-
let decimal = f32::INFINITY; // A number too large for f32, should be infinity
143-
let encoded = encode_to_bytes(&decimal);
144-
let expected = 0b01111111100000000000000000000000; // Positive infinity in f32
145-
assert_eq!(encoded, expected);
146-
}
147-
148-
#[test]
149-
fn test_negative_infinity() {
150-
let decimal = f32::NEG_INFINITY; // A negative number too large for f32
151-
let encoded = encode_to_bytes(&decimal);
152-
let expected = 0b11111111100000000000000000000000; // Negative infinity in f32
153-
assert_eq!(encoded, expected);
154-
}
155-
15682
#[test]
15783
fn test_successful_deserialization() {
15884
let value = 1.2345f32;
Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,118 @@
1-
use bigdecimal::BigDecimal;
1+
use std::hash::{Hash, Hasher};
22

3+
use crate::error::AppError;
4+
use crate::serde::decode::Decode;
35
use crate::serde::encode::{Encode, Encoded};
6+
use crate::verify::verify_bytes_read_eq;
47

5-
#[derive(Hash, Eq, PartialEq)]
6-
pub struct Decimal64(BigDecimal);
8+
const DEFAULT_CONSTR: u8 = 0x84;
9+
10+
pub struct Decimal64(f64);
711

812
impl Encode for Decimal64 {
913
fn encode(&self) -> Encoded {
10-
0x84.into()
14+
Encoded::new_fixed(
15+
DEFAULT_CONSTR,
16+
self.0.to_be_bytes().to_vec()
17+
)
18+
}
19+
}
20+
21+
impl Decode for Decimal64 {
22+
fn can_decode(iter: impl Iterator<Item=u8>) -> bool {
23+
match iter.peekable().peek() {
24+
Some(&DEFAULT_CONSTR) => true,
25+
_ => false,
26+
}
27+
}
28+
29+
fn try_decode(mut iter: impl Iterator<Item=u8>) -> Result<Self, AppError> where Self: Sized {
30+
match iter.next() {
31+
Some(DEFAULT_CONSTR) => Ok(parse_decimal64(iter)?),
32+
Some(c) => Err(AppError::DeserializationIllegalConstructorError(c)),
33+
None => Err(AppError::IteratorEmptyOrTooShortError),
34+
}
35+
}
36+
}
37+
38+
fn parse_decimal64(iter: impl Iterator<Item=u8>) -> Result<Decimal64, AppError> {
39+
let mut byte_vals = [0; 8];
40+
let mut index = 0;
41+
for b in iter.take(8) {
42+
byte_vals[index] = b;
43+
index += 1;
1144
}
45+
verify_bytes_read_eq(index, 8)?;
46+
Ok(Decimal64(f64::from_be_bytes(byte_vals)))
1247
}
1348

1449
impl From<f64> for Decimal64 {
1550
fn from(value: f64) -> Self {
16-
Decimal64(BigDecimal::try_from(value).unwrap())
51+
Decimal64(value)
1752
}
1853
}
1954

20-
#[derive(thiserror::Error, Debug)]
21-
pub enum Decimal64ConversionError {
22-
#[error("Coefficient is too large for Decimal64 representation.")]
23-
CoefficientTooLarge,
24-
#[error("Exponent overflowed in Decimal64 representation")]
25-
ExponentOverflow,
26-
#[error("Exponent underflowed in Decimal64 representation")]
27-
ExponentUnderflow,
55+
impl PartialEq for Decimal64 {
56+
fn eq(&self, other: &Self) -> bool {
57+
self.0.to_bits().eq(&other.0.to_bits())
58+
}
59+
}
60+
61+
impl Eq for Decimal64 {}
62+
63+
impl Hash for Decimal64 {
64+
fn hash<H: Hasher>(&self, state: &mut H) {
65+
self.0.to_bits().hash(state)
66+
}
2867
}
2968

3069
#[cfg(test)]
3170
mod test {
71+
use bytes::BufMut;
72+
3273
use super::*;
3374

3475
#[test]
3576
fn construct_decimal_64() {
3677
let val: Decimal64 = 64.0.into();
3778
assert_eq!(val.encode().constructor(), 0x84);
3879
}
80+
81+
#[test]
82+
fn test_successful_deserialization() {
83+
let value = 1.2345f64;
84+
let mut data = vec![DEFAULT_CONSTR];
85+
data.put_f64(value); // Put an f64 into the buffer
86+
let mut iter = data.into_iter();
87+
88+
match Decimal64::try_decode(&mut iter) {
89+
Ok(decimal) => assert_eq!(value, decimal.0),
90+
Err(e) => panic!("Unexpected error: {:?}", e),
91+
}
92+
}
93+
94+
#[test]
95+
fn test_illegal_constructor_deserialization() {
96+
let illegal_constructor = 0xFF; // Assuming this is not DEFAULT_CONSTR
97+
let bytes = vec![illegal_constructor, /* other bytes */];
98+
let mut iter = bytes.into_iter();
99+
100+
match Decimal64::try_decode(&mut iter) {
101+
Ok(_) => panic!("Expected an error, but deserialization succeeded"),
102+
Err(AppError::DeserializationIllegalConstructorError(c)) => assert_eq!(illegal_constructor, c),
103+
Err(e) => panic!("Unexpected error type: {:?}", e),
104+
}
105+
}
106+
107+
#[test]
108+
fn test_empty_iterator_deserialization() {
109+
let bytes = vec![]; // Empty vector
110+
let mut iter = bytes.into_iter();
111+
112+
match Decimal64::try_decode(&mut iter) {
113+
Ok(_) => panic!("Expected an error, but deserialization succeeded"),
114+
Err(AppError::IteratorEmptyOrTooShortError) => (), // Expected outcome
115+
Err(e) => panic!("Unexpected error type: {:?}", e),
116+
}
117+
}
39118
}

0 commit comments

Comments
 (0)