Skip to main content

arrow_data/equal/
list_view.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use crate::ArrayData;
6use crate::data::count_nulls;
7use crate::equal::equal_range;
8use arrow_buffer::ArrowNativeType;
9use num_integer::Integer;
10
11pub(super) fn list_view_equal<T: ArrowNativeType + Integer>(
12    lhs: &ArrayData,
13    rhs: &ArrayData,
14    lhs_start: usize,
15    rhs_start: usize,
16    len: usize,
17) -> bool {
18    let lhs_offsets = lhs.buffer::<T>(0);
19    let lhs_sizes = lhs.buffer::<T>(1);
20
21    let rhs_offsets = rhs.buffer::<T>(0);
22    let rhs_sizes = rhs.buffer::<T>(1);
23
24    let lhs_data = &lhs.child_data()[0];
25    let rhs_data = &rhs.child_data()[0];
26
27    let lhs_null_count = count_nulls(lhs.nulls(), lhs_start, len);
28    let rhs_null_count = count_nulls(rhs.nulls(), rhs_start, len);
29
30    if lhs_null_count != rhs_null_count {
31        return false;
32    }
33
34    // All four slices are `len` long
35    let lhs_range_sizes = &lhs_sizes[lhs_start..lhs_start + len];
36    let rhs_range_sizes = &rhs_sizes[rhs_start..rhs_start + len];
37    let lhs_range_offsets = &lhs_offsets[lhs_start..lhs_start + len];
38    let rhs_range_offsets = &rhs_offsets[rhs_start..rhs_start + len];
39
40    if lhs_null_count == 0 {
41        // non-null pathway: all sizes must be equal, and all values must be equal
42        if lhs_range_sizes != rhs_range_sizes {
43            return false;
44        }
45
46        // Check values for equality
47        for ((&lhs_offset, &rhs_offset), &size) in lhs_range_offsets
48            .iter()
49            .zip(rhs_range_offsets)
50            .zip(lhs_range_sizes)
51        {
52            let lhs_offset = lhs_offset.to_usize().unwrap();
53            let rhs_offset = rhs_offset.to_usize().unwrap();
54            let size = size.to_usize().unwrap();
55
56            if !equal_range(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
57                return false;
58            }
59        }
60    } else {
61        // Need to integrate validity check in the inner loop.
62        let lhs_nulls = lhs.nulls().unwrap().slice(lhs_start, len);
63        let rhs_nulls = rhs.nulls().unwrap().slice(rhs_start, len);
64
65        // Check values for equality, with null checking
66        for (index, ((&lhs_offset, &rhs_offset), (&lhs_size, &rhs_size))) in lhs_range_offsets
67            .iter()
68            .zip(rhs_range_offsets)
69            .zip(lhs_range_sizes.iter().zip(rhs_range_sizes))
70            .enumerate()
71        {
72            let lhs_is_null = lhs_nulls.is_null(index);
73            let rhs_is_null = rhs_nulls.is_null(index);
74
75            if lhs_is_null != rhs_is_null {
76                return false;
77            }
78
79            // Null rows are equal whatever their sizes and values
80            if lhs_is_null {
81                continue;
82            }
83
84            if lhs_size != rhs_size {
85                return false;
86            }
87
88            let lhs_offset = lhs_offset.to_usize().unwrap();
89            let rhs_offset = rhs_offset.to_usize().unwrap();
90            let size = lhs_size.to_usize().unwrap();
91
92            if !equal_range(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
93                return false;
94            }
95        }
96    }
97
98    true
99}