cassandra_proto/types/
decimal.rs1use super::{to_int, to_varint};
2use crate::frame::traits::IntoBytes;
3
4#[derive(Debug, Clone, PartialEq)]
6pub struct Decimal {
7 pub unscaled: i64,
8 pub scale: u32,
9}
10
11impl Decimal {
12 pub fn new(unscaled: i64, scale: u32) -> Self {
13 Decimal { unscaled, scale }
14 }
15
16 pub fn as_plain(&self) -> f64 {
18 (self.unscaled as f64) / (10i64.pow(self.scale) as f64)
19 }
20}
21
22impl IntoBytes for Decimal {
23 fn into_cbytes(&self) -> Vec<u8> {
24 let mut bytes: Vec<u8> = vec![];
25 bytes.extend(to_int(self.scale as i32));
26 bytes.extend(to_varint(self.unscaled));
27
28 bytes
29 }
30}
31
32macro_rules! impl_from_for_decimal {
33 ($t:ty) => {
34 impl From<$t> for Decimal {
35 fn from(i: $t) -> Self {
36 Decimal {
37 unscaled: i as i64,
38 scale: 0,
39 }
40 }
41 }
42 };
43}
44
45impl_from_for_decimal!(i8);
46impl_from_for_decimal!(i16);
47impl_from_for_decimal!(i32);
48impl_from_for_decimal!(i64);
49impl_from_for_decimal!(u8);
50impl_from_for_decimal!(u16);
51
52impl From<f32> for Decimal {
53 fn from(f: f32) -> Decimal {
54 let mut scale: u32 = 0;
55
56 loop {
57 let unscaled = f * (10i64.pow(scale) as f32);
58
59 if unscaled == unscaled.trunc() {
60 return Decimal::new(unscaled as i64, scale);
61 }
62
63 scale += 1;
64 }
65 }
66}
67
68impl From<f64> for Decimal {
69 fn from(f: f64) -> Decimal {
70 let mut scale: u32 = 0;
71
72 loop {
73 let unscaled = f * (10i64.pow(scale) as f64);
74
75 if unscaled == unscaled.trunc() {
76 return Decimal::new(unscaled as i64, scale);
77 }
78
79 scale += 1;
80 }
81 }
82}
83
84#[cfg(test)]
85mod test {
86 use super::*;
87
88 #[test]
89 fn into_cbytes_test() {
90 assert_eq!(
91 Decimal::new(129, 0).into_cbytes(),
92 vec![0, 0, 0, 0, 0x00, 0x81]
93 );
94
95 assert_eq!(
96 Decimal::new(-129, 0).into_cbytes(),
97 vec![0, 0, 0, 0, 0xFF, 0x7F]
98 );
99
100 let expected: Vec<u8> = vec![0, 0, 0, 1, 0x00, 0x81];
101 assert_eq!(Decimal::new(129, 1).into_cbytes(), expected);
102
103 let expected: Vec<u8> = vec![0, 0, 0, 1, 0xFF, 0x7F];
104 assert_eq!(Decimal::new(-129, 1).into_cbytes(), expected);
105 }
106
107 #[test]
108 fn from_f32() {
109 assert_eq!(Decimal::from(12300001 as f32), Decimal::new(12300001, 0));
110 assert_eq!(Decimal::from(1230000.1 as f32), Decimal::new(12300001, 1));
111 assert_eq!(Decimal::from(0.12300001 as f32), Decimal::new(12300001, 8));
112 }
113
114 #[test]
115 fn from_f64() {
116 assert_eq!(
117 Decimal::from(1230000000000001i64 as f64),
118 Decimal::new(1230000000000001i64, 0)
119 );
120 assert_eq!(
121 Decimal::from(123000000000000.1f64),
122 Decimal::new(1230000000000001i64, 1)
123 );
124 assert_eq!(
125 Decimal::from(0.1230000000000001f64),
126 Decimal::new(1230000000000001i64, 16)
127 );
128 }
129}