use std::fmt::Debug;
use std::ops::Sub;
use arrow::datatypes::ArrowNativeType;
use crate::joins::MapOffset;
#[inline(always)]
pub(crate) fn traverse_chain<T>(
next_chain: &[T],
prob_idx: usize,
start_chain_idx: T,
remaining: &mut usize,
input_indices: &mut Vec<u32>,
match_indices: &mut Vec<u64>,
is_last_input: bool,
) -> Option<MapOffset>
where
T: Copy + TryFrom<usize> + PartialOrd + Into<u64> + Sub<Output = T>,
<T as TryFrom<usize>>::Error: Debug,
T: ArrowNativeType,
{
let zero = T::usize_as(0);
let one = T::usize_as(1);
let mut match_row_idx = start_chain_idx - one;
loop {
match_indices.push(match_row_idx.into());
input_indices.push(prob_idx as u32);
*remaining -= 1;
let next = next_chain[match_row_idx.into() as usize];
if *remaining == 0 {
return if is_last_input && next == zero {
None
} else {
Some((prob_idx, Some(next.into())))
};
}
if next == zero {
return None;
}
match_row_idx = next - one;
}
}