## Coverage Report

#### Created: 2025-08-26 07:03

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
    0
    pub fn bitwise_quaternary_op_helper<F>(
    24
    0
        buffers: [&Buffer; 4],
    25
    0
        offsets: [usize; 4],
    26
    0
        len_in_bits: usize,
    27
    0
        op: F,
    28
    0
    ) -> Buffer
    29
    0
    where
    30
    0
        F: Fn(u64, u64, u64, u64) -> u64,
    31
    {
    32
    0
        let first_chunks = buffers[0].bit_chunks(offsets[0], len_in_bits);
    33
    0
        let second_chunks = buffers[1].bit_chunks(offsets[1], len_in_bits);
    34
    0
        let third_chunks = buffers[2].bit_chunks(offsets[2], len_in_bits);
    35
    0
        let fourth_chunks = buffers[3].bit_chunks(offsets[3], len_in_bits);
    36
    37
    0
        let chunks = first_chunks
    38
    0
            .iter()
    39
    0
            .zip(second_chunks.iter())
    40
    0
            .zip(third_chunks.iter())
    41
    0
            .zip(fourth_chunks.iter())
    42
    0
            .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
    0
        let mut buffer = unsafe { MutableBuffer::from_trusted_len_iter(chunks) };
    46
    47
    0
        let remainder_bytes = ceil(first_chunks.remainder_len(), 8);
    48
    0
        let rem = op(
    49
    0
            first_chunks.remainder_bits(),
    50
    0
            second_chunks.remainder_bits(),
    51
    0
            third_chunks.remainder_bits(),
    52
    0
            fourth_chunks.remainder_bits(),
    53
    0
        );
    54
        // we are counting its starting from the least significant bit, to to_le_bytes should be correct
    55
    0
        let rem = &rem.to_le_bytes()[0..remainder_bytes];
    56
    0
        buffer.extend_from_slice(rem);
    57
    58
    0
        buffer.into()
    59
    0
    }
    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
    0
    pub fn bitwise_bin_op_helper<F>(
    64
    0
        left: &Buffer,
    65
    0
        left_offset_in_bits: usize,
    66
    0
        right: &Buffer,
    67
    0
        right_offset_in_bits: usize,
    68
    0
        len_in_bits: usize,
    69
    0
        mut op: F,
    70
    0
    ) -> Buffer
    71
    0
    where
    72
    0
        F: FnMut(u64, u64) -> u64,
    73
    {
    74
    0
        let left_chunks = left.bit_chunks(left_offset_in_bits, len_in_bits);
    75
    0
        let right_chunks = right.bit_chunks(right_offset_in_bits, len_in_bits);
    76
    77
    0
        let chunks = left_chunks
    78
    0
            .iter()
    79
    0
            .zip(right_chunks.iter())
    80
    0
            .map(|(left, right)| op(left, right));
    81
        // Soundness: `BitChunks` is a `BitChunks` iterator which
    82
        // correctly reports its upper bound
    83
    0
        let mut buffer = unsafe { MutableBuffer::from_trusted_len_iter(chunks) };
    84
    85
    0
        let remainder_bytes = ceil(left_chunks.remainder_len(), 8);
    86
    0
        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
    0
        let rem = &rem.to_le_bytes()[0..remainder_bytes];
    89
    0
        buffer.extend_from_slice(rem);
    90
    91
    0
        buffer.into()
    92
    0
    }
    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
    0
    pub fn bitwise_unary_op_helper<F>(
    97
    0
        left: &Buffer,
    98
    0
        offset_in_bits: usize,
    99
    0
        len_in_bits: usize,
    100
    0
        mut op: F,
    101
    0
    ) -> Buffer
    102
    0
    where
    103
    0
        F: FnMut(u64) -> u64,
    104
    {
    105
        // reserve capacity and set length so we can get a typed view of u64 chunks
    106
    0
        let mut result =
    107
    0
            MutableBuffer::new(ceil(len_in_bits, 8)).with_bitset(len_in_bits / 64 * 8, false);
    108
    109
    0
        let left_chunks = left.bit_chunks(offset_in_bits, len_in_bits);
    110
    111
    0
        let result_chunks = result.typed_data_mut::<u64>().iter_mut();
    112
    113
    0
        result_chunks
    114
    0
            .zip(left_chunks.iter())
    115
    0
            .for_each(|(res, left)| {
    116
    0
                *res = op(left);
    117
    0
            });
    118
    119
    0
        let remainder_bytes = ceil(left_chunks.remainder_len(), 8);
    120
    0
        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
    0
        let rem = &rem.to_le_bytes()[0..remainder_bytes];
    123
    0
        result.extend_from_slice(rem);
    124
    125
    0
        result.into()
    126
    0
    }
    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
    0
    pub fn buffer_bin_and(
    131
    0
        left: &Buffer,
    132
    0
        left_offset_in_bits: usize,
    133
    0
        right: &Buffer,
    134
    0
        right_offset_in_bits: usize,
    135
    0
        len_in_bits: usize,
    136
    0
    ) -> Buffer {
    137
    0
        bitwise_bin_op_helper(
    138
    0
            left,
    139
    0
            left_offset_in_bits,
    140
    0
            right,
    141
    0
            right_offset_in_bits,
    142
    0
            len_in_bits,
    143
    0
            |a, b| a & b,
    144
        )
    145
    0
    }
    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
    0
    pub fn buffer_unary_not(left: &Buffer, offset_in_bits: usize, len_in_bits: usize) -> Buffer {
    207
    0
        bitwise_unary_op_helper(left, offset_in_bits, len_in_bits, |a| !a)
    208
    0
    }