use crate::data::{count_nulls, ArrayData};
use arrow_buffer::ArrowNativeType;
use num::Integer;
use super::equal_range;
fn lengths_equal<T: ArrowNativeType + Integer>(lhs: &[T], rhs: &[T]) -> bool {
debug_assert_eq!(lhs.len(), rhs.len());
if lhs.is_empty() {
return true;
}
if lhs[0] == T::zero() && rhs[0] == T::zero() {
return lhs == rhs;
};
lhs.windows(2)
.zip(rhs.windows(2))
.all(|(lhs_offsets, rhs_offsets)| {
(lhs_offsets[1] - lhs_offsets[0]) == (rhs_offsets[1] - rhs_offsets[0])
})
}
pub(super) fn list_equal<T: ArrowNativeType + Integer>(
lhs: &ArrayData,
rhs: &ArrayData,
lhs_start: usize,
rhs_start: usize,
len: usize,
) -> bool {
let lhs_offsets = lhs.buffer::<T>(0);
let rhs_offsets = rhs.buffer::<T>(0);
if len == 0 {
return true;
}
let lhs_child_length = lhs_offsets[lhs_start + len].to_usize().unwrap()
- lhs_offsets[lhs_start].to_usize().unwrap();
let rhs_child_length = rhs_offsets[rhs_start + len].to_usize().unwrap()
- rhs_offsets[rhs_start].to_usize().unwrap();
if lhs_child_length == 0 && lhs_child_length == rhs_child_length {
return true;
}
let lhs_values = &lhs.child_data()[0];
let rhs_values = &rhs.child_data()[0];
let lhs_null_count = count_nulls(lhs.nulls(), lhs_start, len);
let rhs_null_count = count_nulls(rhs.nulls(), rhs_start, len);
if lhs_null_count != rhs_null_count {
return false;
}
if lhs_null_count == 0 && rhs_null_count == 0 {
lhs_child_length == rhs_child_length
&& lengths_equal(
&lhs_offsets[lhs_start..lhs_start + len],
&rhs_offsets[rhs_start..rhs_start + len],
)
&& equal_range(
lhs_values,
rhs_values,
lhs_offsets[lhs_start].to_usize().unwrap(),
rhs_offsets[rhs_start].to_usize().unwrap(),
lhs_child_length,
)
} else {
let lhs_nulls = lhs.nulls().unwrap();
let rhs_nulls = rhs.nulls().unwrap();
(0..len).all(|i| {
let lhs_pos = lhs_start + i;
let rhs_pos = rhs_start + i;
let lhs_is_null = lhs_nulls.is_null(lhs_pos);
let rhs_is_null = rhs_nulls.is_null(rhs_pos);
if lhs_is_null != rhs_is_null {
return false;
}
let lhs_offset_start = lhs_offsets[lhs_pos].to_usize().unwrap();
let lhs_offset_end = lhs_offsets[lhs_pos + 1].to_usize().unwrap();
let rhs_offset_start = rhs_offsets[rhs_pos].to_usize().unwrap();
let rhs_offset_end = rhs_offsets[rhs_pos + 1].to_usize().unwrap();
let lhs_len = lhs_offset_end - lhs_offset_start;
let rhs_len = rhs_offset_end - rhs_offset_start;
lhs_is_null
|| (lhs_len == rhs_len
&& equal_range(
lhs_values,
rhs_values,
lhs_offset_start,
rhs_offset_start,
lhs_len,
))
})
}
}