use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hasher;
use vortex_error::VortexExpect;
use vortex_error::VortexResult;
use super::Interleave;
use crate::ArrayEq;
use crate::ArrayHash;
use crate::ArrayRef;
use crate::EqMode;
use crate::array::Array;
use crate::array::ArrayParts;
use crate::array::ArraySlots;
use crate::array::TypedArrayRef;
use crate::array_slots;
use crate::dtype::DType;
#[array_slots(Interleave)]
pub(super) struct InterleaveSlots {
#[slot(0)]
pub array_indices: ArrayRef,
#[slot(1)]
pub row_indices: ArrayRef,
#[slot(2..)]
pub values: Vec<ArrayRef>,
}
pub type InterleaveArray = Array<Interleave>;
#[derive(Clone, Debug)]
pub struct InterleaveData {
pub(crate) num_values: usize,
}
impl Display for InterleaveData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "num_values: {}", self.num_values)
}
}
impl ArrayHash for InterleaveData {
fn array_hash<H: Hasher>(&self, state: &mut H, _accuracy: EqMode) {
state.write_usize(self.num_values);
}
}
impl ArrayEq for InterleaveData {
fn array_eq(&self, other: &Self, _accuracy: EqMode) -> bool {
self.num_values == other.num_values
}
}
pub trait InterleaveArrayExt: TypedArrayRef<Interleave> {
fn num_values(&self) -> usize {
self.num_values
}
fn value(&self, idx: usize) -> &ArrayRef {
self.slots()[InterleaveSlots::VALUES_OFFSET + idx]
.as_ref()
.vortex_expect("validated interleave value slot")
}
fn array_indices(&self) -> &ArrayRef {
self.slots()[InterleaveSlots::ARRAY_INDICES]
.as_ref()
.vortex_expect("validated interleave array_indices slot")
}
fn row_indices(&self) -> &ArrayRef {
self.slots()[InterleaveSlots::ROW_INDICES]
.as_ref()
.vortex_expect("validated interleave row_indices slot")
}
}
impl<T: TypedArrayRef<Interleave>> InterleaveArrayExt for T {}
impl Array<Interleave> {
pub fn try_new(
values: Vec<ArrayRef>,
array_indices: ArrayRef,
row_indices: ArrayRef,
) -> VortexResult<Self> {
let dtype = Interleave::check(&values, &array_indices, &row_indices)?;
Ok(unsafe { Self::new_unchecked(values, array_indices, row_indices, dtype) })
}
pub unsafe fn new_unchecked(
values: Vec<ArrayRef>,
array_indices: ArrayRef,
row_indices: ArrayRef,
dtype: DType,
) -> Self {
let slots = InterleaveSlots {
array_indices,
row_indices,
values,
}
.into_slots();
unsafe { Self::new_unchecked_slots(slots, dtype) }
}
pub unsafe fn new_unchecked_slots(slots: ArraySlots, dtype: DType) -> Self {
let num_values = slots.len() - InterleaveSlots::VALUES_OFFSET;
let len = slots[InterleaveSlots::ARRAY_INDICES]
.as_ref()
.vortex_expect("interleave array_indices slot present")
.len();
unsafe {
Array::from_parts_unchecked(ArrayParts::new(
Interleave,
dtype,
len,
InterleaveData { num_values },
slots,
))
}
}
}