use std::os::raw::c_void;
use serde::Serialize;
#[derive(Debug)]
#[repr(C)]
pub struct PackedInfoFFI {
pub is_packed: bool,
pub num_packed_words: u64,
pub unpack_info: *mut u64, pub col_source: *const u8, pub col_lane: *const u8, pub index_bits: u64,
pub words_per_entry: u64,
pub lanes: u64,
}
impl PackedInfoFFI {
pub fn get_ptr(&self) -> *mut c_void {
self as *const PackedInfoFFI as *mut c_void
}
}
#[derive(Default, Debug, Clone, Serialize)]
pub struct PackedInfo {
pub is_packed: bool,
pub num_packed_words: u64,
pub unpack_info: Vec<u64>,
pub col_source: Vec<u8>,
pub col_lane: Vec<u8>,
pub index_bits: u64,
pub words_per_entry: u64,
pub lanes: u64,
}
pub const MAX_LANES: u64 = u8::MAX as u64 + 1;
impl PackedInfo {
pub fn new(is_packed: bool, num_packed_words: u64, unpack_info: Vec<u64>) -> Self {
Self { is_packed, num_packed_words, unpack_info, ..Default::default() }
}
pub fn with_indexed(
mut self,
col_source: Vec<u8>,
col_lane: Vec<u8>,
index_bits: u64,
words_per_entry: u64,
lanes: u64,
) -> Self {
assert_eq!(
col_source.len(),
col_lane.len(),
"indexed descriptor: col_source and col_lane must both cover every column"
);
assert_eq!(
col_source.len(),
self.unpack_info.len(),
"indexed descriptor: column maps must cover every unpack_info column"
);
let n_lanes = lanes.max(1);
assert!(n_lanes <= MAX_LANES, "indexed descriptor: at most {MAX_LANES} lanes (col_lane names one in a u8)");
assert!(
col_lane.iter().all(|&l| (l as u64) < n_lanes),
"indexed descriptor: every col_lane must be below lanes ({n_lanes})"
);
assert!((1..=64).contains(&index_bits), "indexed descriptor: index_bits must be in 1..=64, got {index_bits}");
assert!(
n_lanes * index_bits <= self.num_packed_words * 64,
"indexed descriptor: a {n_lanes}-lane header of {index_bits}-bit indices does not \
fit a {}-word compact row",
self.num_packed_words
);
self.col_source = col_source;
self.col_lane = col_lane;
self.index_bits = index_bits;
self.words_per_entry = words_per_entry;
self.lanes = lanes;
self
}
pub fn is_indexed(&self) -> bool {
!self.col_source.is_empty()
}
pub fn as_ffi(&self) -> PackedInfoFFI {
PackedInfoFFI {
is_packed: self.is_packed,
num_packed_words: self.num_packed_words,
unpack_info: self.unpack_info.as_ptr() as *mut u64,
col_source: if self.col_source.is_empty() { std::ptr::null() } else { self.col_source.as_ptr() },
col_lane: if self.col_lane.is_empty() { std::ptr::null() } else { self.col_lane.as_ptr() },
index_bits: self.index_bits,
words_per_entry: self.words_per_entry,
lanes: self.lanes,
}
}
}
#[derive(Default, Debug, Clone, Serialize)]
pub struct PackedInfoConst {
pub is_packed: bool,
pub num_packed_words: u64,
pub unpack_info: &'static [u64],
}
impl PackedInfoConst {
pub fn new(is_packed: bool, num_packed_words: u64, unpack_info: &'static [u64]) -> Self {
Self { is_packed, num_packed_words, unpack_info }
}
}