use core::mem;
use core::ptr;
use core::slice;
use bun_alloc::AllocError;
#[inline(always)]
const fn bool_mask_usize(value: bool) -> usize {
if value { usize::MAX } else { 0 }
}
#[inline(always)]
const fn word_mask_bit(index: usize) -> usize {
1usize << ((index as u32) & (usize::BITS - 1)) }
#[inline(always)]
const fn word_mask_index(index: usize) -> usize {
index >> usize::BITS.trailing_zeros()
}
#[inline]
fn set_range_value_masks(masks: &mut [usize], range: Range, value: bool) {
const MASK_LEN: u32 = usize::BITS;
if range.start == range.end {
return;
}
let start_mask_index = word_mask_index(range.start);
let start_bit = (range.start as u32) & (MASK_LEN - 1);
let end_mask_index = word_mask_index(range.end);
let end_bit = (range.end as u32) & (MASK_LEN - 1);
if start_mask_index == end_mask_index {
let mut mask1 = bool_mask_usize(true) << start_bit;
let mut mask2 = bool_mask_usize(true) >> ((MASK_LEN - 1) - (end_bit - 1));
masks[start_mask_index] &= !(mask1 & mask2);
mask1 = bool_mask_usize(value) << start_bit;
mask2 = bool_mask_usize(value) >> ((MASK_LEN - 1) - (end_bit - 1));
masks[start_mask_index] |= mask1 & mask2;
} else {
let bulk_mask_index: usize;
if start_bit > 0 {
masks[start_mask_index] = (masks[start_mask_index]
& !(bool_mask_usize(true) << start_bit))
| (bool_mask_usize(value) << start_bit);
bulk_mask_index = start_mask_index + 1;
} else {
bulk_mask_index = start_mask_index;
}
for mask in &mut masks[bulk_mask_index..end_mask_index] {
*mask = bool_mask_usize(value);
}
if end_bit > 0 {
masks[end_mask_index] = (masks[end_mask_index] & (bool_mask_usize(true) << end_bit))
| (bool_mask_usize(value) >> ((MASK_LEN - 1) - (end_bit - 1)));
}
}
}
pub type StaticBitSet<const SIZE: usize> = IntegerBitSet<SIZE>;
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct IntegerBitSet<const SIZE: usize> {
pub mask: usize,
}
impl<const SIZE: usize> IntegerBitSet<SIZE> {
pub const BIT_LENGTH: usize = SIZE;
const FULL_MASK: usize = if SIZE as u32 >= usize::BITS {
usize::MAX
} else {
(1usize << (SIZE as u32)) - 1
};
pub const fn init_empty() -> Self {
Self { mask: 0 }
}
pub const fn init_full() -> Self {
Self {
mask: Self::FULL_MASK,
}
}
#[inline(always)]
pub const fn capacity(self) -> usize {
Self::BIT_LENGTH
}
pub fn is_set(self, index: usize) -> bool {
debug_assert!(index < Self::BIT_LENGTH);
(self.mask & Self::mask_bit(index)) != 0
}
pub const fn count(self) -> usize {
self.mask.count_ones() as usize
}
pub fn set_value(&mut self, index: usize, value: bool) {
debug_assert!(index < Self::BIT_LENGTH);
if SIZE == 0 {
return;
}
let bit = Self::mask_bit(index);
let new_bit = bit & bool_mask_usize(value);
self.mask = (self.mask & !bit) | new_bit;
}
pub fn set(&mut self, index: usize) {
debug_assert!(index < Self::BIT_LENGTH);
self.mask |= Self::mask_bit(index);
}
pub fn set_range_value(&mut self, range: Range, value: bool) {
debug_assert!(range.end <= Self::BIT_LENGTH);
debug_assert!(range.start <= range.end);
if range.start == range.end {
return;
}
if SIZE == 0 {
return;
}
let start_bit = u32::try_from(range.start).expect("int cast");
let mut mask = bool_mask_usize(true) << start_bit;
if range.end != Self::BIT_LENGTH {
let end_bit = u32::try_from(range.end).expect("int cast");
mask &= bool_mask_usize(true) >> (usize::BITS - end_bit);
}
mask &= Self::FULL_MASK;
self.mask &= !mask;
let mut mask = bool_mask_usize(value) << start_bit;
if range.end != Self::BIT_LENGTH {
let end_bit = u32::try_from(range.end).expect("int cast");
mask &= bool_mask_usize(value) >> (usize::BITS - end_bit);
}
mask &= Self::FULL_MASK;
self.mask |= mask;
}
pub fn unset(&mut self, index: usize) {
debug_assert!(index < Self::BIT_LENGTH);
if SIZE == 0 {
return;
}
self.mask &= !Self::mask_bit(index);
}
pub fn toggle(&mut self, index: usize) {
debug_assert!(index < Self::BIT_LENGTH);
self.mask ^= Self::mask_bit(index);
}
pub fn toggle_set(&mut self, toggles: Self) {
self.mask ^= toggles.mask;
}
pub fn toggle_all(&mut self) {
self.mask = !self.mask & Self::FULL_MASK;
}
pub fn set_union(&mut self, other: Self) {
self.mask |= other.mask;
}
pub fn set_intersection(&mut self, other: Self) {
self.mask &= other.mask;
}
pub fn find_first_set(self) -> Option<usize> {
let mask = self.mask;
if mask == 0 {
return None;
}
Some(mask.trailing_zeros() as usize)
}
pub fn find_first_unset(self) -> Option<usize> {
let mask = !self.mask & Self::FULL_MASK;
if mask == 0 {
return None;
}
Some(mask.trailing_zeros() as usize)
}
pub fn toggle_first_set(&mut self) -> Option<usize> {
let mask = self.mask;
if mask == 0 {
return None;
}
let index = mask.trailing_zeros() as usize;
self.mask = mask & (mask - 1);
Some(index)
}
pub fn eql(self, other: Self) -> bool {
Self::BIT_LENGTH == 0 || self.mask == other.mask
}
pub fn subset_of(self, other: Self) -> bool {
self.intersect_with(other).eql(self)
}
pub fn superset_of(self, other: Self) -> bool {
other.subset_of(self)
}
pub fn complement(self) -> Self {
let mut result = self;
result.toggle_all();
result
}
pub fn union_with(self, other: Self) -> Self {
let mut result = self;
result.set_union(other);
result
}
pub fn intersect_with(self, other: Self) -> Self {
let mut result = self;
result.set_intersection(other);
result
}
pub fn xor_with(self, other: Self) -> Self {
let mut result = self;
result.toggle_set(other);
result
}
pub fn difference_with(self, other: Self) -> Self {
let mut result = self;
result.set_intersection(other.complement());
result
}
pub fn iterator<const KIND_SET: bool, const DIR_FWD: bool>(
self,
) -> SingleWordIterator<SIZE, DIR_FWD> {
SingleWordIterator {
bits_remain: if KIND_SET {
self.mask
} else {
!self.mask & Self::FULL_MASK
},
}
}
#[inline]
pub fn iter_set(self) -> SingleWordIterator<SIZE, true> {
self.iterator::<true, true>()
}
#[inline(always)]
fn mask_bit(index: usize) -> usize {
if SIZE == 0 {
return 0;
}
1usize << index
}
}
pub struct SingleWordIterator<const SIZE: usize, const DIR_FWD: bool> {
bits_remain: usize,
}
impl<const SIZE: usize, const DIR_FWD: bool> SingleWordIterator<SIZE, DIR_FWD> {
pub fn next(&mut self) -> Option<usize> {
if self.bits_remain == 0 {
return None;
}
if DIR_FWD {
let next_index = self.bits_remain.trailing_zeros() as usize;
self.bits_remain &= self.bits_remain - 1;
Some(next_index)
} else {
let leading_zeroes = self.bits_remain.leading_zeros();
let top_bit = (usize::BITS - 1 - leading_zeroes) as usize;
self.bits_remain &= (1usize << top_bit) - 1;
Some(top_bit)
}
}
}
#[inline(always)]
pub const fn num_masks_for(bit_length: usize) -> usize {
bit_length.div_ceil(usize::BITS as usize)
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ArrayBitSet<const SIZE: usize, const NUM_MASKS: usize> {
pub masks: [usize; NUM_MASKS],
}
impl<const SIZE: usize, const NUM_MASKS: usize> ArrayBitSet<SIZE, NUM_MASKS> {
pub const BIT_LENGTH: usize = SIZE;
const MASK_LEN: u32 = usize::BITS;
const _ASSERT: () = assert!(
NUM_MASKS == num_masks_for(SIZE),
"ArrayBitSet: NUM_MASKS must equal num_masks_for(SIZE)"
);
const LAST_PAD_BITS: u32 = (Self::MASK_LEN as usize * NUM_MASKS - SIZE) as u32;
pub const LAST_ITEM_MASK: usize = usize::MAX >> Self::LAST_PAD_BITS;
pub const fn init_empty() -> Self {
Self {
masks: [0usize; NUM_MASKS],
}
}
pub const fn init_full() -> Self {
if NUM_MASKS == 0 {
Self {
masks: [0usize; NUM_MASKS],
}
} else {
let mut masks = [usize::MAX; NUM_MASKS];
masks[NUM_MASKS - 1] = Self::LAST_ITEM_MASK;
Self { masks }
}
}
#[inline(always)]
pub const fn capacity(&self) -> usize {
Self::BIT_LENGTH
}
pub fn is_set(&self, index: usize) -> bool {
debug_assert!(index < Self::BIT_LENGTH);
if NUM_MASKS == 0 {
return false; }
(self.masks[word_mask_index(index)] & word_mask_bit(index)) != 0
}
pub fn count(&self) -> usize {
let mut total: usize = 0;
for mask in self.masks {
total += mask.count_ones() as usize;
}
total
}
pub fn set_value(&mut self, index: usize, value: bool) {
debug_assert!(index < Self::BIT_LENGTH);
if NUM_MASKS == 0 {
return; }
let bit = word_mask_bit(index);
let mask_index = word_mask_index(index);
let new_bit = bit & bool_mask_usize(value);
self.masks[mask_index] = (self.masks[mask_index] & !bit) | new_bit;
}
pub fn set(&mut self, index: usize) {
debug_assert!(index < Self::BIT_LENGTH);
if NUM_MASKS == 0 {
return; }
self.masks[word_mask_index(index)] |= word_mask_bit(index);
}
pub fn set_range_value(&mut self, range: Range, value: bool) {
debug_assert!(range.end <= Self::BIT_LENGTH);
debug_assert!(range.start <= range.end);
if NUM_MASKS == 0 {
return;
}
set_range_value_masks(&mut self.masks, range, value);
}
pub fn unset(&mut self, index: usize) {
debug_assert!(index < Self::BIT_LENGTH);
if NUM_MASKS == 0 {
return; }
self.masks[word_mask_index(index)] &= !word_mask_bit(index);
}
pub fn toggle(&mut self, index: usize) {
debug_assert!(index < Self::BIT_LENGTH);
if NUM_MASKS == 0 {
return; }
self.masks[word_mask_index(index)] ^= word_mask_bit(index);
}
pub fn toggle_set(&mut self, toggles: &Self) {
debug_assert_eq!(self.masks.len(), toggles.masks.len());
for (mask, b) in self.masks.iter_mut().zip(toggles.masks.iter()) {
*mask ^= *b;
}
}
pub fn toggle_all(&mut self) {
for mask in self.masks.iter_mut() {
*mask = !*mask;
}
if NUM_MASKS > 0 {
self.masks[NUM_MASKS - 1] &= Self::LAST_ITEM_MASK;
}
}
pub fn set_all(&mut self, value: bool) {
self.masks.fill(if value { usize::MAX } else { 0 });
if NUM_MASKS > 0 {
self.masks[NUM_MASKS - 1] &= Self::LAST_ITEM_MASK;
}
}
pub fn set_union(&mut self, other: &Self) {
debug_assert_eq!(self.masks.len(), other.masks.len());
for (mask, alt) in self.masks.iter_mut().zip(other.masks.iter()) {
*mask |= *alt;
}
}
pub fn set_intersection(&mut self, other: &Self) {
debug_assert_eq!(self.masks.len(), other.masks.len());
for (mask, alt) in self.masks.iter_mut().zip(other.masks.iter()) {
*mask &= *alt;
}
}
pub fn find_first_set(&self) -> Option<usize> {
let mut offset: usize = 0;
let mask = 'brk: {
for mask in self.masks {
if mask != 0 {
break 'brk mask;
}
offset += Self::MASK_LEN as usize;
}
return None;
};
Some(offset + mask.trailing_zeros() as usize)
}
pub fn toggle_first_set(&mut self) -> Option<usize> {
let mut offset: usize = 0;
let mask = 'brk: {
for mask in self.masks.iter_mut() {
if *mask != 0 {
break 'brk mask;
}
offset += Self::MASK_LEN as usize;
}
return None;
};
let index = mask.trailing_zeros() as usize;
*mask &= *mask - 1;
Some(offset + index)
}
pub fn eql(&self, other: &Self) -> bool {
let mut i: usize = 0;
while i < NUM_MASKS {
if self.masks[i] != other.masks[i] {
return false;
}
i += 1;
}
true
}
pub fn subset_of(&self, other: &Self) -> bool {
self.intersect_with(other).eql(self)
}
pub fn superset_of(&self, other: &Self) -> bool {
other.subset_of(self)
}
pub fn complement(&self) -> Self {
let mut result = *self;
result.toggle_all();
result
}
pub fn union_with(&self, other: &Self) -> Self {
let mut result = *self;
result.set_union(other);
result
}
pub fn intersect_with(&self, other: &Self) -> Self {
let mut result = *self;
result.set_intersection(other);
result
}
pub fn has_intersection(&self, other: &Self) -> bool {
debug_assert_eq!(self.masks.len(), other.masks.len());
for (a, b) in self.masks.iter().zip(other.masks.iter()) {
if a & b != 0 {
return true;
}
}
false
}
pub fn xor_with(&self, other: &Self) -> Self {
let mut result = *self;
result.toggle_set(other);
result
}
pub fn difference_with(&self, other: &Self) -> Self {
let mut result = *self;
result.set_intersection(&other.complement());
result
}
pub fn iterator<const KIND_SET: bool, const DIR_FWD: bool>(
&self,
) -> BitSetIterator<'_, KIND_SET, DIR_FWD> {
BitSetIterator::init(&self.masks, Self::LAST_ITEM_MASK)
}
#[inline]
pub fn iter_set(&self) -> BitSetIterator<'_, true, true> {
self.iterator::<true, true>()
}
}
pub struct DynamicBitSetUnmanaged {
pub bit_length: usize,
pub masks: *mut usize,
}
const DYN_MASK_BITS: u32 = usize::BITS;
static EMPTY_MASKS_DATA: bun_core::RacyCell<[usize; 2]> = bun_core::RacyCell::new([0, 0]);
#[inline(always)]
fn empty_masks_ptr() -> *mut usize {
unsafe { EMPTY_MASKS_DATA.get().cast::<usize>().add(1) }
}
impl Default for DynamicBitSetUnmanaged {
fn default() -> Self {
Self {
bit_length: 0,
masks: empty_masks_ptr(),
}
}
}
impl Drop for DynamicBitSetUnmanaged {
fn drop(&mut self) {
self.deinit();
}
}
impl DynamicBitSetUnmanaged {
pub const EMPTY: fn() -> Self = Self::default;
#[inline(always)]
pub fn masks_slice(&self) -> &[usize] {
let n = Self::num_masks(self.bit_length);
unsafe { slice::from_raw_parts(self.masks, n) }
}
#[inline(always)]
pub fn masks_slice_mut(&mut self) -> &mut [usize] {
let n = Self::num_masks(self.bit_length);
unsafe { slice::from_raw_parts_mut(self.masks, n) }
}
#[inline(always)]
pub fn masks_ptr(&self) -> *mut usize {
self.masks
}
#[inline(always)]
fn zip_masks_raw(&mut self, other: &Self, mut f: impl FnMut(usize, usize) -> usize) {
let num_masks = Self::num_masks(self.bit_length);
let dst = self.masks;
let src = other.masks;
for i in 0..num_masks {
unsafe { *dst.add(i) = f(*dst.add(i), *src.add(i)) };
}
}
pub fn init_empty(bit_length: usize) -> Result<Self, AllocError> {
let mut this = Self::default();
this.resize(bit_length, false)?;
Ok(this)
}
pub fn init_full(bit_length: usize) -> Result<Self, AllocError> {
let mut this = Self::default();
this.resize(bit_length, true)?;
Ok(this)
}
pub fn resize(&mut self, new_len: usize, fill: bool) -> Result<(), AllocError> {
let old_len = self.bit_length;
let old_masks = Self::num_masks(old_len);
let new_masks = Self::num_masks(new_len);
let alloc_base = unsafe { self.masks.sub(1) };
let old_alloc_len = unsafe { *alloc_base };
if new_masks == 0 {
debug_assert!(new_len == 0);
unsafe { dyn_free(alloc_base, old_alloc_len) };
self.masks = empty_masks_ptr();
self.bit_length = 0;
return Ok(());
}
'realloc: {
if old_alloc_len == new_masks + 1 {
break 'realloc;
}
let new_alloc = match unsafe { dyn_realloc(alloc_base, old_alloc_len, new_masks + 1) } {
Ok(p) => p,
Err(err) => {
if new_masks + 1 > old_alloc_len {
return Err(err);
}
break 'realloc;
}
};
unsafe { *new_alloc = new_masks + 1 };
self.masks = unsafe { new_alloc.add(1) };
}
if new_len > old_len {
if fill && old_masks > 0 {
let old_padding_bits =
u32::try_from(old_masks * DYN_MASK_BITS as usize - old_len).expect("int cast");
let old_mask = usize::MAX >> old_padding_bits;
unsafe { *self.masks.add(old_masks - 1) |= !old_mask };
}
if new_masks > old_masks {
let fill_value = bool_mask_usize(fill);
unsafe {
slice::from_raw_parts_mut(self.masks.add(old_masks), new_masks - old_masks)
.fill(fill_value);
}
}
}
if new_len > 0 {
let padding_bits =
u32::try_from(new_masks * DYN_MASK_BITS as usize - new_len).expect("int cast");
let last_item_mask = usize::MAX >> padding_bits;
unsafe { *self.masks.add(new_masks - 1) &= last_item_mask };
}
self.bit_length = new_len;
Ok(())
}
pub fn deinit(&mut self) {
self.resize(0, false).expect("unreachable");
}
pub fn clone(&self) -> Result<Self, AllocError> {
let mut copy = Self::default();
copy.resize(self.bit_length, false)?;
copy.masks_slice_mut().copy_from_slice(self.masks_slice());
Ok(copy)
}
#[inline(always)]
pub fn capacity(&self) -> usize {
self.bit_length
}
pub fn is_set(&self, index: usize) -> bool {
debug_assert!(index < self.bit_length);
(self.masks_slice()[word_mask_index(index)] & word_mask_bit(index)) != 0
}
pub fn is_set_allow_out_of_bound(&self, index: usize, out_of_bounds: bool) -> bool {
if index >= self.bit_length {
return out_of_bounds;
}
(self.masks_slice()[word_mask_index(index)] & word_mask_bit(index)) != 0
}
pub fn bytes(&self) -> &[u8] {
bun_core::cast_slice::<usize, u8>(self.masks_slice())
}
pub fn count(&self) -> usize {
let mut total: usize = 0;
for mask in self.masks_slice() {
total += mask.count_ones() as usize;
}
total
}
pub fn has_intersection(&self, other: &Self) -> bool {
debug_assert_eq!(
Self::num_masks(self.bit_length),
Self::num_masks(other.bit_length)
);
for (a, b) in self.masks_slice().iter().zip(other.masks_slice()) {
if (a & b) != 0 {
return true;
}
}
false
}
pub fn set_value(&mut self, index: usize, value: bool) {
debug_assert!(index < self.bit_length);
let bit = word_mask_bit(index);
let mask_index = word_mask_index(index);
let new_bit = bit & bool_mask_usize(value);
let mask = &mut self.masks_slice_mut()[mask_index];
*mask = (*mask & !bit) | new_bit;
}
pub fn set(&mut self, index: usize) {
debug_assert!(index < self.bit_length);
self.masks_slice_mut()[word_mask_index(index)] |= word_mask_bit(index);
}
pub fn set_range_value(&mut self, range: Range, value: bool) {
debug_assert!(range.end <= self.bit_length);
debug_assert!(range.start <= range.end);
set_range_value_masks(self.masks_slice_mut(), range, value);
}
pub fn unset(&mut self, index: usize) {
debug_assert!(index < self.bit_length);
self.masks_slice_mut()[word_mask_index(index)] &= !word_mask_bit(index);
}
pub fn toggle(&mut self, index: usize) {
debug_assert!(index < self.bit_length);
self.masks_slice_mut()[word_mask_index(index)] ^= word_mask_bit(index);
}
pub fn toggle_set(&mut self, toggles: &Self) {
debug_assert!(toggles.bit_length == self.bit_length);
let bit_length = self.bit_length;
if bit_length == 0 {
return;
}
let num_masks = Self::num_masks(self.bit_length);
self.zip_masks_raw(toggles, |a, b| a ^ b);
let padding_bits =
u32::try_from(num_masks * DYN_MASK_BITS as usize - bit_length).expect("int cast");
let last_item_mask = usize::MAX >> padding_bits;
self.masks_slice_mut()[num_masks - 1] &= last_item_mask;
}
pub fn set_all(&mut self, value: bool) {
let bit_length = self.bit_length;
if bit_length == 0 {
return;
}
let num_masks = Self::num_masks(self.bit_length);
for mask in self.masks_slice_mut() {
*mask = bool_mask_usize(value);
}
let padding_bits =
u32::try_from(num_masks * DYN_MASK_BITS as usize - bit_length).expect("int cast");
let last_item_mask = usize::MAX >> padding_bits;
self.masks_slice_mut()[num_masks - 1] &= last_item_mask;
}
pub fn toggle_all(&mut self) {
let bit_length = self.bit_length;
if bit_length == 0 {
return;
}
let num_masks = Self::num_masks(self.bit_length);
for mask in self.masks_slice_mut() {
*mask = !*mask;
}
let padding_bits =
u32::try_from(num_masks * DYN_MASK_BITS as usize - bit_length).expect("int cast");
let last_item_mask = usize::MAX >> padding_bits;
self.masks_slice_mut()[num_masks - 1] &= last_item_mask;
}
pub fn copy_into(&mut self, other: &Self) {
let bit_length = self.bit_length;
if bit_length == 0 {
return;
}
let num_masks = Self::num_masks(self.bit_length);
self.zip_masks_raw(other, |_, b| b);
let padding_bits =
u32::try_from(num_masks * DYN_MASK_BITS as usize - bit_length).expect("int cast");
let last_item_mask = usize::MAX >> padding_bits;
self.masks_slice_mut()[num_masks - 1] &= last_item_mask;
}
pub fn set_union(&mut self, other: &Self) {
debug_assert!(other.bit_length == self.bit_length);
self.zip_masks_raw(other, |a, b| a | b);
}
pub fn set_intersection(&mut self, other: &Self) {
debug_assert!(other.bit_length == self.bit_length);
self.zip_masks_raw(other, |a, b| a & b);
}
pub fn set_exclude_two(&mut self, other: &Self, third: &Self) {
debug_assert!(other.bit_length == self.bit_length);
self.zip_masks_raw(other, |a, b| a & !b);
self.zip_masks_raw(third, |a, c| a & !c);
}
pub fn set_exclude(&mut self, other: &Self) {
debug_assert!(other.bit_length == self.bit_length);
self.zip_masks_raw(other, |a, b| a & !b);
}
pub fn find_first_set(&self) -> Option<usize> {
let mut offset: usize = 0;
for &mask in self.masks_slice() {
if mask != 0 {
return Some(offset + mask.trailing_zeros() as usize);
}
offset += DYN_MASK_BITS as usize;
}
None
}
pub fn toggle_first_set(&mut self) -> Option<usize> {
let mut offset: usize = 0;
for mask in self.masks_slice_mut() {
let m = *mask;
if m != 0 {
let index = m.trailing_zeros() as usize;
*mask = m & (m - 1);
return Some(offset + index);
}
offset += DYN_MASK_BITS as usize;
}
None
}
pub fn eql(&self, other: &Self) -> bool {
if self.bit_length != other.bit_length {
return false;
}
self.masks_slice() == other.masks_slice()
}
pub fn subset_of(&self, other: &Self) -> bool {
if self.bit_length != other.bit_length {
return false;
}
for (&a, &b) in self.masks_slice().iter().zip(other.masks_slice()) {
if a & b != a {
return false;
}
}
true
}
pub fn superset_of(&self, other: &Self) -> bool {
if self.bit_length != other.bit_length {
return false;
}
for (&a, &b) in self.masks_slice().iter().zip(other.masks_slice()) {
if a & b != b {
return false;
}
}
true
}
pub fn iterator<const KIND_SET: bool, const DIR_FWD: bool>(
&self,
) -> BitSetIterator<'_, KIND_SET, DIR_FWD> {
let num_masks = Self::num_masks(self.bit_length);
let padding_bits =
u32::try_from(num_masks * DYN_MASK_BITS as usize - self.bit_length).expect("int cast");
let last_item_mask = usize::MAX >> padding_bits;
BitSetIterator::init(self.masks_slice(), last_item_mask)
}
#[inline(always)]
pub const fn num_masks(bit_length: usize) -> usize {
num_masks_for(bit_length)
}
}
pub struct DynamicBitSetList {
buf: ptr::NonNull<usize>,
buf_len: usize,
pub n: usize,
pub bit_length: usize,
}
impl DynamicBitSetList {
pub fn init_empty(n: usize, bit_length: usize) -> Result<Self, AllocError> {
let masks = DynamicBitSetUnmanaged::num_masks(bit_length);
let single_bitset_buf_size = masks + 1;
let buf_len = single_bitset_buf_size * n;
if buf_len == 0 {
return Ok(Self {
buf: ptr::NonNull::dangling(),
buf_len: 0,
n,
bit_length,
});
}
let layout = core::alloc::Layout::array::<usize>(buf_len).map_err(|_| AllocError)?;
let raw = unsafe { std::alloc::alloc_zeroed(layout) };
let buf = ptr::NonNull::new(raw).ok_or(AllocError)?.cast::<usize>();
for i in 0..n {
unsafe { *buf.as_ptr().add(i * single_bitset_buf_size) = single_bitset_buf_size };
}
Ok(Self {
buf,
buf_len,
n,
bit_length,
})
}
pub fn at(&self, i: usize) -> core::mem::ManuallyDrop<DynamicBitSetUnmanaged> {
debug_assert!(i < self.n, "DynamicBitSetList::at index out of bounds");
let num_masks = DynamicBitSetUnmanaged::num_masks(self.bit_length);
let single_bitset_buf_size = num_masks + 1;
let offset = single_bitset_buf_size * i;
core::mem::ManuallyDrop::new(DynamicBitSetUnmanaged {
bit_length: self.bit_length,
masks: unsafe { self.buf.as_ptr().add(offset).add(1) },
})
}
pub fn set(&self, i: usize, j: usize) {
let mut bitset = self.at(i);
bitset.set(j);
}
pub fn set_union(&self, i: usize, other: &DynamicBitSetUnmanaged) {
let mut bitset = self.at(i);
bitset.set_union(other);
}
}
impl Drop for DynamicBitSetList {
fn drop(&mut self) {
if self.buf_len == 0 {
return;
}
let layout = core::alloc::Layout::array::<usize>(self.buf_len).expect("unreachable");
unsafe { std::alloc::dealloc(self.buf.as_ptr().cast(), layout) };
}
}
unsafe impl Send for DynamicBitSetList {}
unsafe fn dyn_free(base: *mut usize, len: usize) {
if len == 0 {
return;
}
let layout = core::alloc::Layout::array::<usize>(len).expect("unreachable");
unsafe { std::alloc::dealloc(base.cast(), layout) };
}
unsafe fn dyn_realloc(
base: *mut usize,
old_len: usize,
new_len: usize,
) -> Result<*mut usize, AllocError> {
let new_layout = core::alloc::Layout::array::<usize>(new_len).map_err(|_| AllocError)?;
if old_len == 0 {
let p = unsafe { std::alloc::alloc(new_layout) };
if p.is_null() {
return Err(AllocError);
}
return Ok(p.cast());
}
let old_layout = core::alloc::Layout::array::<usize>(old_len).expect("unreachable");
let p = unsafe { std::alloc::realloc(base.cast(), old_layout, new_layout.size()) };
if p.is_null() {
return Err(AllocError);
}
Ok(p.cast())
}
pub(crate) const AUTO_STATIC_BITS: usize = mem::size_of::<DynamicBitSetUnmanaged>() * 8 - 1;
pub(crate) type AutoBitSetStatic =
ArrayBitSet<AUTO_STATIC_BITS, { num_masks_for(AUTO_STATIC_BITS) }>;
pub enum AutoBitSet {
Static(AutoBitSetStatic),
Dynamic(DynamicBitSetUnmanaged),
}
macro_rules! auto_forward {
($self:expr, |$b:ident| $body:expr) => {
match $self {
AutoBitSet::Static($b) => $body,
AutoBitSet::Dynamic($b) => $body,
}
};
}
impl AutoBitSet {
#[inline(always)]
pub fn needs_dynamic(bit_length: usize) -> bool {
bit_length > AutoBitSetStatic::BIT_LENGTH
}
pub fn init_empty(bit_length: usize) -> Result<AutoBitSet, AllocError> {
if bit_length <= AutoBitSetStatic::BIT_LENGTH {
Ok(AutoBitSet::Static(AutoBitSetStatic::init_empty()))
} else {
Ok(AutoBitSet::Dynamic(DynamicBitSetUnmanaged::init_empty(
bit_length,
)?))
}
}
pub fn is_set(&self, index: usize) -> bool {
auto_forward!(self, |b| b.is_set(index))
}
pub fn has_intersection(&self, other: &AutoBitSet) -> bool {
match (self, other) {
(AutoBitSet::Static(a), AutoBitSet::Static(b)) => a.has_intersection(b),
(AutoBitSet::Dynamic(a), AutoBitSet::Dynamic(b)) => a.has_intersection(b),
_ => false,
}
}
pub fn clone(&self) -> Result<AutoBitSet, AllocError> {
match self {
AutoBitSet::Static(s) => Ok(AutoBitSet::Static(*s)),
AutoBitSet::Dynamic(d) => Ok(AutoBitSet::Dynamic(d.clone()?)),
}
}
pub fn set(&mut self, index: usize) {
auto_forward!(self, |b| b.set(index))
}
pub fn unset(&mut self, index: usize) {
auto_forward!(self, |b| b.unset(index))
}
pub fn set_union(&mut self, other: &AutoBitSet) {
match (self, other) {
(AutoBitSet::Static(a), AutoBitSet::Static(b)) => a.set_union(b),
(AutoBitSet::Dynamic(a), AutoBitSet::Dynamic(b)) => a.set_union(b),
_ => unreachable!("AutoBitSet::set_union: mismatched bit lengths"),
}
}
pub fn set_intersection(&mut self, other: &AutoBitSet) {
match (self, other) {
(AutoBitSet::Static(a), AutoBitSet::Static(b)) => a.set_intersection(b),
(AutoBitSet::Dynamic(a), AutoBitSet::Dynamic(b)) => a.set_intersection(b),
_ => unreachable!("AutoBitSet::set_intersection: mismatched bit lengths"),
}
}
pub fn subset_of(&self, other: &AutoBitSet) -> bool {
match (self, other) {
(AutoBitSet::Static(a), AutoBitSet::Static(b)) => a.subset_of(b),
(AutoBitSet::Dynamic(a), AutoBitSet::Dynamic(b)) => a.subset_of(b),
_ => unreachable!("AutoBitSet::subset_of: mismatched bit lengths"),
}
}
pub fn raw_bytes(&self) -> &[u8] {
match self {
AutoBitSet::Static(s) => bun_core::cast_slice::<usize, u8>(&s.masks),
AutoBitSet::Dynamic(d) => d.bytes(),
}
}
pub fn bytes(&self, _: usize) -> &[u8] {
self.raw_bytes()
}
pub fn eql(&self, b: &AutoBitSet) -> bool {
self.raw_bytes() == b.raw_bytes()
}
pub fn hash(&self) -> u64 {
bun_wyhash::hash(self.raw_bytes())
}
pub fn for_each<Ctx>(&self, ctx: &mut Ctx, function: fn(&mut Ctx, usize)) {
let mut iter = self.iterator::<true, true>();
while let Some(index) = iter.next() {
function(ctx, index);
}
}
pub fn set_all(&mut self, value: bool) {
auto_forward!(self, |b| b.set_all(value))
}
pub fn count(&self) -> usize {
auto_forward!(self, |b| b.count())
}
pub fn find_first_set(&self) -> Option<usize> {
auto_forward!(self, |b| b.find_first_set())
}
pub fn iterator<const KIND_SET: bool, const DIR_FWD: bool>(
&self,
) -> AutoBitSetIterator<'_, KIND_SET, DIR_FWD> {
auto_forward!(self, |b| b.iterator::<KIND_SET, DIR_FWD>())
}
}
pub(crate) type AutoBitSetIterator<'a, const KIND_SET: bool, const DIR_FWD: bool> =
BitSetIterator<'a, KIND_SET, DIR_FWD>;
impl Drop for AutoBitSet {
fn drop(&mut self) {
match self {
AutoBitSet::Static(_) => {}
AutoBitSet::Dynamic(d) => d.deinit(),
}
}
}
#[derive(Default)]
pub struct DynamicBitSet {
pub unmanaged: DynamicBitSetUnmanaged,
}
impl DynamicBitSet {
pub fn init_empty(bit_length: usize) -> Result<Self, AllocError> {
Ok(Self {
unmanaged: DynamicBitSetUnmanaged::init_empty(bit_length)?,
})
}
pub fn init_full(bit_length: usize) -> Result<Self, AllocError> {
Ok(Self {
unmanaged: DynamicBitSetUnmanaged::init_full(bit_length)?,
})
}
pub fn resize(&mut self, new_len: usize, fill: bool) -> Result<(), AllocError> {
self.unmanaged.resize(new_len, fill)
}
pub fn clone(&self) -> Result<Self, AllocError> {
Ok(Self {
unmanaged: self.unmanaged.clone()?,
})
}
#[inline(always)]
pub fn capacity(&self) -> usize {
self.unmanaged.capacity()
}
#[inline(always)]
pub fn bit_length(&self) -> usize {
self.unmanaged.capacity()
}
#[inline]
pub fn copy_into(&self, other: &mut Self) {
other.unmanaged.copy_into(&self.unmanaged);
}
pub fn is_set(&self, index: usize) -> bool {
self.unmanaged.is_set(index)
}
pub fn count(&self) -> usize {
self.unmanaged.count()
}
pub fn set_value(&mut self, index: usize, value: bool) {
self.unmanaged.set_value(index, value);
}
pub fn set(&mut self, index: usize) {
self.unmanaged.set(index);
}
pub fn set_all(&mut self, value: bool) {
self.unmanaged.set_all(value);
}
pub fn set_range_value(&mut self, range: Range, value: bool) {
self.unmanaged.set_range_value(range, value);
}
pub fn unset(&mut self, index: usize) {
self.unmanaged.unset(index);
}
pub fn toggle(&mut self, index: usize) {
self.unmanaged.toggle(index);
}
pub fn toggle_set(&mut self, toggles: &Self) {
self.unmanaged.toggle_set(&toggles.unmanaged);
}
pub fn toggle_all(&mut self) {
self.unmanaged.toggle_all();
}
pub fn set_union(&mut self, other: &Self) {
self.unmanaged.set_union(&other.unmanaged);
}
pub fn set_intersection(&mut self, other: &Self) {
self.unmanaged.set_intersection(&other.unmanaged);
}
pub fn find_first_set(&self) -> Option<usize> {
self.unmanaged.find_first_set()
}
pub fn toggle_first_set(&mut self) -> Option<usize> {
self.unmanaged.toggle_first_set()
}
pub fn eql(&self, other: &Self) -> bool {
self.unmanaged.eql(&other.unmanaged)
}
pub fn iterator<const KIND_SET: bool, const DIR_FWD: bool>(
&self,
) -> BitSetIterator<'_, KIND_SET, DIR_FWD> {
self.unmanaged.iterator::<KIND_SET, DIR_FWD>()
}
}
#[derive(Clone, Copy, Default)]
pub struct IteratorOptions {
pub kind: IteratorKind,
pub direction: IteratorDirection,
}
#[derive(PartialEq, Eq, Clone, Copy, Default)]
pub enum IteratorKind {
#[default]
Set,
Unset,
}
#[derive(PartialEq, Eq, Clone, Copy, Default)]
pub enum IteratorDirection {
#[default]
Forward,
Reverse,
}
pub struct BitSetIterator<'a, const KIND_SET: bool, const DIR_FWD: bool> {
bits_remain: usize,
words_remain: &'a [usize],
bit_offset: usize,
last_word_mask: usize,
}
impl<'a, const KIND_SET: bool, const DIR_FWD: bool> BitSetIterator<'a, KIND_SET, DIR_FWD> {
fn init(masks: &'a [usize], last_word_mask: usize) -> Self {
if masks.is_empty() {
Self {
bits_remain: 0,
words_remain: &[],
last_word_mask,
bit_offset: 0,
}
} else {
let mut result = Self {
bits_remain: 0,
words_remain: masks,
last_word_mask,
bit_offset: if DIR_FWD {
0
} else {
(masks.len() - 1) * usize::BITS as usize
},
};
result.next_word::<true>();
result
}
}
pub fn next(&mut self) -> Option<usize> {
while self.bits_remain == 0 {
if self.words_remain.is_empty() {
return None;
}
self.next_word::<false>();
if DIR_FWD {
self.bit_offset += usize::BITS as usize
} else {
self.bit_offset -= usize::BITS as usize
}
}
if DIR_FWD {
let next_index = self.bits_remain.trailing_zeros() as usize + self.bit_offset;
self.bits_remain &= self.bits_remain - 1;
Some(next_index)
} else {
let leading_zeroes = self.bits_remain.leading_zeros();
let top_bit = (usize::BITS - 1 - leading_zeroes) as usize;
self.bits_remain &= (1usize << top_bit) - 1;
Some(top_bit + self.bit_offset)
}
}
#[inline(always)]
fn next_word<const IS_FIRST_WORD: bool>(&mut self) {
let mut word = if DIR_FWD {
self.words_remain[0]
} else {
self.words_remain[self.words_remain.len() - 1]
};
if !KIND_SET {
word = !word;
if (!DIR_FWD && IS_FIRST_WORD) || (DIR_FWD && self.words_remain.len() == 1) {
word &= self.last_word_mask;
}
}
if DIR_FWD {
self.words_remain = &self.words_remain[1..];
} else {
self.words_remain = &self.words_remain[..self.words_remain.len() - 1];
}
self.bits_remain = word;
}
}
#[derive(Clone, Copy)]
pub struct Range {
pub start: usize,
pub end: usize,
}