#![cfg(target_pointer_width = "64")]
use std::convert::TryFrom;
use std::io::{Read, Write};
use anyhow::{anyhow, Result};
use num_traits::ToPrimitive;
use crate::bit_vectors::{self, BitVector, Rank, Rank9Sel};
use crate::int_vectors::{Access, Build, NumVals};
use crate::utils;
use crate::Serializable;
const LEVEL_WIDTH: usize = 8;
const LEVEL_MASK: usize = (1 << LEVEL_WIDTH) - 1;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DacsByte {
data: Vec<Vec<u8>>,
flags: Vec<Rank9Sel>,
}
impl DacsByte {
pub fn from_slice<T>(vals: &[T]) -> Result<Self>
where
T: ToPrimitive,
{
if vals.is_empty() {
return Ok(Self::default());
}
let mut maxv = 0;
for x in vals {
maxv =
maxv.max(x.to_usize().ok_or_else(|| {
anyhow!("vals must consist only of values castable into usize.")
})?);
}
let num_bits = utils::needed_bits(maxv);
let num_levels = utils::ceiled_divide(num_bits, LEVEL_WIDTH);
assert_ne!(num_levels, 0);
if num_levels == 1 {
let data: Vec<_> = vals
.iter()
.map(|x| u8::try_from(x.to_usize().unwrap()).unwrap())
.collect();
return Ok(Self {
data: vec![data],
flags: vec![],
});
}
let mut data = vec![vec![]; num_levels];
let mut flags = vec![BitVector::default(); num_levels - 1];
for x in vals {
let mut x = x.to_usize().unwrap();
for j in 0..num_levels {
data[j].push(u8::try_from(x & LEVEL_MASK).unwrap());
x >>= LEVEL_WIDTH;
if j == num_levels - 1 {
assert_eq!(x, 0);
break;
} else if x == 0 {
flags[j].push_bit(false);
break;
}
flags[j].push_bit(true);
}
}
let flags = flags.into_iter().map(Rank9Sel::new).collect();
Ok(Self { data, flags })
}
pub const fn iter(&self) -> Iter {
Iter::new(self)
}
#[inline(always)]
pub fn len(&self) -> usize {
self.data[0].len()
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline(always)]
pub fn num_levels(&self) -> usize {
self.data.len()
}
#[inline(always)]
pub fn widths(&self) -> Vec<usize> {
self.data.iter().map(|_| LEVEL_WIDTH).collect()
}
}
impl Default for DacsByte {
fn default() -> Self {
Self {
data: vec![vec![]],
flags: vec![],
}
}
}
impl Build for DacsByte {
fn build_from_slice<T>(vals: &[T]) -> Result<Self>
where
T: ToPrimitive,
Self: Sized,
{
Self::from_slice(vals)
}
}
impl NumVals for DacsByte {
fn num_vals(&self) -> usize {
self.len()
}
}
impl Access for DacsByte {
fn access(&self, mut pos: usize) -> Option<usize> {
if self.len() <= pos {
return None;
}
let mut x = 0;
for j in 0..self.num_levels() {
x |= usize::from(self.data[j][pos]) << (j * LEVEL_WIDTH);
if j == self.num_levels() - 1
|| !bit_vectors::Access::access(&self.flags[j], pos).unwrap()
{
break;
}
pos = self.flags[j].rank1(pos).unwrap();
}
Some(x)
}
}
pub struct Iter<'a> {
seq: &'a DacsByte,
pos: usize,
}
impl<'a> Iter<'a> {
pub const fn new(seq: &'a DacsByte) -> Self {
Self { seq, pos: 0 }
}
}
impl Iterator for Iter<'_> {
type Item = usize;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.pos < self.seq.len() {
let x = self.seq.access(self.pos).unwrap();
self.pos += 1;
Some(x)
} else {
None
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.seq.len(), Some(self.seq.len()))
}
}
impl Serializable for DacsByte {
fn serialize_into<W: Write>(&self, mut writer: W) -> Result<usize> {
let mut mem = 0;
mem += self.data.serialize_into(&mut writer)?;
mem += self.flags.serialize_into(&mut writer)?;
Ok(mem)
}
fn deserialize_from<R: Read>(mut reader: R) -> Result<Self> {
let data = Vec::<Vec<u8>>::deserialize_from(&mut reader)?;
let flags = Vec::<Rank9Sel>::deserialize_from(&mut reader)?;
Ok(Self { data, flags })
}
fn size_in_bytes(&self) -> usize {
self.data.size_in_bytes() + self.flags.size_in_bytes()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic() {
let seq = DacsByte::from_slice(&[0xFFFF, 0xFF, 0xF, 0xFFFFF, 0xF]).unwrap();
assert_eq!(
seq.data,
vec![
vec![0xFF, 0xFF, 0xF, 0xFF, 0xF],
vec![0xFF, 0xFF],
vec![0xF]
]
);
assert_eq!(
seq.flags,
vec![
Rank9Sel::from_bits([true, false, false, true, false]),
Rank9Sel::from_bits([false, true])
]
);
assert!(!seq.is_empty());
assert_eq!(seq.len(), 5);
assert_eq!(seq.num_levels(), 3);
assert_eq!(seq.widths(), vec![LEVEL_WIDTH, LEVEL_WIDTH, LEVEL_WIDTH]);
assert_eq!(seq.access(0), Some(0xFFFF));
assert_eq!(seq.access(1), Some(0xFF));
assert_eq!(seq.access(2), Some(0xF));
assert_eq!(seq.access(3), Some(0xFFFFF));
assert_eq!(seq.access(4), Some(0xF));
}
#[test]
fn test_empty() {
let seq = DacsByte::from_slice::<usize>(&[]).unwrap();
assert!(seq.is_empty());
assert_eq!(seq.len(), 0);
assert_eq!(seq.num_levels(), 1);
assert_eq!(seq.widths(), vec![LEVEL_WIDTH]);
}
#[test]
fn test_all_zeros() {
let seq = DacsByte::from_slice(&[0, 0, 0, 0]).unwrap();
assert!(!seq.is_empty());
assert_eq!(seq.len(), 4);
assert_eq!(seq.num_levels(), 1);
assert_eq!(seq.widths(), vec![LEVEL_WIDTH]);
assert_eq!(seq.access(0), Some(0));
assert_eq!(seq.access(1), Some(0));
assert_eq!(seq.access(2), Some(0));
assert_eq!(seq.access(3), Some(0));
}
#[test]
fn test_from_slice_uncastable() {
let e = DacsByte::from_slice(&[u128::MAX]);
assert_eq!(
e.err().map(|x| x.to_string()),
Some("vals must consist only of values castable into usize.".to_string())
);
}
#[test]
fn test_serialize() {
let mut bytes = vec![];
let seq = DacsByte::from_slice(&[0xFFFFF, 0xFF, 0xF, 0xFFFFF, 0xF]).unwrap();
let size = seq.serialize_into(&mut bytes).unwrap();
let other = DacsByte::deserialize_from(&bytes[..]).unwrap();
assert_eq!(seq, other);
assert_eq!(size, bytes.len());
assert_eq!(size, seq.size_in_bytes());
}
}