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

vortex-data / vortex / 16980200873

15 Aug 2025 12:53AM UTC coverage: 49.805%. First build
16980200873

Pull #2456

github

web-flow
Merge aff477380 into aaf3e36ad
Pull Request #2456: feat: basic BoolBuffer / BoolBufferMut

574 of 1074 new or added lines in 84 files covered. (53.45%)

20158 of 40474 relevant lines covered (49.8%)

238516.31 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 {
732✔
22
        let byte_len = (offset + len).div_ceil(8);
732✔
23
        assert!(
732✔
24
            byte_len <= buffer.len(),
732✔
NEW
25
            "Buffer {} too small for given length {len} and offset {offset}",
×
NEW
26
            buffer.len()
×
27
        );
28

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

33
        Self {
732✔
34
            buffer: buffer.slice(byte_offset..byte_len),
732✔
35
            len,
732✔
36
            bit_offset,
732✔
37
            remainder_len,
732✔
38
        }
732✔
39
    }
732✔
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 {
732✔
48
        if self.remainder_len == 0 {
732✔
49
            return 0;
372✔
50
        }
360✔
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..];
360✔
55
        let mut result_bits = remainder_bytes[0] as u64 >> self.bit_offset;
360✔
56
        for (i, &byte) in remainder_bytes[1..].iter().enumerate() {
1,710✔
57
            result_bits |= (byte as u64) << ((i + 1) * 8 - self.bit_offset);
1,710✔
58
        }
1,710✔
59

60
        result_bits & ((1 << self.remainder_len) - 1)
360✔
61
    }
732✔
62

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

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

79
    fn into_iter(self) -> Self::IntoIter {
366✔
80
        self.iter()
366✔
81
    }
366✔
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> {
668,598✔
99
        if self.index >= self.chunk_count {
668,598✔
100
            return None;
732✔
101
        }
667,866✔
102

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

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