|
1 |
| -use bigdecimal::BigDecimal; |
| 1 | +use std::hash::{Hash, Hasher}; |
2 | 2 |
|
| 3 | +use crate::error::AppError; |
| 4 | +use crate::serde::decode::Decode; |
3 | 5 | use crate::serde::encode::{Encode, Encoded};
|
| 6 | +use crate::verify::verify_bytes_read_eq; |
4 | 7 |
|
5 |
| -#[derive(Hash, Eq, PartialEq)] |
6 |
| -pub struct Decimal64(BigDecimal); |
| 8 | +const DEFAULT_CONSTR: u8 = 0x84; |
| 9 | + |
| 10 | +pub struct Decimal64(f64); |
7 | 11 |
|
8 | 12 | impl Encode for Decimal64 {
|
9 | 13 | 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; |
11 | 44 | }
|
| 45 | + verify_bytes_read_eq(index, 8)?; |
| 46 | + Ok(Decimal64(f64::from_be_bytes(byte_vals))) |
12 | 47 | }
|
13 | 48 |
|
14 | 49 | impl From<f64> for Decimal64 {
|
15 | 50 | fn from(value: f64) -> Self {
|
16 |
| - Decimal64(BigDecimal::try_from(value).unwrap()) |
| 51 | + Decimal64(value) |
17 | 52 | }
|
18 | 53 | }
|
19 | 54 |
|
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 | + } |
28 | 67 | }
|
29 | 68 |
|
30 | 69 | #[cfg(test)]
|
31 | 70 | mod test {
|
| 71 | + use bytes::BufMut; |
| 72 | + |
32 | 73 | use super::*;
|
33 | 74 |
|
34 | 75 | #[test]
|
35 | 76 | fn construct_decimal_64() {
|
36 | 77 | let val: Decimal64 = 64.0.into();
|
37 | 78 | assert_eq!(val.encode().constructor(), 0x84);
|
38 | 79 | }
|
| 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 | + } |
39 | 118 | }
|
0 commit comments