use vortex_array::ArrayView;
use vortex_array::ExecutionCtx;
use vortex_array::IntoArray;
use vortex_array::arrays::PrimitiveArray;
use vortex_array::scalar::Scalar;
use vortex_array::vtable::OperationsVTable;
use vortex_error::VortexResult;
use super::Delta;
impl OperationsVTable<Delta> for Delta {
fn scalar_at(
array: ArrayView<'_, Delta>,
index: usize,
ctx: &mut ExecutionCtx,
) -> VortexResult<Scalar> {
let decompressed = array
.array()
.slice(index..index + 1)?
.execute::<PrimitiveArray>(ctx)?;
decompressed.into_array().execute_scalar(0, ctx)
}
}
#[cfg(test)]
mod tests {
use std::sync::LazyLock;
use rstest::rstest;
use vortex_array::IntoArray;
use vortex_array::VortexSessionExecute;
use vortex_array::arrays::PrimitiveArray;
use vortex_array::assert_arrays_eq;
use vortex_array::compute::conformance::binary_numeric::test_binary_numeric_array;
use vortex_array::compute::conformance::consistency::test_array_consistency;
use vortex_array::session::ArraySession;
use vortex_array::validity::Validity;
use vortex_buffer::buffer;
use vortex_error::VortexExpect;
use vortex_session::VortexSession;
use crate::Delta;
use crate::DeltaArray;
static SESSION: LazyLock<VortexSession> =
LazyLock::new(|| VortexSession::empty().with::<ArraySession>());
fn da(array: &PrimitiveArray) -> DeltaArray {
Delta::try_from_primitive_array(array, &mut SESSION.create_execution_ctx())
.vortex_expect("Delta array construction should succeed")
}
#[test]
fn test_slice_non_jagged_array_first_chunk_of_two() {
let delta = da(&(0u32..2048).collect());
let actual = delta.slice(10..250).unwrap();
let expected = PrimitiveArray::from_iter(10u32..250).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_non_jagged_array_second_chunk_of_two() {
let delta = da(&(0u32..2048).collect());
let actual = delta.slice(1024 + 10..1024 + 250).unwrap();
let expected = PrimitiveArray::from_iter((1024 + 10u32)..(1024 + 250)).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_non_jagged_array_span_two_chunks_chunk_of_two() {
let delta = da(&(0u32..2048).collect());
let actual = delta.slice(1000..1048).unwrap();
let expected = PrimitiveArray::from_iter(1000u32..1048).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_non_jagged_array_span_two_chunks_chunk_of_four() {
let delta = da(&(0u32..4096).collect());
let actual = delta.slice(2040..2050).unwrap();
let expected = PrimitiveArray::from_iter(2040u32..2050).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_non_jagged_array_whole() {
let delta = da(&(0u32..4096).collect());
let actual = delta.slice(0..4096).unwrap();
let expected = PrimitiveArray::from_iter(0u32..4096).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_non_jagged_array_empty() {
let delta = da(&(0u32..4096).collect());
let actual = delta.slice(0..0).unwrap();
let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
assert_arrays_eq!(actual, expected);
let actual = delta.slice(4096..4096).unwrap();
let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
assert_arrays_eq!(actual, expected);
let actual = delta.slice(1024..1024).unwrap();
let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_jagged_array_second_chunk_of_two() {
let delta = da(&(0u32..2000).collect());
let actual = delta.slice(1024 + 10..1024 + 250).unwrap();
let expected = PrimitiveArray::from_iter((1024 + 10u32)..(1024 + 250)).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_jagged_array_empty() {
let delta = da(&(0u32..4000).collect());
let actual = delta.slice(0..0).unwrap();
let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
assert_arrays_eq!(actual, expected);
let actual = delta.slice(4000..4000).unwrap();
let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
assert_arrays_eq!(actual, expected);
let actual = delta.slice(1024..1024).unwrap();
let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
assert_arrays_eq!(actual, expected);
}
#[test]
fn test_slice_of_slice_of_non_jagged() {
let delta = da(&(0u32..2048).collect());
let sliced = delta.slice(10..1013).unwrap();
let sliced_again = sliced.slice(0..2).unwrap();
let expected = PrimitiveArray::from_iter(vec![10u32, 11]).into_array();
assert_arrays_eq!(sliced_again, expected);
}
#[test]
fn test_slice_of_slice_of_jagged() {
let delta = da(&(0u32..2000).collect());
let sliced = delta.slice(10..1013).unwrap();
let sliced_again = sliced.slice(0..2).unwrap();
let expected = PrimitiveArray::from_iter(vec![10u32, 11]).into_array();
assert_arrays_eq!(sliced_again, expected);
}
#[test]
fn test_slice_of_slice_second_chunk_of_non_jagged() {
let delta = da(&(0u32..2048).collect());
let sliced = delta.slice(1034..1050).unwrap();
let sliced_again = sliced.slice(0..2).unwrap();
let expected = PrimitiveArray::from_iter(vec![1034u32, 1035]).into_array();
assert_arrays_eq!(sliced_again, expected);
}
#[test]
fn test_slice_of_slice_second_chunk_of_jagged() {
let delta = da(&(0u32..2000).collect());
let sliced = delta.slice(1034..1050).unwrap();
let sliced_again = sliced.slice(0..2).unwrap();
let expected = PrimitiveArray::from_iter(vec![1034u32, 1035]).into_array();
assert_arrays_eq!(sliced_again, expected);
}
#[test]
fn test_slice_of_slice_spanning_two_chunks_of_non_jagged() {
let delta = da(&(0u32..2048).collect());
let sliced = delta.slice(1010..1050).unwrap();
let sliced_again = sliced.slice(5..20).unwrap();
let expected = PrimitiveArray::from_iter(1015u32..1030).into_array();
assert_arrays_eq!(sliced_again, expected);
}
#[test]
fn test_slice_of_slice_spanning_two_chunks_of_jagged() {
let delta = da(&(0u32..2000).collect());
let sliced = delta.slice(1010..1050).unwrap();
let sliced_again = sliced.slice(5..20).unwrap();
let expected = PrimitiveArray::from_iter(1015u32..1030).into_array();
assert_arrays_eq!(sliced_again, expected);
}
#[test]
fn test_scalar_at_non_jagged_array() {
let delta = da(&(0u32..2048).collect()).into_array();
let expected = PrimitiveArray::from_iter(0u32..2048).into_array();
assert_arrays_eq!(delta, expected);
}
#[test]
#[should_panic]
fn test_scalar_at_non_jagged_array_oob() {
let delta = da(&(0u32..2048).collect()).into_array();
delta
.execute_scalar(2048, &mut SESSION.create_execution_ctx())
.unwrap();
}
#[test]
fn test_scalar_at_jagged_array() {
let delta = da(&(0u32..2000).collect()).into_array();
let expected = PrimitiveArray::from_iter(0u32..2000).into_array();
assert_arrays_eq!(delta, expected);
}
#[test]
#[should_panic]
fn test_scalar_at_jagged_array_oob() {
let delta = da(&(0u32..2000).collect()).into_array();
delta
.execute_scalar(2000, &mut SESSION.create_execution_ctx())
.unwrap();
}
#[rstest]
#[case::delta_u32((0u32..100).collect())]
#[case::delta_u64((0..100).map(|i| i as u64 * 10).collect())]
#[case::delta_large_u32((0u32..2048).collect())]
#[case::delta_large_u64((0u64..2048).collect())]
#[case::delta_single(PrimitiveArray::new(buffer![42u32], Validity::NonNullable))]
fn test_delta_consistency(#[case] array: PrimitiveArray) {
test_array_consistency(&da(&array).into_array());
}
#[rstest]
#[case::delta_u8_basic(PrimitiveArray::new(buffer![1u8, 1, 1, 1, 1], Validity::NonNullable))]
#[case::delta_u16_basic(PrimitiveArray::new(buffer![1u16, 1, 1, 1, 1], Validity::NonNullable))]
#[case::delta_u32_basic(PrimitiveArray::new(buffer![1u32, 1, 1, 1, 1], Validity::NonNullable))]
#[case::delta_u64_basic(PrimitiveArray::new(buffer![1u64, 1, 1, 1, 1], Validity::NonNullable))]
#[case::delta_u32_large(PrimitiveArray::new(buffer![1u32; 100], Validity::NonNullable))]
fn test_delta_binary_numeric(#[case] array: PrimitiveArray) {
test_binary_numeric_array(da(&array).into_array());
}
}