use std::ops::Range;
use vortex_buffer::Buffer;
use vortex_dtype::DecimalDType;
use vortex_scalar::{DecimalValue, NativeDecimalType, Scalar, match_each_decimal_value_type};
use crate::arrays::{DecimalArray, DecimalVTable};
use crate::validity::Validity;
use crate::vtable::OperationsVTable;
use crate::{ArrayRef, IntoArray};
impl OperationsVTable<DecimalVTable> for DecimalVTable {
fn slice(array: &DecimalArray, range: Range<usize>) -> ArrayRef {
match_each_decimal_value_type!(array.values_type(), |D| {
slice_typed(
array.buffer::<D>(),
range,
array.decimal_dtype(),
array.validity.clone(),
)
})
}
fn scalar_at(array: &DecimalArray, index: usize) -> Scalar {
match_each_decimal_value_type!(array.values_type(), |D| {
Scalar::decimal(
DecimalValue::from(array.buffer::<D>()[index]),
array.decimal_dtype(),
array.dtype().nullability(),
)
})
}
}
fn slice_typed<T: NativeDecimalType>(
values: Buffer<T>,
range: Range<usize>,
decimal_dtype: DecimalDType,
validity: Validity,
) -> ArrayRef {
let sliced = values.slice(range.clone());
let validity = validity.slice(range);
unsafe { DecimalArray::new_unchecked(sliced, decimal_dtype, validity) }.into_array()
}
#[cfg(test)]
mod tests {
use vortex_buffer::buffer;
use vortex_dtype::{DecimalDType, Nullability};
use vortex_scalar::{DecimalValue, Scalar};
use crate::Array;
use crate::arrays::{DecimalArray, DecimalVTable};
use crate::validity::Validity;
#[test]
fn test_slice() {
let array = DecimalArray::new(
buffer![100i128, 200i128, 300i128, 4000i128],
DecimalDType::new(3, 2),
Validity::NonNullable,
)
.to_array();
let sliced = array.slice(1..3);
assert_eq!(sliced.len(), 2);
let decimal = sliced.as_::<DecimalVTable>();
assert_eq!(decimal.buffer::<i128>(), buffer![200i128, 300i128]);
}
#[test]
fn test_slice_nullable() {
let array = DecimalArray::new(
buffer![100i128, 200i128, 300i128, 4000i128],
DecimalDType::new(3, 2),
Validity::from_iter([false, true, false, true]),
)
.to_array();
let sliced = array.slice(1..3);
assert_eq!(sliced.len(), 2);
}
#[test]
fn test_scalar_at() {
let array = DecimalArray::new(
buffer![100i128],
DecimalDType::new(3, 2),
Validity::NonNullable,
);
assert_eq!(
array.scalar_at(0),
Scalar::decimal(
DecimalValue::I128(100),
DecimalDType::new(3, 2),
Nullability::NonNullable
)
);
}
}