reifydb_codec/primitive/
uint.rs1use std::ptr;
5
6use num_bigint::{BigInt, BigUint};
7use num_traits::ToPrimitive;
8use reifydb_value::{
9 reifydb_assertions,
10 value::{uint::Uint, value_type::ValueType},
11};
12
13use crate::row::{bytes::RowBuilder, shape::RowShape};
14
15const MODE_INLINE: u128 = 0x00000000000000000000000000000000;
16const MODE_MASK: u128 = 0x80000000000000000000000000000000;
17
18const INLINE_VALUE_MASK: u128 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
19
20const DYNAMIC_OFFSET_MASK: u128 = 0x0000000000000000FFFFFFFFFFFFFFFF;
21const DYNAMIC_LENGTH_MASK: u128 = 0x7FFFFFFFFFFFFFFF0000000000000000;
22
23impl RowShape {
24 pub fn set_uint(&self, row: &mut impl RowBuilder, index: usize, value: &Uint) {
25 let field = &self.fields()[index];
26 reifydb_assertions! {
27 assert!(
28 row.len() >= self.total_static_size(),
29 "row/shape size mismatch: row.len()={} < total_static_size()={}",
30 row.len(),
31 self.total_static_size()
32 );
33 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Uint);
34 }
35
36 let unsigned_value = value.0.to_biguint().unwrap_or(BigUint::from(0u32));
37
38 if let Some(u128_val) = unsigned_value.to_u128()
39 && u128_val < (1u128 << 127)
40 {
41 self.remove_dynamic_data(row, index);
42
43 let packed = MODE_INLINE | (u128_val & INLINE_VALUE_MASK);
44 unsafe {
47 ptr::write_unaligned(
48 row.as_mut_slice().as_mut_ptr().add(field.offset as usize) as *mut u128,
49 packed.to_le(),
50 );
51 }
52 self.set_valid(row, index, true);
53 return;
54 }
55
56 let bytes = unsigned_value.to_bytes_le();
57 self.replace_dynamic_data(row, index, &bytes);
58 }
59
60 pub fn get_uint(&self, row: &[u8], index: usize) -> Uint {
61 let field = &self.fields()[index];
62 reifydb_assertions! {
63 assert!(
64 row.len() >= self.total_static_size(),
65 "row/shape size mismatch: row.len()={} < total_static_size()={}",
66 row.len(),
67 self.total_static_size()
68 );
69 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Uint);
70 }
71
72 let packed = unsafe { (row.as_ptr().add(field.offset as usize) as *const u128).read_unaligned() };
75 let packed = u128::from_le(packed);
76
77 let mode = packed & MODE_MASK;
78
79 if mode == MODE_INLINE {
80 let value = packed & INLINE_VALUE_MASK;
81
82 let unsigned = BigUint::from(value);
83 Uint::from(BigInt::from(unsigned))
84 } else {
85 let offset = (packed & DYNAMIC_OFFSET_MASK) as usize;
86 let length = ((packed & DYNAMIC_LENGTH_MASK) >> 64) as usize;
87
88 let dynamic_start = self.dynamic_section_start();
89 let data_bytes = &row[dynamic_start + offset..dynamic_start + offset + length];
90
91 let unsigned = BigUint::from_bytes_le(data_bytes);
92 Uint::from(BigInt::from(unsigned))
93 }
94 }
95
96 pub fn try_get_uint(&self, row: &[u8], index: usize) -> Option<Uint> {
97 if self.is_defined(row, index) && self.fields()[index].constraint.get_type() == ValueType::Uint {
98 Some(self.get_uint(row, index))
99 } else {
100 None
101 }
102 }
103}