arrow_data/equal/
list_view.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::ArrayData;
19use crate::data::count_nulls;
20use crate::equal::equal_values;
21use arrow_buffer::ArrowNativeType;
22use num_integer::Integer;
23
24pub(super) fn list_view_equal<T: ArrowNativeType + Integer>(
25    lhs: &ArrayData,
26    rhs: &ArrayData,
27    lhs_start: usize,
28    rhs_start: usize,
29    len: usize,
30) -> bool {
31    let lhs_offsets = lhs.buffer::<T>(0);
32    let lhs_sizes = lhs.buffer::<T>(1);
33
34    let rhs_offsets = rhs.buffer::<T>(0);
35    let rhs_sizes = rhs.buffer::<T>(1);
36
37    let lhs_data = &lhs.child_data()[0];
38    let rhs_data = &rhs.child_data()[0];
39
40    let lhs_null_count = count_nulls(lhs.nulls(), lhs_start, len);
41    let rhs_null_count = count_nulls(rhs.nulls(), rhs_start, len);
42
43    if lhs_null_count != rhs_null_count {
44        return false;
45    }
46
47    if lhs_null_count == 0 {
48        // non-null pathway: all sizes must be equal, and all values must be equal
49        let lhs_range_sizes = &lhs_sizes[lhs_start..lhs_start + len];
50        let rhs_range_sizes = &rhs_sizes[rhs_start..rhs_start + len];
51
52        if lhs_range_sizes.len() != rhs_range_sizes.len() {
53            return false;
54        }
55
56        if lhs_range_sizes != rhs_range_sizes {
57            return false;
58        }
59
60        // Check values for equality
61        let lhs_range_offsets = &lhs_offsets[lhs_start..lhs_start + len];
62        let rhs_range_offsets = &rhs_offsets[rhs_start..rhs_start + len];
63
64        if lhs_range_offsets.len() != rhs_range_offsets.len() {
65            return false;
66        }
67
68        for ((&lhs_offset, &rhs_offset), &size) in lhs_range_offsets
69            .iter()
70            .zip(rhs_range_offsets)
71            .zip(lhs_range_sizes)
72        {
73            let lhs_offset = lhs_offset.to_usize().unwrap();
74            let rhs_offset = rhs_offset.to_usize().unwrap();
75            let size = size.to_usize().unwrap();
76
77            // Check if offsets are valid for the given range
78            if !equal_values(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
79                return false;
80            }
81        }
82    } else {
83        // Need to integrate validity check in the inner loop.
84        // non-null pathway: all sizes must be equal, and all values must be equal
85        let lhs_range_sizes = &lhs_sizes[lhs_start..lhs_start + len];
86        let rhs_range_sizes = &rhs_sizes[rhs_start..rhs_start + len];
87
88        let lhs_nulls = lhs.nulls().unwrap().slice(lhs_start, len);
89        let rhs_nulls = rhs.nulls().unwrap().slice(rhs_start, len);
90
91        // Sizes can differ if values are null
92        if lhs_range_sizes.len() != rhs_range_sizes.len() {
93            return false;
94        }
95
96        // Check values for equality, with null checking
97        let lhs_range_offsets = &lhs_offsets[lhs_start..lhs_start + len];
98        let rhs_range_offsets = &rhs_offsets[rhs_start..rhs_start + len];
99
100        if lhs_range_offsets.len() != rhs_range_offsets.len() {
101            return false;
102        }
103
104        for (index, ((&lhs_offset, &rhs_offset), &size)) in lhs_range_offsets
105            .iter()
106            .zip(rhs_range_offsets)
107            .zip(lhs_range_sizes)
108            .enumerate()
109        {
110            let lhs_is_null = lhs_nulls.is_null(index);
111            let rhs_is_null = rhs_nulls.is_null(index);
112
113            if lhs_is_null != rhs_is_null {
114                return false;
115            }
116
117            let lhs_offset = lhs_offset.to_usize().unwrap();
118            let rhs_offset = rhs_offset.to_usize().unwrap();
119            let size = size.to_usize().unwrap();
120
121            // Check if values match in the range
122            if !lhs_is_null && !equal_values(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
123                return false;
124            }
125        }
126    }
127
128    true
129}