use std::fmt::Debug;
use std::mem::transmute;
use std::sync::Arc;
use arcref::ArcRef;
use vortex_error::VortexExpect;
use vortex_error::VortexResult;
use vortex_error::vortex_ensure;
use vortex_session::VortexSession;
use crate::ArrayAdapter;
use crate::ArrayRef;
use crate::DynArray;
use crate::ExecutionResult;
use crate::ExecutionStep;
use crate::IntoArray;
use crate::buffer::BufferHandle;
use crate::dtype::DType;
use crate::executor::ExecutionCtx;
use crate::serde::ArrayChildren;
use crate::vtable::VTable;
pub type ArrayId = ArcRef<str>;
pub type DynVTableRef = Arc<dyn DynVTable>;
pub trait DynVTable: 'static + Send + Sync + Debug {
fn clone_boxed(&self) -> Box<dyn DynVTable>;
#[allow(clippy::too_many_arguments)]
fn build(
&self,
id: ArrayId,
dtype: &DType,
len: usize,
metadata: &[u8],
buffers: &[BufferHandle],
children: &dyn ArrayChildren,
session: &VortexSession,
) -> VortexResult<ArrayRef>;
fn with_children(&self, array: &ArrayRef, children: Vec<ArrayRef>) -> VortexResult<ArrayRef>;
fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
fn reduce_parent(
&self,
array: &ArrayRef,
parent: &ArrayRef,
child_idx: usize,
) -> VortexResult<Option<ArrayRef>>;
fn execute(&self, array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult>;
fn execute_parent(
&self,
array: &ArrayRef,
parent: &ArrayRef,
child_idx: usize,
ctx: &mut ExecutionCtx,
) -> VortexResult<Option<ArrayRef>>;
}
impl<V: VTable> DynVTable for V {
fn clone_boxed(&self) -> Box<dyn DynVTable> {
Box::new(self.clone())
}
fn build(
&self,
_id: ArrayId,
dtype: &DType,
len: usize,
metadata: &[u8],
buffers: &[BufferHandle],
children: &dyn ArrayChildren,
session: &VortexSession,
) -> VortexResult<ArrayRef> {
let metadata = V::deserialize(metadata, dtype, len, buffers, session)?;
let array = V::build(dtype, len, &metadata, buffers, children)?;
assert_eq!(array.len(), len, "Array length mismatch after building");
assert_eq!(array.dtype(), dtype, "Array dtype mismatch after building");
Ok(array.into_array())
}
fn with_children(&self, array: &ArrayRef, children: Vec<ArrayRef>) -> VortexResult<ArrayRef> {
let mut array = array.as_::<V>().clone();
V::with_children(&mut array, children)?;
Ok(array.into_array())
}
fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
let Some(reduced) = V::reduce(downcast::<V>(array))? else {
return Ok(None);
};
vortex_ensure!(
reduced.len() == array.len(),
"Reduced array length mismatch from {} to {}",
array.encoding_id(),
reduced.encoding_id()
);
vortex_ensure!(
reduced.dtype() == array.dtype(),
"Reduced array dtype mismatch from {} to {}",
array.encoding_id(),
reduced.encoding_id()
);
Ok(Some(reduced))
}
fn reduce_parent(
&self,
array: &ArrayRef,
parent: &ArrayRef,
child_idx: usize,
) -> VortexResult<Option<ArrayRef>> {
let Some(reduced) = V::reduce_parent(downcast::<V>(array), parent, child_idx)? else {
return Ok(None);
};
vortex_ensure!(
reduced.len() == parent.len(),
"Reduced array length mismatch from {} to {}",
parent.encoding_id(),
reduced.encoding_id()
);
vortex_ensure!(
reduced.dtype() == parent.dtype(),
"Reduced array dtype mismatch from {} to {}",
parent.encoding_id(),
reduced.encoding_id()
);
Ok(Some(reduced))
}
fn execute(&self, array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
let len = array.len();
let dtype = array.dtype().clone();
let stats = array.statistics().to_owned();
let owned = downcast_owned::<V>(array);
let result = V::execute(owned, ctx)?;
if matches!(result.step(), ExecutionStep::Done) {
if cfg!(debug_assertions) {
vortex_ensure!(
result.array().len() == len,
"Result length mismatch for {:?}",
self
);
vortex_ensure!(
result.array().dtype() == &dtype,
"Executed canonical dtype mismatch for {:?}",
self
);
}
result.array().statistics().set_iter(stats.into_iter());
}
Ok(result)
}
fn execute_parent(
&self,
array: &ArrayRef,
parent: &ArrayRef,
child_idx: usize,
ctx: &mut ExecutionCtx,
) -> VortexResult<Option<ArrayRef>> {
let Some(result) = V::execute_parent(downcast::<V>(array), parent, child_idx, ctx)? else {
return Ok(None);
};
if cfg!(debug_assertions) {
vortex_ensure!(
result.as_ref().len() == parent.len(),
"Executed parent canonical length mismatch"
);
vortex_ensure!(
result.as_ref().dtype() == parent.dtype(),
"Executed parent canonical dtype mismatch"
);
}
Ok(Some(result))
}
}
fn downcast<V: VTable>(array: &ArrayRef) -> &V::Array {
array
.as_any()
.downcast_ref::<ArrayAdapter<V>>()
.vortex_expect("Failed to downcast array to expected encoding type")
.as_inner()
}
fn downcast_owned<V: VTable>(array: ArrayRef) -> Arc<V::Array> {
let adapter: Arc<ArrayAdapter<V>> = array
.as_any_arc()
.downcast::<ArrayAdapter<V>>()
.ok()
.vortex_expect("Failed to downcast array to expected encoding type");
unsafe { transmute::<Arc<ArrayAdapter<V>>, Arc<V::Array>>(adapter) }
}
pub(crate) fn upcast_array<V: VTable>(array: Arc<V::Array>) -> ArrayRef {
unsafe { transmute::<Arc<V::Array>, Arc<ArrayAdapter<V>>>(array) }
}