• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16992335779

15 Aug 2025 02:38PM UTC coverage: 87.202% (-0.5%) from 87.72%
16992335779

Pull #2456

github

web-flow
Merge 39c262e2c into 4a23f65b3
Pull Request #2456: feat: basic BoolBuffer / BoolBufferMut

476 of 1231 new or added lines in 107 files covered. (38.67%)

74 existing lines in 19 files now uncovered.

56525 of 64821 relevant lines covered (87.2%)

623742.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/vortex-buffer/src/bit/aligned.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::iter;
5

6
use vortex_error::VortexExpect;
7

8
use crate::ByteBuffer;
9
use crate::trusted_len::TrustedLen;
10

11
/// Aligned bitwise view over underlying bytes in u64 chunks
12
pub struct BitChunks {
13
    buffer: ByteBuffer,
14
    len: usize,
15
    bit_offset: usize,
16
    remainder_len: usize,
17
}
18

19
impl BitChunks {
20
    /// Construct new with given length and offset
NEW
21
    pub fn new(buffer: ByteBuffer, offset: usize, len: usize) -> Self {
×
NEW
22
        let byte_len = (offset + len).div_ceil(8);
×
NEW
23
        assert!(
×
NEW
24
            byte_len <= buffer.len(),
×
NEW
25
            "Buffer {} too small for given length {len} and offset {offset}",
×
NEW
26
            buffer.len()
×
27
        );
28

NEW
29
        let bit_offset = offset % 8;
×
NEW
30
        let byte_offset = offset / 8;
×
NEW
31
        let remainder_len = len % 64;
×
32

NEW
33
        Self {
×
NEW
34
            buffer: buffer.slice(byte_offset..byte_len),
×
NEW
35
            len,
×
NEW
36
            bit_offset,
×
NEW
37
            remainder_len,
×
NEW
38
        }
×
NEW
39
    }
×
40

41
    /// Length of the last non full slice of bits
NEW
42
    pub fn remainder_len(&self) -> usize {
×
NEW
43
        self.remainder_len
×
NEW
44
    }
×
45

46
    /// Last u64 chunk of the underlying buffer
NEW
47
    pub fn remainder_bits(&self) -> u64 {
×
NEW
48
        if self.remainder_len == 0 {
×
NEW
49
            return 0;
×
NEW
50
        }
×
51

52
        // Since we sliced the buffer on construction then remainder is aligned with the buffer
53
        // NOTE: you want the rounding behaviour of integer division i.e., it's not correct to simplify this to self.len / 8
NEW
54
        let remainder_bytes = &self.buffer[self.len / 64 * 8..];
×
NEW
55
        let mut result_bits = remainder_bytes[0] as u64 >> self.bit_offset;
×
NEW
56
        for (i, &byte) in remainder_bytes[1..].iter().enumerate() {
×
NEW
57
            result_bits |= (byte as u64) << ((i + 1) * 8 - self.bit_offset);
×
NEW
58
        }
×
59

NEW
60
        result_bits & ((1 << self.remainder_len) - 1)
×
NEW
61
    }
×
62

63
    /// Get an interator over the bitwise chunks including the trailer
NEW
64
    pub fn iter(&self) -> PaddedBitChunksIterator {
×
NEW
65
        BitChunksIterator {
×
NEW
66
            buffer: self.buffer.clone(),
×
NEW
67
            bit_offset: self.bit_offset,
×
NEW
68
            chunk_count: self.len / 64,
×
NEW
69
            index: 0,
×
NEW
70
        }
×
NEW
71
        .chain(iter::once(self.remainder_bits()))
×
NEW
72
    }
×
73
}
74

75
impl IntoIterator for BitChunks {
76
    type Item = u64;
77
    type IntoIter = PaddedBitChunksIterator;
78

NEW
79
    fn into_iter(self) -> Self::IntoIter {
×
NEW
80
        self.iter()
×
NEW
81
    }
×
82
}
83

84
pub type PaddedBitChunksIterator = iter::Chain<BitChunksIterator, iter::Once<u64>>;
85

86
unsafe impl TrustedLen for PaddedBitChunksIterator {}
87

88
pub struct BitChunksIterator {
89
    buffer: ByteBuffer,
90
    bit_offset: usize,
91
    chunk_count: usize,
92
    index: usize,
93
}
94

95
impl Iterator for BitChunksIterator {
96
    type Item = u64;
97

NEW
98
    fn next(&mut self) -> Option<Self::Item> {
×
NEW
99
        if self.index >= self.chunk_count {
×
NEW
100
            return None;
×
NEW
101
        }
×
102

NEW
103
        let non_offset_chunk = u64::from_le_bytes(
×
NEW
104
            self.buffer[self.index * 8..(self.index + 1) * 8]
×
NEW
105
                .try_into()
×
NEW
106
                .vortex_expect("slice of 8 bytes"),
×
107
        );
NEW
108
        let result = if self.bit_offset == 0 {
×
NEW
109
            non_offset_chunk
×
110
        } else {
NEW
111
            let next_byte = self.buffer[(self.index + 1) * 8] as u64;
×
NEW
112
            (non_offset_chunk >> self.bit_offset) | (next_byte << (64 - self.bit_offset))
×
113
        };
114

NEW
115
        self.index += 1;
×
NEW
116
        Some(result)
×
NEW
117
    }
×
118

NEW
119
    fn size_hint(&self) -> (usize, Option<usize>) {
×
NEW
120
        let size = self.chunk_count - self.index;
×
NEW
121
        (size, Some(size))
×
NEW
122
    }
×
123
}
124

125
impl ExactSizeIterator for BitChunksIterator {}
126

127
unsafe impl TrustedLen for BitChunksIterator {}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc