#![cfg(target_pointer_width = "64")]
pub mod inner;
use std::io::{Read, Write};
use anyhow::Result;
use crate::bit_vectors::prelude::*;
use crate::bit_vectors::rank9sel::inner::Rank9SelIndex;
use crate::bit_vectors::BitVector;
use crate::Serializable;
use inner::DArrayIndex;
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct DArray {
bv: BitVector,
s1: DArrayIndex,
s0: Option<DArrayIndex>,
r9: Option<Rank9SelIndex>,
}
impl DArray {
pub fn from_bits<I>(bits: I) -> Self
where
I: IntoIterator<Item = bool>,
{
let bv = BitVector::from_bits(bits);
let s1 = DArrayIndex::new(&bv, true);
Self {
bv,
s1,
s0: None,
r9: None,
}
}
#[must_use]
pub fn enable_rank(mut self) -> Self {
self.r9 = Some(Rank9SelIndex::new(&self.bv));
self
}
#[must_use]
pub fn enable_select0(mut self) -> Self {
self.s0 = Some(DArrayIndex::new(&self.bv, false));
self
}
#[inline(always)]
pub const fn has_rank(&self) -> bool {
self.r9.is_some()
}
#[inline(always)]
pub const fn has_select0(&self) -> bool {
self.s0.is_some()
}
pub const fn bit_vector(&self) -> &BitVector {
&self.bv
}
pub const fn s1_index(&self) -> &DArrayIndex {
&self.s1
}
pub const fn s0_index(&self) -> Option<&DArrayIndex> {
self.s0.as_ref()
}
pub const fn r9_index(&self) -> Option<&Rank9SelIndex> {
self.r9.as_ref()
}
pub const fn len(&self) -> usize {
self.bv.len()
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Build for DArray {
fn build_from_bits<I>(
bits: I,
with_rank: bool,
_with_select1: bool,
with_select0: bool,
) -> Result<Self>
where
I: IntoIterator<Item = bool>,
Self: Sized,
{
let mut rsbv = Self::from_bits(bits);
if with_rank {
rsbv = rsbv.enable_rank();
}
if with_select0 {
rsbv = rsbv.enable_select0();
}
Ok(rsbv)
}
}
impl NumBits for DArray {
#[inline(always)]
fn num_bits(&self) -> usize {
self.len()
}
#[inline(always)]
fn num_ones(&self) -> usize {
self.s1.num_ones()
}
}
impl Access for DArray {
fn access(&self, pos: usize) -> Option<bool> {
self.bv.access(pos)
}
}
impl Rank for DArray {
fn rank1(&self, pos: usize) -> Option<usize> {
let r9 = self.r9.as_ref().expect("enable_rank() must be set up.");
unsafe { r9.rank1(&self.bv, pos) }
}
fn rank0(&self, pos: usize) -> Option<usize> {
let r9 = self.r9.as_ref().expect("enable_rank() must be set up.");
unsafe { r9.rank0(&self.bv, pos) }
}
}
impl Select for DArray {
fn select1(&self, k: usize) -> Option<usize> {
unsafe { self.s1.select(&self.bv, k) }
}
fn select0(&self, k: usize) -> Option<usize> {
let s0 = self.s0.as_ref().expect("enable_select0() must be set up.");
unsafe { s0.select(&self.bv, k) }
}
}
impl Serializable for DArray {
fn serialize_into<W: Write>(&self, mut writer: W) -> Result<usize> {
let mut mem = 0;
mem += self.bv.serialize_into(&mut writer)?;
mem += self.s1.serialize_into(&mut writer)?;
mem += self.s0.serialize_into(&mut writer)?;
mem += self.r9.serialize_into(&mut writer)?;
Ok(mem)
}
fn deserialize_from<R: Read>(mut reader: R) -> Result<Self> {
let bv = BitVector::deserialize_from(&mut reader)?;
let s1 = DArrayIndex::deserialize_from(&mut reader)?;
let s0 = Option::<DArrayIndex>::deserialize_from(&mut reader)?;
let r9 = Option::<Rank9SelIndex>::deserialize_from(&mut reader)?;
Ok(Self { bv, s1, s0, r9 })
}
fn size_in_bytes(&self) -> usize {
self.bv.size_in_bytes()
+ self.s1.size_in_bytes()
+ self.s0.size_in_bytes()
+ self.r9.size_in_bytes()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_all_zeros() {
let da = DArray::from_bits([false, false, false]);
assert_eq!(da.select1(0), None);
}
#[test]
#[should_panic]
fn test_rank1() {
let da = DArray::from_bits([false, true, false]);
da.rank1(1);
}
#[test]
#[should_panic]
fn test_rank0() {
let da = DArray::from_bits([false, true, false]);
da.rank0(1);
}
#[test]
#[should_panic]
fn test_select1() {
let da = DArray::from_bits([false, true, false]);
da.select0(0);
}
#[test]
fn test_serialize() {
let mut bytes = vec![];
let da = DArray::from_bits([true, false, false, true]);
let size = da.serialize_into(&mut bytes).unwrap();
let other = DArray::deserialize_from(&bytes[..]).unwrap();
assert_eq!(da, other);
assert_eq!(size, bytes.len());
assert_eq!(size, da.size_in_bytes());
}
}