use vortex_compute::lane_kernels::IndexedSourceExt;
use vortex_error::VortexError;
use vortex_error::VortexResult;
use vortex_error::vortex_ensure;
use crate::ArrayRef;
use crate::ExecutionCtx;
use crate::scalar_fn::ExecutionArgs;
use crate::scalar_fn::unstable::row::FailureEvidence;
use crate::scalar_fn::unstable::row::IndexedElementTuple;
use crate::scalar_fn::unstable::row::OutputElement;
use crate::scalar_fn::unstable::row::visitor::assert_owned_output_needs_no_drop;
pub(in crate::scalar_fn::unstable::row) enum DenseAttempt {
Values(ArrayRef),
DeferredError(VortexError),
}
pub(in crate::scalar_fn::unstable::row) fn execute_owned_dense_attempt<Args, Out, Prepared, Fail>(
args: &dyn ExecutionArgs,
ctx: &mut ExecutionCtx,
prepare: impl FnOnce(Args::ConstElems<'_>) -> Prepared,
apply: impl Fn(&Prepared, Args::Elems<'_>) -> (Out, Fail),
finish_failure: impl FnOnce(Fail) -> VortexResult<()>,
) -> VortexResult<DenseAttempt>
where
Args: IndexedElementTuple,
Out: OutputElement,
Fail: FailureEvidence,
{
const { assert_owned_output_needs_no_drop::<Out>() };
let columns = Args::decode(args, ctx)?;
let prepared = prepare(Args::const_values(&columns));
let row_count = args.row_count();
let mut values = Vec::<Out>::with_capacity(row_count);
let output = &mut values.spare_capacity_mut()[..row_count];
let failure_evidence = if let Some(views) = Args::views_if_no_consts(&columns) {
vortex_ensure!(
Args::view_lens_match(&views, row_count),
"a decoded row input does not address exactly {row_count} rows",
);
let source = unsafe { Args::indexed_source(views, row_count) };
source.map_checked_into(output, |elements| apply(&prepared, elements))
} else {
vortex_ensure!(
Args::decoded_lens_match(&columns, row_count),
"a decoded row input does not address exactly {row_count} rows",
);
let mut accumulated_failure = Fail::default();
for (index, slot) in output.iter_mut().enumerate() {
let (value, row_failure) = apply(&prepared, Args::get(&columns, index));
slot.write(value);
accumulated_failure |= row_failure;
}
accumulated_failure
};
unsafe { values.set_len(row_count) };
match finish_failure(failure_evidence) {
Ok(()) => Ok(DenseAttempt::Values(Out::build(values))),
Err(error) => Ok(DenseAttempt::DeferredError(error)),
}
}