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

vortex-data / vortex / 16992684502

15 Aug 2025 02:56PM UTC coverage: 87.875% (+0.2%) from 87.72%
16992684502

Pull #2456

github

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

1275 of 1428 new or added lines in 110 files covered. (89.29%)

334 existing lines in 31 files now uncovered.

57169 of 65057 relevant lines covered (87.88%)

658056.52 hits per line

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

88.52
/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
21
    pub fn new(buffer: ByteBuffer, offset: usize, len: usize) -> Self {
125,855✔
22
        let byte_len = (offset + len).div_ceil(8);
125,855✔
23
        assert!(
125,855✔
24
            byte_len <= buffer.len(),
125,855✔
NEW
25
            "Buffer {} too small for given length {len} and offset {offset}",
×
NEW
26
            buffer.len()
×
27
        );
28

29
        let bit_offset = offset % 8;
125,855✔
30
        let byte_offset = offset / 8;
125,855✔
31
        let remainder_len = len % 64;
125,855✔
32

33
        Self {
125,855✔
34
            buffer: buffer.slice(byte_offset..byte_len),
125,855✔
35
            len,
125,855✔
36
            bit_offset,
125,855✔
37
            remainder_len,
125,855✔
38
        }
125,855✔
39
    }
125,855✔
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
47
    pub fn remainder_bits(&self) -> u64 {
125,855✔
48
        if self.remainder_len == 0 {
125,855✔
49
            return 0;
1,994✔
50
        }
123,861✔
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
54
        let remainder_bytes = &self.buffer[self.len / 64 * 8..];
123,861✔
55
        let mut result_bits = remainder_bytes[0] as u64 >> self.bit_offset;
123,861✔
56
        for (i, &byte) in remainder_bytes[1..].iter().enumerate() {
125,361✔
57
            result_bits |= (byte as u64) << ((i + 1) * 8 - self.bit_offset);
50,326✔
58
        }
50,326✔
59

60
        result_bits & ((1 << self.remainder_len) - 1)
123,861✔
61
    }
125,855✔
62

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

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

79
    fn into_iter(self) -> Self::IntoIter {
31,258✔
80
        self.iter()
31,258✔
81
    }
31,258✔
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

98
    fn next(&mut self) -> Option<Self::Item> {
1,140,419✔
99
        if self.index >= self.chunk_count {
1,140,419✔
100
            return None;
125,855✔
101
        }
1,014,564✔
102

103
        let non_offset_chunk = u64::from_le_bytes(
1,014,564✔
104
            self.buffer[self.index * 8..(self.index + 1) * 8]
1,014,564✔
105
                .try_into()
1,014,564✔
106
                .vortex_expect("slice of 8 bytes"),
1,014,564✔
107
        );
108
        let result = if self.bit_offset == 0 {
1,014,564✔
109
            non_offset_chunk
1,014,564✔
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

115
        self.index += 1;
1,014,564✔
116
        Some(result)
1,014,564✔
117
    }
1,140,419✔
118

119
    fn size_hint(&self) -> (usize, Option<usize>) {
116,825✔
120
        let size = self.chunk_count - self.index;
116,825✔
121
        (size, Some(size))
116,825✔
122
    }
116,825✔
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