Skip to main content

arrow_data/equal/
byte_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, ByteView};
6
7pub(super) fn byte_view_equal(
8    lhs: &ArrayData,
9    rhs: &ArrayData,
10    lhs_start: usize,
11    rhs_start: usize,
12    len: usize,
13) -> bool {
14    let lhs_views = &lhs.buffer::<u128>(0)[lhs_start..lhs_start + len];
15    let lhs_buffers = &lhs.buffers()[1..];
16    let rhs_views = &rhs.buffer::<u128>(0)[rhs_start..rhs_start + len];
17    let rhs_buffers = &rhs.buffers()[1..];
18
19    for (idx, (l, r)) in lhs_views.iter().zip(rhs_views).enumerate() {
20        // Only checking one null mask here because by the time the control flow reaches
21        // this point, the equality of the two masks would have already been verified.
22        // `idx` counts from `lhs_start`, so offset it to index the null mask.
23        if lhs.is_null(lhs_start + idx) {
24            continue;
25        }
26
27        let l_len_prefix = *l as u64;
28        let r_len_prefix = *r as u64;
29        // short-circuit, check length and prefix
30        if l_len_prefix != r_len_prefix {
31            return false;
32        }
33
34        let len = l_len_prefix as u32;
35        // for inline storage, only need check view
36        if len <= 12 {
37            if l != r {
38                return false;
39            }
40            continue;
41        }
42
43        // check buffers
44        let l_view = ByteView::from(*l);
45        let r_view = ByteView::from(*r);
46
47        let l_buffer = &lhs_buffers[l_view.buffer_index as usize];
48        let r_buffer = &rhs_buffers[r_view.buffer_index as usize];
49
50        // prefixes are already known to be equal; skip checking them
51        let len = len as usize - 4;
52        let l_offset = l_view.offset as usize + 4;
53        let r_offset = r_view.offset as usize + 4;
54        if l_buffer[l_offset..l_offset + len] != r_buffer[r_offset..r_offset + len] {
55            return false;
56        }
57    }
58    true
59}