use std::ptr;
use reifydb_value::{
reifydb_assertions,
value::{constraint::Constraint, dictionary::DictionaryEntryId, value_type::ValueType},
};
use crate::row::{bytes::RowBuilder, shape::RowShape};
impl RowShape {
pub fn set_dictionary_id(&self, row: &mut impl RowBuilder, index: usize, entry: &DictionaryEntryId) {
let field = &self.fields()[index];
reifydb_assertions! {
assert!(
row.len() >= self.total_static_size(),
"row/shape size mismatch: row.len()={} < total_static_size()={}",
row.len(),
self.total_static_size()
);
assert_eq!(*field.constraint.get_type().inner_type(), ValueType::DictionaryId);
}
let id_type = match field.constraint.constraint() {
Some(Constraint::Dictionary(_, id_type)) => id_type.clone(),
_ => ValueType::Uint4,
};
let raw = entry.to_u128();
self.set_valid(row, index, true);
let written = unsafe {
let ptr = row.as_mut_slice().as_mut_ptr().add(field.offset as usize);
match id_type {
ValueType::Uint1 => u8::try_from(raw).map(|v| ptr.write_unaligned(v)),
ValueType::Uint2 => {
u16::try_from(raw).map(|v| ptr::write_unaligned(ptr as *mut u16, v))
}
ValueType::Uint8 => {
u64::try_from(raw).map(|v| ptr::write_unaligned(ptr as *mut u64, v))
}
ValueType::Uint16 => {
ptr::write_unaligned(ptr as *mut u128, raw);
Ok(())
}
_ => u32::try_from(raw).map(|v| ptr::write_unaligned(ptr as *mut u32, v)),
}
};
if written.is_err() {
panic!("dictionary id {raw} does not fit the {id_type} id slot of field {index}");
}
}
pub fn get_dictionary_id(&self, row: &[u8], index: usize) -> DictionaryEntryId {
let field = &self.fields()[index];
reifydb_assertions! {
assert!(
row.len() >= self.total_static_size(),
"row/shape size mismatch: row.len()={} < total_static_size()={}",
row.len(),
self.total_static_size()
);
assert_eq!(*field.constraint.get_type().inner_type(), ValueType::DictionaryId);
}
let id_type = match field.constraint.constraint() {
Some(Constraint::Dictionary(_, id_type)) => id_type.clone(),
_ => ValueType::Uint4,
};
unsafe {
let ptr = row.as_ptr().add(field.offset as usize);
let raw: u128 = match id_type {
ValueType::Uint1 => ptr.read_unaligned() as u128,
ValueType::Uint2 => (ptr as *const u16).read_unaligned() as u128,
ValueType::Uint4 => (ptr as *const u32).read_unaligned() as u128,
ValueType::Uint8 => (ptr as *const u64).read_unaligned() as u128,
ValueType::Uint16 => (ptr as *const u128).read_unaligned(),
_ => (ptr as *const u32).read_unaligned() as u128,
};
DictionaryEntryId::from_u128(raw, id_type).unwrap()
}
}
pub fn try_get_dictionary_id(&self, row: &[u8], index: usize) -> Option<DictionaryEntryId> {
if self.is_defined(row, index) && self.fields()[index].constraint.get_type() == ValueType::DictionaryId
{
Some(self.get_dictionary_id(row, index))
} else {
None
}
}
}