use std::mem::size_of;
use roaring::RoaringBitmap;
const CONTAINER: usize = 40;
#[must_use]
#[expect(
clippy::integer_division,
reason = "both counts are exact multiples of their divisor, so no remainder exists to lose"
)]
pub fn bitmap(set: &RoaringBitmap) -> usize {
let stats = set.statistics();
let containers = usize::try_from(stats.n_containers).unwrap_or(usize::MAX);
let arrays = usize::try_from(stats.n_bytes_array_containers).unwrap_or(usize::MAX) / 2;
let bitsets = usize::try_from(stats.n_bytes_bitset_containers).unwrap_or(usize::MAX) / 8;
let runs = usize::try_from(stats.n_bytes_run_containers).unwrap_or(usize::MAX);
arrays
.saturating_add(bitsets)
.saturating_add(runs)
.saturating_add(containers.saturating_mul(CONTAINER))
}
#[must_use]
pub fn bitmaps(sets: &[RoaringBitmap]) -> usize {
let own = sets.len().saturating_mul(size_of::<RoaringBitmap>());
sets.iter()
.fold(own, |total, set| total.saturating_add(bitmap(set)))
}
#[must_use]
pub fn vector<T>(values: &Vec<T>) -> usize {
values.capacity().saturating_mul(size_of::<T>())
}
#[must_use]
pub fn strings(values: &Vec<String>) -> usize {
values.iter().fold(vector(values), |total, text| {
total.saturating_add(text.capacity())
})
}
#[must_use]
pub fn entries<K, V>(len: usize) -> usize {
len.saturating_mul(size_of::<K>().saturating_add(size_of::<V>()))
}
#[cfg(test)]
mod tests {
use roaring::RoaringBitmap;
use super::{bitmap, bitmaps, entries, strings, vector};
#[test]
fn an_empty_bitmap_holds_nothing() {
assert_eq!(bitmap(&RoaringBitmap::new()), 0);
}
#[test]
fn a_sparse_bitmap_costs_two_bytes_a_value_and_one_container() {
let set: RoaringBitmap = (0..100).collect();
assert!(bitmap(&set) >= 200 + 40, "{}", bitmap(&set));
assert!(bitmap(&set) < 1024, "{}", bitmap(&set));
}
#[test]
fn a_dense_bitmap_costs_a_bitset_container() {
let set: RoaringBitmap = (0..20_000).collect();
assert_eq!(bitmap(&set), 8192 + 40);
}
#[test]
fn a_list_of_bitmaps_carries_its_own_vector() {
let sets = vec![RoaringBitmap::new(), RoaringBitmap::new()];
assert_eq!(bitmaps(&sets), 2 * size_of::<RoaringBitmap>());
}
#[test]
fn a_vector_is_counted_at_its_capacity() {
let mut values: Vec<u32> = Vec::with_capacity(16);
values.push(1);
assert_eq!(vector(&values), 64);
}
#[test]
fn strings_carry_their_text() {
let values = vec![String::from("abcd")];
assert_eq!(strings(&values), vector(&values) + 4);
}
#[test]
fn map_entries_are_counted_at_their_own_width() {
assert_eq!(entries::<u64, u32>(10), 10 * (8 + 4));
}
}