Skip to main content

reifydb_codec/primitive/
int.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::ptr;
5
6use num_bigint::BigInt as StdBigInt;
7use num_traits::ToPrimitive;
8use reifydb_value::{
9	reifydb_assertions,
10	value::{int::Int, 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_int(&self, row: &mut impl RowBuilder, index: usize, value: &Int) {
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::Int);
34		}
35
36		if let Some(i128_val) = value.0.to_i128()
37			&& (-(1i128 << 126)..(1i128 << 126)).contains(&i128_val)
38		{
39			self.remove_dynamic_data(row, index);
40
41			let packed = MODE_INLINE | ((i128_val as u128) & INLINE_VALUE_MASK);
42			// SAFETY: row.len() >= total_static_size() puts the 16-byte slot at field.offset inside the
43			// uniquely-owned buffer, and write_unaligned needs no alignment.
44			unsafe {
45				ptr::write_unaligned(
46					row.as_mut_slice().as_mut_ptr().add(field.offset as usize) as *mut u128,
47					packed.to_le(),
48				);
49			}
50			self.set_valid(row, index, true);
51			return;
52		}
53
54		let bytes = value.0.to_signed_bytes_le();
55		self.replace_dynamic_data(row, index, &bytes);
56	}
57
58	pub fn get_int(&self, row: &[u8], index: usize) -> Int {
59		let field = &self.fields()[index];
60		reifydb_assertions! {
61			assert!(
62				row.len() >= self.total_static_size(),
63				"row/shape size mismatch: row.len()={} < total_static_size()={}",
64				row.len(),
65				self.total_static_size()
66			);
67			assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Int);
68		}
69
70		// SAFETY: row.len() >= total_static_size() puts the 16-byte slot at field.offset inside the row,
71		// read_unaligned needs no alignment, and u128 has no invalid bit patterns.
72		let packed = unsafe { (row.as_ptr().add(field.offset as usize) as *const u128).read_unaligned() };
73		let packed = u128::from_le(packed);
74
75		let mode = packed & MODE_MASK;
76
77		if mode == MODE_INLINE {
78			let value = (packed & INLINE_VALUE_MASK) as i128;
79			let signed = if value & (1i128 << 126) != 0 {
80				value | (1i128 << 127)
81			} else {
82				value
83			};
84			Int::from(signed)
85		} else {
86			let offset = (packed & DYNAMIC_OFFSET_MASK) as usize;
87			let length = ((packed & DYNAMIC_LENGTH_MASK) >> 64) as usize;
88
89			let dynamic_start = self.dynamic_section_start();
90			let bigint_bytes = &row[dynamic_start + offset..dynamic_start + offset + length];
91
92			Int::from(StdBigInt::from_signed_bytes_le(bigint_bytes))
93		}
94	}
95
96	pub fn try_get_int(&self, row: &[u8], index: usize) -> Option<Int> {
97		if self.is_defined(row, index) && self.fields()[index].constraint.get_type() == ValueType::Int {
98			Some(self.get_int(row, index))
99		} else {
100			None
101		}
102	}
103}