use itertools::Itertools;
use vortex_error::VortexResult;
use vortex_scalar::Scalar;
use crate::array::struct_::StructArray;
use crate::compute::unary::{scalar_at, ScalarAtFn};
use crate::compute::{slice, take, ArrayCompute, SliceFn, TakeFn};
use crate::variants::StructArrayTrait;
use crate::{Array, ArrayDType, IntoArray};
impl ArrayCompute for StructArray {
fn scalar_at(&self) -> Option<&dyn ScalarAtFn> {
Some(self)
}
fn slice(&self) -> Option<&dyn SliceFn> {
Some(self)
}
fn take(&self) -> Option<&dyn TakeFn> {
Some(self)
}
}
impl ScalarAtFn for StructArray {
fn scalar_at(&self, index: usize) -> VortexResult<Scalar> {
Ok(Scalar::r#struct(
self.dtype().clone(),
self.children()
.map(|field| scalar_at(&field, index).map(|s| s.into_value()))
.try_collect()?,
))
}
}
impl TakeFn for StructArray {
fn take(&self, indices: &Array) -> VortexResult<Array> {
Self::try_new(
self.names().clone(),
self.children()
.map(|field| take(&field, indices))
.try_collect()?,
indices.len(),
self.validity().take(indices)?,
)
.map(|a| a.into_array())
}
}
impl SliceFn for StructArray {
fn slice(&self, start: usize, stop: usize) -> VortexResult<Array> {
let fields = self
.children()
.map(|field| slice(&field, start, stop))
.try_collect()?;
Self::try_new(
self.names().clone(),
fields,
stop - start,
self.validity().slice(start, stop)?,
)
.map(|a| a.into_array())
}
}