## Coverage Report

#### Created: 2025-11-17 14:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/arrow-rs/arrow-buffer/src/buffer/ops.rs

    Line
    Count
    Source
    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
    18
    use super::{Buffer, MutableBuffer};
    19
    use crate::util::bit_util::ceil;
    20
    21
    /// Apply a bitwise operation `op` to four inputs and return the result as a Buffer.
    22
    /// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
    23
    pub fn bitwise_quaternary_op_helper<F>(
    24
        buffers: [&Buffer; 4],
    25
        offsets: [usize; 4],
    26
        len_in_bits: usize,
    27
        op: F,
    28
    ) -> Buffer
    29
    where
    30
        F: Fn(u64, u64, u64, u64) -> u64,
    31
    {
    32
        let first_chunks = buffers[0].bit_chunks(offsets[0], len_in_bits);
    33
        let second_chunks = buffers[1].bit_chunks(offsets[1], len_in_bits);
    34
        let third_chunks = buffers[2].bit_chunks(offsets[2], len_in_bits);
    35
        let fourth_chunks = buffers[3].bit_chunks(offsets[3], len_in_bits);
    36
    37
        let chunks = first_chunks
    38
            .iter()
    39
            .zip(second_chunks.iter())
    40
            .zip(third_chunks.iter())
    41
            .zip(fourth_chunks.iter())
    42
            .map(|(((first, second), third), fourth)| op(first, second, third, fourth));
    43
        // Soundness: `BitChunks` is a `BitChunks` iterator which
    44
        // correctly reports its upper bound
    45
        let mut buffer = unsafe { MutableBuffer::from_trusted_len_iter(chunks) };
    46
    47
        let remainder_bytes = ceil(first_chunks.remainder_len(), 8);
    48
        let rem = op(
    49
            first_chunks.remainder_bits(),
    50
            second_chunks.remainder_bits(),
    51
            third_chunks.remainder_bits(),
    52
            fourth_chunks.remainder_bits(),
    53
        );
    54
        // we are counting its starting from the least significant bit, to to_le_bytes should be correct
    55
        let rem = &rem.to_le_bytes()[0..remainder_bytes];
    56
        buffer.extend_from_slice(rem);
    57
    58
        buffer.into()
    59
    }
    60
    61
    /// Apply a bitwise operation `op` to two inputs and return the result as a Buffer.
    62
    /// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
    63
    789
    pub fn bitwise_bin_op_helper<F>(
    64
    789
        left: &Buffer,
    65
    789
        left_offset_in_bits: usize,
    66
    789
        right: &Buffer,
    67
    789
        right_offset_in_bits: usize,
    68
    789
        len_in_bits: usize,
    69
    789
        mut op: F,
    70
    789
    ) -> Buffer
    71
    789
    where
    72
    789
        F: FnMut(u64, u64) -> u64,
    73
    {
    74
    789
        let left_chunks = left.bit_chunks(left_offset_in_bits, len_in_bits);
    75
    789
        let right_chunks = right.bit_chunks(right_offset_in_bits, len_in_bits);
    76
    77
    789
        let chunks = left_chunks
    78
    789
            .iter()
    79
    789
            .zip(right_chunks.iter())
    80
    789
            .map(|(left, right)| op768(left768, right768));
    81
        // Soundness: `BitChunks` is a `BitChunks` iterator which
    82
        // correctly reports its upper bound
    83
    789
        let mut buffer = unsafe { MutableBuffer::from_trusted_len_iter(chunks) };
    84
    85
    789
        let remainder_bytes = ceil(left_chunks.remainder_len(), 8);
    86
    789
        let rem = op(left_chunks.remainder_bits(), right_chunks.remainder_bits());
    87
        // we are counting its starting from the least significant bit, to to_le_bytes should be correct
    88
    789
        let rem = &rem.to_le_bytes()[0..remainder_bytes];
    89
    789
        buffer.extend_from_slice(rem);
    90
    91
    789
        buffer.into()
    92
    789
    }
    93
    94
    /// Apply a bitwise operation `op` to one input and return the result as a Buffer.
    95
    /// The input is treated as a bitmap, meaning that offset and length are specified in number of bits.
    96
    271
    pub fn bitwise_unary_op_helper<F>(
    97
    271
        left: &Buffer,
    98
    271
        offset_in_bits: usize,
    99
    271
        len_in_bits: usize,
    100
    271
        mut op: F,
    101
    271
    ) -> Buffer
    102
    271
    where
    103
    271
        F: FnMut(u64) -> u64,
    104
    {
    105
        // reserve capacity and set length so we can get a typed view of u64 chunks
    106
    271
        let mut result =
    107
    271
            MutableBuffer::new(ceil(len_in_bits, 8)).with_bitset(len_in_bits / 64 * 8, false);
    108
    109
    271
        let left_chunks = left.bit_chunks(offset_in_bits, len_in_bits);
    110
    111
    271
        let result_chunks = result.typed_data_mut::<u64>().iter_mut();
    112
    113
    271
        result_chunks
    114
    271
            .zip(left_chunks.iter())
    115
    271
            .for_each(|(res, left)| {256
    116
    256
                *res = op(left);
    117
    256
            });
    118
    119
    271
        let remainder_bytes = ceil(left_chunks.remainder_len(), 8);
    120
    271
        let rem = op(left_chunks.remainder_bits());
    121
        // we are counting its starting from the least significant bit, to to_le_bytes should be correct
    122
    271
        let rem = &rem.to_le_bytes()[0..remainder_bytes];
    123
    271
        result.extend_from_slice(rem);
    124
    125
    271
        result.into()
    126
    271
    }
    127
    128
    /// Apply a bitwise and to two inputs and return the result as a Buffer.
    129
    /// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
    130
    530
    pub fn buffer_bin_and(
    131
    530
        left: &Buffer,
    132
    530
        left_offset_in_bits: usize,
    133
    530
        right: &Buffer,
    134
    530
        right_offset_in_bits: usize,
    135
    530
        len_in_bits: usize,
    136
    530
    ) -> Buffer {
    137
    530
        bitwise_bin_op_helper(
    138
    530
            left,
    139
    530
            left_offset_in_bits,
    140
    530
            right,
    141
    530
            right_offset_in_bits,
    142
    530
            len_in_bits,
    143
    1.04k
            |a, b| a & b,
    144
        )
    145
    530
    }
    146
    147
    /// Apply a bitwise or to two inputs and return the result as a Buffer.
    148
    /// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
    149
    0
    pub fn buffer_bin_or(
    150
    0
        left: &Buffer,
    151
    0
        left_offset_in_bits: usize,
    152
    0
        right: &Buffer,
    153
    0
        right_offset_in_bits: usize,
    154
    0
        len_in_bits: usize,
    155
    0
    ) -> Buffer {
    156
    0
        bitwise_bin_op_helper(
    157
    0
            left,
    158
    0
            left_offset_in_bits,
    159
    0
            right,
    160
    0
            right_offset_in_bits,
    161
    0
            len_in_bits,
    162
    0
            |a, b| a | b,
    163
        )
    164
    0
    }
    165
    166
    /// Apply a bitwise xor to two inputs and return the result as a Buffer.
    167
    /// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
    168
    0
    pub fn buffer_bin_xor(
    169
    0
        left: &Buffer,
    170
    0
        left_offset_in_bits: usize,
    171
    0
        right: &Buffer,
    172
    0
        right_offset_in_bits: usize,
    173
    0
        len_in_bits: usize,
    174
    0
    ) -> Buffer {
    175
    0
        bitwise_bin_op_helper(
    176
    0
            left,
    177
    0
            left_offset_in_bits,
    178
    0
            right,
    179
    0
            right_offset_in_bits,
    180
    0
            len_in_bits,
    181
    0
            |a, b| a ^ b,
    182
        )
    183
    0
    }
    184
    185
    /// Apply a bitwise and_not to two inputs and return the result as a Buffer.
    186
    /// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
    187
    0
    pub fn buffer_bin_and_not(
    188
    0
        left: &Buffer,
    189
    0
        left_offset_in_bits: usize,
    190
    0
        right: &Buffer,
    191
    0
        right_offset_in_bits: usize,
    192
    0
        len_in_bits: usize,
    193
    0
    ) -> Buffer {
    194
    0
        bitwise_bin_op_helper(
    195
    0
            left,
    196
    0
            left_offset_in_bits,
    197
    0
            right,
    198
    0
            right_offset_in_bits,
    199
    0
            len_in_bits,
    200
    0
            |a, b| a & !b,
    201
        )
    202
    0
    }
    203
    204
    /// Apply a bitwise not to one input and return the result as a Buffer.
    205
    /// The input is treated as a bitmap, meaning that offset and length are specified in number of bits.
    206
    9
    pub fn buffer_unary_not(left: &Buffer, offset_in_bits: usize, len_in_bits: usize) -> Buffer {
    207
    9
        bitwise_unary_op_helper(left, offset_in_bits, len_in_bits, |a| !a)
    208
    9
    }