reifydb_codec/primitive/
decimal.rs1use reifydb_value::{
5 reifydb_assertions,
6 value::{decimal::Decimal, value_type::ValueType},
7};
8
9use crate::{
10 row::{bytes::RowBuilder, shape::RowShape},
11 unscaled::{decimal_unscaled, read_le, write_le},
12};
13
14impl RowShape {
15 pub fn set_decimal(&self, row: &mut impl RowBuilder, index: usize, value: &Decimal) {
16 let field = &self.fields()[index];
17 reifydb_assertions! {
18 assert!(
19 row.len() >= self.total_static_size(),
20 "row/shape size mismatch: row.len()={} < total_static_size()={}",
21 row.len(),
22 self.total_static_size()
23 );
24 }
25 let ValueType::Decimal {
26 precision,
27 scale,
28 } = *field.constraint.get_type().inner_type()
29 else {
30 panic!("set_decimal on field {:?} of type {}", field.name, field.constraint.get_type());
31 };
32 let unscaled = decimal_unscaled(value, precision, scale).unwrap_or_else(|| {
33 panic!(
34 "decimal {value} does not fit field {:?} of type {}",
35 field.name,
36 field.constraint.get_type()
37 )
38 });
39 let start = field.offset as usize;
40 write_le(unscaled, &mut row.as_mut_slice()[start..start + field.size as usize]);
41 self.set_valid(row, index, true);
42 }
43
44 pub fn get_decimal(&self, row: &[u8], index: usize) -> Decimal {
45 let field = &self.fields()[index];
46 reifydb_assertions! {
47 assert!(
48 row.len() >= self.total_static_size(),
49 "row/shape size mismatch: row.len()={} < total_static_size()={}",
50 row.len(),
51 self.total_static_size()
52 );
53 }
54 let ValueType::Decimal {
55 scale,
56 ..
57 } = *field.constraint.get_type().inner_type()
58 else {
59 panic!("get_decimal on field {:?} of type {}", field.name, field.constraint.get_type());
60 };
61 let start = field.offset as usize;
62 let unscaled = read_le(&row[start..start + field.size as usize]);
63 Decimal::from_parts(unscaled, scale.value()).expect("a stored decimal is within 76 digits")
64 }
65}