use crate::header::QvdFieldHeader;
pub fn read_field_index(record: &[u8], field: &QvdFieldHeader) -> i64 {
if field.bit_width == 0 {
return field.bias as i64;
}
let bit_offset = field.bit_offset;
let bit_width = field.bit_width;
let mut value: u64 = 0;
for bit_pos in 0..bit_width {
let abs_bit = bit_offset + bit_pos;
let byte_idx = abs_bit / 8;
let bit_idx = abs_bit % 8;
if byte_idx < record.len() && (record[byte_idx] >> bit_idx) & 1 == 1 {
value |= 1u64 << bit_pos;
}
}
value as i64 + field.bias as i64
}
pub fn read_all_row_indices(
buf: &[u8],
fields: &[QvdFieldHeader],
record_byte_size: usize,
no_of_records: usize,
) -> Vec<Vec<i64>> {
let mut columns: Vec<Vec<i64>> = fields.iter().map(|_| Vec::with_capacity(no_of_records)).collect();
for row_idx in 0..no_of_records {
let row_start = row_idx * record_byte_size;
let row_end = row_start + record_byte_size;
if row_end > buf.len() {
break;
}
let record = &buf[row_start..row_end];
for (col_idx, field) in fields.iter().enumerate() {
let index = read_field_index(record, field);
columns[col_idx].push(index);
}
}
columns
}
pub fn write_row_record(
fields: &[QvdFieldHeader],
indices: &[u64],
record_byte_size: usize,
) -> Vec<u8> {
let mut record = vec![0u8; record_byte_size];
for (field, &raw_index) in fields.iter().zip(indices.iter()) {
if field.bit_width == 0 {
continue;
}
let bit_offset = field.bit_offset;
let bit_width = field.bit_width;
for bit_pos in 0..bit_width {
if (raw_index >> bit_pos) & 1 == 1 {
let abs_bit = bit_offset + bit_pos;
let byte_idx = abs_bit / 8;
let bit_idx = abs_bit % 8;
if byte_idx < record.len() {
record[byte_idx] |= 1u8 << bit_idx;
}
}
}
}
record
}
pub fn bits_needed(n: usize) -> usize {
if n <= 1 {
return 0;
}
let max_val = n - 1;
(usize::BITS - max_val.leading_zeros()) as usize
}