Path: blob/main/crates/polars-arrow/src/bitmap/mutable.rs
6939 views
#![allow(unsafe_op_in_unsafe_fn)]1use std::hint::unreachable_unchecked;23use polars_error::{PolarsResult, polars_bail};4use polars_utils::vec::PushUnchecked;56use super::bitmask::BitMask;7use super::utils::{BitChunk, BitChunks, BitChunksExactMut, BitmapIter, count_zeros, fmt};8use super::{Bitmap, intersects_with_mut};9use crate::bitmap::utils::{get_bit_unchecked, merge_reversed, set_bit_in_byte};10use crate::storage::SharedStorage;11use crate::trusted_len::TrustedLen;1213/// A container of booleans. [`MutableBitmap`] is semantically equivalent14/// to [`Vec<bool>`].15///16/// The two main differences against [`Vec<bool>`] is that each element stored as a single bit,17/// thereby:18/// * it uses 8x less memory19/// * it cannot be represented as `&[bool]` (i.e. no pointer arithmetics).20///21/// A [`MutableBitmap`] can be converted to a [`Bitmap`] at `O(1)`.22/// # Examples23/// ```24/// use polars_arrow::bitmap::MutableBitmap;25///26/// let bitmap = MutableBitmap::from([true, false, true]);27/// assert_eq!(bitmap.iter().collect::<Vec<_>>(), vec![true, false, true]);28///29/// // creation directly from bytes30/// let mut bitmap = MutableBitmap::try_new(vec![0b00001101], 5).unwrap();31/// // note: the first bit is the left-most of the first byte32/// assert_eq!(bitmap.iter().collect::<Vec<_>>(), vec![true, false, true, true, false]);33/// // we can also get the slice:34/// assert_eq!(bitmap.as_slice(), [0b00001101u8].as_ref());35/// // debug helps :)36/// assert_eq!(format!("{:?}", bitmap), "Bitmap { len: 5, offset: 0, bytes: [0b___01101] }");37///38/// // It supports mutation in place39/// bitmap.set(0, false);40/// assert_eq!(format!("{:?}", bitmap), "Bitmap { len: 5, offset: 0, bytes: [0b___01100] }");41/// // and `O(1)` random access42/// assert_eq!(bitmap.get(0), false);43/// ```44/// # Implementation45/// This container is internally a [`Vec<u8>`].46#[derive(Clone)]47pub struct MutableBitmap {48buffer: Vec<u8>,49// invariant: length.saturating_add(7) / 8 == buffer.len();50length: usize,51}5253impl std::fmt::Debug for MutableBitmap {54fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {55fmt(&self.buffer, 0, self.len(), f)56}57}5859impl PartialEq for MutableBitmap {60fn eq(&self, other: &Self) -> bool {61self.iter().eq(other.iter())62}63}6465impl MutableBitmap {66/// Initializes an empty [`MutableBitmap`].67#[inline]68pub fn new() -> Self {69Self {70buffer: Vec::new(),71length: 0,72}73}7475/// Initializes a new [`MutableBitmap`] from a [`Vec<u8>`] and a length.76/// # Errors77/// This function errors iff `length > bytes.len() * 8`78#[inline]79pub fn try_new(mut bytes: Vec<u8>, length: usize) -> PolarsResult<Self> {80if length > bytes.len().saturating_mul(8) {81polars_bail!(InvalidOperation:82"The length of the bitmap ({}) must be `<=` to the number of bytes times 8 ({})",83length,84bytes.len().saturating_mul(8)85)86}8788// Ensure invariant holds.89let min_byte_length_needed = length.div_ceil(8);90bytes.drain(min_byte_length_needed..);91Ok(Self {92length,93buffer: bytes,94})95}9697/// Initializes a [`MutableBitmap`] from a [`Vec<u8>`] and a length.98/// This function is `O(1)`.99/// # Panic100/// Panics iff the length is larger than the length of the buffer times 8.101#[inline]102pub fn from_vec(buffer: Vec<u8>, length: usize) -> Self {103Self::try_new(buffer, length).unwrap()104}105106/// Initializes a pre-allocated [`MutableBitmap`] with capacity for `capacity` bits.107#[inline]108pub fn with_capacity(capacity: usize) -> Self {109Self {110buffer: Vec::with_capacity(capacity.saturating_add(7) / 8),111length: 0,112}113}114115/// Pushes a new bit to the [`MutableBitmap`], re-sizing it if necessary.116#[inline]117pub fn push(&mut self, value: bool) {118if self.length.is_multiple_of(8) {119self.buffer.push(0);120}121let byte = unsafe { self.buffer.last_mut().unwrap_unchecked() };122*byte = set_bit_in_byte(*byte, self.length % 8, value);123self.length += 1;124}125126/// Pop the last bit from the [`MutableBitmap`].127/// Note if the [`MutableBitmap`] is empty, this method will return None.128#[inline]129pub fn pop(&mut self) -> Option<bool> {130if self.is_empty() {131return None;132}133134self.length -= 1;135let value = unsafe { self.get_unchecked(self.length) };136if self.length.is_multiple_of(8) {137self.buffer.pop();138}139Some(value)140}141142/// Returns whether the position `index` is set.143/// # Panics144/// Panics iff `index >= self.len()`.145#[inline]146pub fn get(&self, index: usize) -> bool {147assert!(index < self.len());148unsafe { self.get_unchecked(index) }149}150151/// Returns whether the position `index` is set.152///153/// # Safety154/// The caller must ensure `index < self.len()`.155#[inline]156pub unsafe fn get_unchecked(&self, index: usize) -> bool {157get_bit_unchecked(&self.buffer, index)158}159160/// Sets the position `index` to `value`161/// # Panics162/// Panics iff `index >= self.len()`.163#[inline]164pub fn set(&mut self, index: usize, value: bool) {165assert!(index < self.len());166unsafe {167self.set_unchecked(index, value);168}169}170171/// Sets the position `index` to the OR of its original value and `value`.172///173/// # Safety174/// It's undefined behavior if index >= self.len().175#[inline]176pub unsafe fn or_pos_unchecked(&mut self, index: usize, value: bool) {177*self.buffer.get_unchecked_mut(index / 8) |= (value as u8) << (index % 8);178}179180/// Sets the position `index` to the AND of its original value and `value`.181///182/// # Safety183/// It's undefined behavior if index >= self.len().184#[inline]185pub unsafe fn and_pos_unchecked(&mut self, index: usize, value: bool) {186*self.buffer.get_unchecked_mut(index / 8) &=187(0xFE | u8::from(value)).rotate_left(index as u32);188}189190/// Sets the position `index` to the XOR of its original value and `value`.191///192/// # Safety193/// It's undefined behavior if index >= self.len().194#[inline]195pub unsafe fn xor_pos_unchecked(&mut self, index: usize, value: bool) {196*self.buffer.get_unchecked_mut(index / 8) ^= (value as u8) << (index % 8);197}198199/// constructs a new iterator over the bits of [`MutableBitmap`].200pub fn iter(&self) -> BitmapIter<'_> {201BitmapIter::new(&self.buffer, 0, self.length)202}203204/// Empties the [`MutableBitmap`].205#[inline]206pub fn clear(&mut self) {207self.length = 0;208self.buffer.clear();209}210211/// Extends [`MutableBitmap`] by `additional` values of constant `value`.212/// # Implementation213/// This function is an order of magnitude faster than pushing element by element.214#[inline]215pub fn extend_constant(&mut self, additional: usize, value: bool) {216if additional == 0 {217return;218}219220if value {221self.extend_set(additional)222} else {223self.extend_unset(additional)224}225}226227/// Resizes the [`MutableBitmap`] to the specified length, inserting value228/// if the length is bigger than the current length.229pub fn resize(&mut self, length: usize, value: bool) {230if let Some(additional) = length.checked_sub(self.len()) {231self.extend_constant(additional, value);232} else {233self.buffer.truncate(length.saturating_add(7) / 8);234self.length = length;235}236}237238/// Initializes a zeroed [`MutableBitmap`].239#[inline]240pub fn from_len_zeroed(length: usize) -> Self {241Self {242buffer: vec![0; length.saturating_add(7) / 8],243length,244}245}246247/// Initializes a [`MutableBitmap`] with all values set to valid/ true.248#[inline]249pub fn from_len_set(length: usize) -> Self {250Self {251buffer: vec![u8::MAX; length.saturating_add(7) / 8],252length,253}254}255256/// Reserves `additional` bits in the [`MutableBitmap`], potentially re-allocating its buffer.257#[inline(always)]258pub fn reserve(&mut self, additional: usize) {259self.buffer260.reserve((self.length + additional).saturating_add(7) / 8 - self.buffer.len())261}262263/// Returns the capacity of [`MutableBitmap`] in number of bits.264#[inline]265pub fn capacity(&self) -> usize {266self.buffer.capacity() * 8267}268269/// Pushes a new bit to the [`MutableBitmap`]270///271/// # Safety272/// The caller must ensure that the [`MutableBitmap`] has sufficient capacity.273#[inline]274pub unsafe fn push_unchecked(&mut self, value: bool) {275if self.length.is_multiple_of(8) {276self.buffer.push_unchecked(0);277}278let byte = self.buffer.last_mut().unwrap_unchecked();279*byte = set_bit_in_byte(*byte, self.length % 8, value);280self.length += 1;281}282283/// Returns the number of unset bits on this [`MutableBitmap`].284///285/// Guaranteed to be `<= self.len()`.286/// # Implementation287/// This function is `O(N)`288pub fn unset_bits(&self) -> usize {289count_zeros(&self.buffer, 0, self.length)290}291292/// Returns the number of set bits on this [`MutableBitmap`].293///294/// Guaranteed to be `<= self.len()`.295/// # Implementation296/// This function is `O(N)`297pub fn set_bits(&self) -> usize {298self.length - self.unset_bits()299}300301/// Returns the length of the [`MutableBitmap`].302#[inline]303pub fn len(&self) -> usize {304self.length305}306307/// Returns whether [`MutableBitmap`] is empty.308#[inline]309pub fn is_empty(&self) -> bool {310self.len() == 0311}312313/// # Safety314/// The caller must ensure that the [`MutableBitmap`] was properly initialized up to `len`.315#[inline]316pub(crate) unsafe fn set_len(&mut self, len: usize) {317self.buffer.set_len(len.saturating_add(7) / 8);318self.length = len;319}320321fn extend_set(&mut self, mut additional: usize) {322let offset = self.length % 8;323let added = if offset != 0 {324// offset != 0 => at least one byte in the buffer325let last_index = self.buffer.len() - 1;326let last = &mut self.buffer[last_index];327328let remaining = 0b11111111u8;329let remaining = remaining >> 8usize.saturating_sub(additional);330let remaining = remaining << offset;331*last |= remaining;332std::cmp::min(additional, 8 - offset)333} else {3340335};336self.length += added;337additional = additional.saturating_sub(added);338if additional > 0 {339debug_assert_eq!(self.length % 8, 0);340let existing = self.length.saturating_add(7) / 8;341let required = (self.length + additional).saturating_add(7) / 8;342// add remaining as full bytes343self.buffer344.extend(std::iter::repeat_n(0b11111111u8, required - existing));345self.length += additional;346}347}348349fn extend_unset(&mut self, mut additional: usize) {350let offset = self.length % 8;351let added = if offset != 0 {352// offset != 0 => at least one byte in the buffer353let last_index = self.buffer.len() - 1;354let last = &mut self.buffer[last_index];355*last &= 0b11111111u8 >> (8 - offset); // unset them356std::cmp::min(additional, 8 - offset)357} else {3580359};360self.length += added;361additional = additional.saturating_sub(added);362if additional > 0 {363debug_assert_eq!(self.length % 8, 0);364self.buffer365.resize((self.length + additional).saturating_add(7) / 8, 0);366self.length += additional;367}368}369370/// Sets the position `index` to `value`371///372/// # Safety373/// Caller must ensure that `index < self.len()`374#[inline]375pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) {376debug_assert!(index < self.len());377let byte = self.buffer.get_unchecked_mut(index / 8);378*byte = set_bit_in_byte(*byte, index % 8, value);379}380381/// Shrinks the capacity of the [`MutableBitmap`] to fit its current length.382pub fn shrink_to_fit(&mut self) {383self.buffer.shrink_to_fit();384}385386/// Returns an iterator over bits in bit chunks [`BitChunk`].387///388/// This iterator is useful to operate over multiple bits via e.g. bitwise.389pub fn chunks<T: BitChunk>(&self) -> BitChunks<'_, T> {390BitChunks::new(&self.buffer, 0, self.length)391}392393/// Returns an iterator over mutable slices, [`BitChunksExactMut`]394pub(crate) fn bitchunks_exact_mut<T: BitChunk>(&mut self) -> BitChunksExactMut<'_, T> {395BitChunksExactMut::new(&mut self.buffer, self.length)396}397398pub fn intersects_with(&self, other: &Self) -> bool {399intersects_with_mut(self, other)400}401402pub fn freeze(self) -> Bitmap {403self.into()404}405}406407impl From<MutableBitmap> for Bitmap {408#[inline]409fn from(buffer: MutableBitmap) -> Self {410Bitmap::try_new(buffer.buffer, buffer.length).unwrap()411}412}413414impl From<MutableBitmap> for Option<Bitmap> {415#[inline]416fn from(buffer: MutableBitmap) -> Self {417let unset_bits = buffer.unset_bits();418if unset_bits > 0 {419// SAFETY: invariants of the `MutableBitmap` equal that of `Bitmap`.420let bitmap = unsafe {421Bitmap::from_inner_unchecked(422SharedStorage::from_vec(buffer.buffer),4230,424buffer.length,425Some(unset_bits),426)427};428Some(bitmap)429} else {430None431}432}433}434435impl<P: AsRef<[bool]>> From<P> for MutableBitmap {436#[inline]437fn from(slice: P) -> Self {438MutableBitmap::from_trusted_len_iter(slice.as_ref().iter().copied())439}440}441442impl Extend<bool> for MutableBitmap {443fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T) {444let mut iterator = iter.into_iter();445446let mut buffer = std::mem::take(&mut self.buffer);447let mut length = std::mem::take(&mut self.length);448449let byte_capacity: usize = iterator.size_hint().0.saturating_add(7) / 8;450buffer.reserve(byte_capacity);451452loop {453let mut exhausted = false;454let mut byte_accum: u8 = 0;455let mut mask: u8 = 1;456457//collect (up to) 8 bits into a byte458while mask != 0 {459if let Some(value) = iterator.next() {460length += 1;461byte_accum |= match value {462true => mask,463false => 0,464};465mask <<= 1;466} else {467exhausted = true;468break;469}470}471472// break if the iterator was exhausted before it provided a bool for this byte473if exhausted && mask == 1 {474break;475}476477//ensure we have capacity to write the byte478if buffer.len() == buffer.capacity() {479//no capacity for new byte, allocate 1 byte more (plus however many more the iterator advertises)480let additional_byte_capacity = 1usize.saturating_add(481iterator.size_hint().0.saturating_add(7) / 8, //convert bit count to byte count, rounding up482);483buffer.reserve(additional_byte_capacity)484}485486// Soundness: capacity was allocated above487buffer.push(byte_accum);488if exhausted {489break;490}491}492493self.buffer = buffer;494self.length = length;495}496}497498impl FromIterator<bool> for MutableBitmap {499fn from_iter<I>(iter: I) -> Self500where501I: IntoIterator<Item = bool>,502{503let mut bm = Self::new();504bm.extend(iter);505bm506}507}508509// [7, 6, 5, 4, 3, 2, 1, 0], [15, 14, 13, 12, 11, 10, 9, 8]510// [00000001_00000000_00000000_00000000_...] // u64511/// # Safety512/// The iterator must be trustedLen and its len must be least `len`.513#[inline]514unsafe fn get_chunk_unchecked(iterator: &mut impl Iterator<Item = bool>) -> u64 {515let mut byte = 0u64;516let mut mask;517for i in 0..8 {518mask = 1u64 << (8 * i);519for _ in 0..8 {520let value = match iterator.next() {521Some(value) => value,522None => unsafe { unreachable_unchecked() },523};524525byte |= match value {526true => mask,527false => 0,528};529mask <<= 1;530}531}532byte533}534535/// # Safety536/// The iterator must be trustedLen and its len must be least `len`.537#[inline]538unsafe fn get_byte_unchecked(len: usize, iterator: &mut impl Iterator<Item = bool>) -> u8 {539let mut byte_accum: u8 = 0;540let mut mask: u8 = 1;541for _ in 0..len {542let value = match iterator.next() {543Some(value) => value,544None => unsafe { unreachable_unchecked() },545};546547byte_accum |= match value {548true => mask,549false => 0,550};551mask <<= 1;552}553byte_accum554}555556/// Extends the [`Vec<u8>`] from `iterator`557/// # Safety558/// The iterator MUST be [`TrustedLen`].559#[inline]560unsafe fn extend_aligned_trusted_iter_unchecked(561buffer: &mut Vec<u8>,562mut iterator: impl Iterator<Item = bool>,563) -> usize {564let additional_bits = iterator.size_hint().1.unwrap();565let chunks = additional_bits / 64;566let remainder = additional_bits % 64;567568let additional = additional_bits.div_ceil(8);569assert_eq!(570additional,571// a hint of how the following calculation will be done572chunks * 8 + remainder / 8 + !remainder.is_multiple_of(8) as usize573);574buffer.reserve(additional);575576// chunks of 64 bits577for _ in 0..chunks {578let chunk = get_chunk_unchecked(&mut iterator);579buffer.extend_from_slice(&chunk.to_le_bytes());580}581582// remaining complete bytes583for _ in 0..(remainder / 8) {584let byte = unsafe { get_byte_unchecked(8, &mut iterator) };585buffer.push(byte)586}587588// remaining bits589let remainder = remainder % 8;590if remainder > 0 {591let byte = unsafe { get_byte_unchecked(remainder, &mut iterator) };592buffer.push(byte)593}594additional_bits595}596597impl MutableBitmap {598/// Extends `self` from a [`TrustedLen`] iterator.599#[inline]600pub fn extend_from_trusted_len_iter<I: TrustedLen<Item = bool>>(&mut self, iterator: I) {601// SAFETY: I: TrustedLen602unsafe { self.extend_from_trusted_len_iter_unchecked(iterator) }603}604605/// Extends `self` from an iterator of trusted len.606///607/// # Safety608/// The caller must guarantee that the iterator has a trusted len.609#[inline]610pub unsafe fn extend_from_trusted_len_iter_unchecked<I: Iterator<Item = bool>>(611&mut self,612mut iterator: I,613) {614// the length of the iterator throughout this function.615let mut length = iterator.size_hint().1.unwrap();616617let bit_offset = self.length % 8;618619if length < 8 - bit_offset {620if bit_offset == 0 {621self.buffer.push(0);622}623// the iterator will not fill the last byte624let byte = self.buffer.last_mut().unwrap();625let mut i = bit_offset;626for value in iterator {627*byte = set_bit_in_byte(*byte, i, value);628i += 1;629}630self.length += length;631return;632}633634// at this point we know that length will hit a byte boundary and thus635// increase the buffer.636637if bit_offset != 0 {638// we are in the middle of a byte; lets finish it639let byte = self.buffer.last_mut().unwrap();640(bit_offset..8).for_each(|i| {641*byte = set_bit_in_byte(*byte, i, iterator.next().unwrap());642});643self.length += 8 - bit_offset;644length -= 8 - bit_offset;645}646647// everything is aligned; proceed with the bulk operation648debug_assert_eq!(self.length % 8, 0);649650unsafe { extend_aligned_trusted_iter_unchecked(&mut self.buffer, iterator) };651self.length += length;652}653654/// Creates a new [`MutableBitmap`] from an iterator of booleans.655///656/// # Safety657/// The iterator must report an accurate length.658#[inline]659pub unsafe fn from_trusted_len_iter_unchecked<I>(iterator: I) -> Self660where661I: Iterator<Item = bool>,662{663let mut buffer = Vec::<u8>::new();664665let length = extend_aligned_trusted_iter_unchecked(&mut buffer, iterator);666667Self { buffer, length }668}669670/// Creates a new [`MutableBitmap`] from an iterator of booleans.671#[inline]672pub fn from_trusted_len_iter<I>(iterator: I) -> Self673where674I: TrustedLen<Item = bool>,675{676// SAFETY: Iterator is `TrustedLen`677unsafe { Self::from_trusted_len_iter_unchecked(iterator) }678}679680/// Creates a new [`MutableBitmap`] from an iterator of booleans.681pub fn try_from_trusted_len_iter<E, I>(iterator: I) -> std::result::Result<Self, E>682where683I: TrustedLen<Item = std::result::Result<bool, E>>,684{685unsafe { Self::try_from_trusted_len_iter_unchecked(iterator) }686}687688/// Creates a new [`MutableBitmap`] from an falible iterator of booleans.689///690/// # Safety691/// The caller must guarantee that the iterator is `TrustedLen`.692pub unsafe fn try_from_trusted_len_iter_unchecked<E, I>(693mut iterator: I,694) -> std::result::Result<Self, E>695where696I: Iterator<Item = std::result::Result<bool, E>>,697{698let length = iterator.size_hint().1.unwrap();699700let mut buffer = vec![0u8; length.div_ceil(8)];701702let chunks = length / 8;703let reminder = length % 8;704705let data = buffer.as_mut_slice();706data[..chunks].iter_mut().try_for_each(|byte| {707(0..8).try_for_each(|i| {708*byte = set_bit_in_byte(*byte, i, iterator.next().unwrap()?);709Ok(())710})711})?;712713if reminder != 0 {714let last = &mut data[chunks];715iterator.enumerate().try_for_each(|(i, value)| {716*last = set_bit_in_byte(*last, i, value?);717Ok(())718})?;719}720721Ok(Self { buffer, length })722}723724fn extend_unaligned(&mut self, slice: &[u8], offset: usize, length: usize) {725// e.g.726// [a, b, --101010] <- to be extended727// [00111111, 11010101] <- to extend728// [a, b, 11101010, --001111] expected result729730let aligned_offset = offset / 8;731let own_offset = self.length % 8;732debug_assert_eq!(offset % 8, 0); // assumed invariant733debug_assert!(own_offset != 0); // assumed invariant734735let bytes_len = length.saturating_add(7) / 8;736let items = &slice[aligned_offset..aligned_offset + bytes_len];737// self has some offset => we need to shift all `items`, and merge the first738let buffer = self.buffer.as_mut_slice();739let last = &mut buffer[buffer.len() - 1];740741// --101010 | 00111111 << 6 = 11101010742// erase previous743*last &= 0b11111111u8 >> (8 - own_offset); // unset before setting744*last |= items[0] << own_offset;745746if length + own_offset <= 8 {747// no new bytes needed748self.length += length;749return;750}751let additional = length - (8 - own_offset);752753let remaining = [items[items.len() - 1], 0];754let bytes = items755.windows(2)756.chain(std::iter::once(remaining.as_ref()))757.map(|w| merge_reversed(w[0], w[1], 8 - own_offset))758.take(additional.saturating_add(7) / 8);759self.buffer.extend(bytes);760761self.length += length;762}763764fn extend_aligned(&mut self, slice: &[u8], offset: usize, length: usize) {765let aligned_offset = offset / 8;766let bytes_len = length.saturating_add(7) / 8;767let items = &slice[aligned_offset..aligned_offset + bytes_len];768self.buffer.extend_from_slice(items);769self.length += length;770}771772/// Extends the [`MutableBitmap`] from a slice of bytes with optional offset.773/// This is the fastest way to extend a [`MutableBitmap`].774/// # Implementation775/// When both [`MutableBitmap`]'s length and `offset` are both multiples of 8,776/// this function performs a memcopy. Else, it first aligns bit by bit and then performs a memcopy.777///778/// # Safety779/// Caller must ensure `offset + length <= slice.len() * 8`780#[inline]781pub unsafe fn extend_from_slice_unchecked(782&mut self,783slice: &[u8],784offset: usize,785length: usize,786) {787if length == 0 {788return;789};790let is_aligned = self.length.is_multiple_of(8);791let other_is_aligned = offset.is_multiple_of(8);792match (is_aligned, other_is_aligned) {793(true, true) => self.extend_aligned(slice, offset, length),794(false, true) => self.extend_unaligned(slice, offset, length),795// todo: further optimize the other branches.796_ => self.extend_from_trusted_len_iter(BitmapIter::new(slice, offset, length)),797}798// internal invariant:799debug_assert_eq!(self.length.saturating_add(7) / 8, self.buffer.len());800}801802/// Extends the [`MutableBitmap`] from a slice of bytes with optional offset.803/// This is the fastest way to extend a [`MutableBitmap`].804/// # Implementation805/// When both [`MutableBitmap`]'s length and `offset` are both multiples of 8,806/// this function performs a memcopy. Else, it first aligns bit by bit and then performs a memcopy.807#[inline]808pub fn extend_from_slice(&mut self, slice: &[u8], offset: usize, length: usize) {809assert!(offset + length <= slice.len() * 8);810// SAFETY: invariant is asserted811unsafe { self.extend_from_slice_unchecked(slice, offset, length) }812}813814#[inline]815pub fn extend_from_bitmask(&mut self, bitmask: BitMask<'_>) {816let (slice, offset, length) = bitmask.inner();817self.extend_from_slice(slice, offset, length)818}819820/// Extends the [`MutableBitmap`] from a [`Bitmap`].821#[inline]822pub fn extend_from_bitmap(&mut self, bitmap: &Bitmap) {823let (slice, offset, length) = bitmap.as_slice();824// SAFETY: bitmap.as_slice adheres to the invariant825unsafe {826self.extend_from_slice_unchecked(slice, offset, length);827}828}829830/// Returns the slice of bytes of this [`MutableBitmap`].831/// Note that the last byte may not be fully used.832#[inline]833pub fn as_slice(&self) -> &[u8] {834let len = (self.length).saturating_add(7) / 8;835&self.buffer[..len]836}837838/// Returns the slice of bytes of this [`MutableBitmap`].839/// Note that the last byte may not be fully used.840#[inline]841pub fn as_mut_slice(&mut self) -> &mut [u8] {842let len = (self.length).saturating_add(7) / 8;843&mut self.buffer[..len]844}845}846847impl Default for MutableBitmap {848fn default() -> Self {849Self::new()850}851}852853impl<'a> IntoIterator for &'a MutableBitmap {854type Item = bool;855type IntoIter = BitmapIter<'a>;856857fn into_iter(self) -> Self::IntoIter {858BitmapIter::<'a>::new(&self.buffer, 0, self.length)859}860}861862863