Path: blob/main/crates/polars-parquet/src/parquet/encoding/hybrid_rle/bitmap.rs
7887 views
use std::io::Write;12const BIT_MASK: [u8; 8] = [1, 2, 4, 8, 16, 32, 64, 128];34/// Sets bit at position `i` in `byte`5#[inline]6pub fn set(byte: u8, i: usize) -> u8 {7byte | BIT_MASK[i]8}910/// An [`Iterator`] of bool that decodes a bitmap.11/// This is a specialization of [`super::super::bitpacked::Decoder`] for `num_bits == 1`.12#[derive(Debug)]13pub struct BitmapIter<'a> {14iter: std::slice::Iter<'a, u8>,15current_byte: &'a u8,16remaining: usize,17mask: u8,18}1920impl<'a> BitmapIter<'a> {21/// Returns a new [`BitmapIter`].22/// # Panics23/// This function panics iff `offset / 8 > slice.len()`24#[inline]25pub fn new(slice: &'a [u8], offset: usize, len: usize) -> Self {26let bytes = &slice[offset / 8..];2728let mut iter = bytes.iter();2930let current_byte = iter.next().unwrap_or(&0);3132Self {33iter,34mask: 1u8.rotate_left(offset as u32),35remaining: len,36current_byte,37}38}39}4041impl Iterator for BitmapIter<'_> {42type Item = bool;4344#[inline]45fn next(&mut self) -> Option<Self::Item> {46// easily predictable in branching47if self.remaining == 0 {48return None;49} else {50self.remaining -= 1;51}52let value = self.current_byte & self.mask != 0;53self.mask = self.mask.rotate_left(1);54if self.mask == 1 {55// reached a new byte => try to fetch it from the iterator56if let Some(v) = self.iter.next() {57self.current_byte = v58}59}60Some(value)61}6263#[inline]64fn size_hint(&self) -> (usize, Option<usize>) {65(self.remaining, Some(self.remaining))66}67}6869/// Writes an iterator of bools into writer, with LSB first.70pub fn encode_bool<W: Write, I: Iterator<Item = bool>>(71writer: &mut W,72mut iterator: I,73) -> std::io::Result<()> {74// the length of the iterator.75let length = iterator.size_hint().1.unwrap();7677let chunks = length / 8;78let reminder = length % 8;7980(0..chunks).try_for_each(|_| {81let mut byte = 0u8;82(0..8).for_each(|i| {83if iterator.next().unwrap() {84byte = set(byte, i)85}86});87writer.write_all(&[byte])88})?;8990if reminder != 0 {91let mut last = 0u8;92iterator.enumerate().for_each(|(i, value)| {93if value {94last = set(last, i)95}96});97writer.write_all(&[last])98} else {99Ok(())100}101}102103104