use super::slice::{Packable4, Packed4Slice, Packed4SliceMut};
use crate::types::{Bf4, F4};
use alloc::vec::Vec;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Packed4Vec<T: Packable4> {
pub(crate) data: Vec<u8>,
pub(crate) len: usize,
pub(crate) _marker: core::marker::PhantomData<T>,
}
impl<T: Packable4> Packed4Vec<T> {
#[inline]
pub fn new() -> Self {
Self {
data: Vec::new(),
len: 0,
_marker: core::marker::PhantomData,
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
data: Vec::with_capacity(capacity.div_ceil(2)),
len: 0,
_marker: core::marker::PhantomData,
}
}
#[inline(always)]
pub fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn clear(&mut self) {
self.data.clear();
self.len = 0;
}
#[inline]
pub fn push(&mut self, val: T) {
if self.len.is_multiple_of(2) {
let byte = T::pack_pair(val, val);
self.data.push(byte);
} else {
let last_idx = self.data.len() - 1;
let last_byte = self.data[last_idx];
let (low, _) = T::unpack_pair(last_byte);
self.data[last_idx] = T::pack_pair(low, val);
}
self.len += 1;
}
#[inline]
pub fn get(&self, index: usize) -> Option<T> {
if index >= self.len {
None
} else {
let byte_idx = index / 2;
let byte = self.data[byte_idx];
let (low, high) = T::unpack_pair(byte);
if index.is_multiple_of(2) {
Some(low)
} else {
Some(high)
}
}
}
#[inline]
pub fn set(&mut self, index: usize, val: T) {
if index < self.len {
let byte_idx = index / 2;
let byte = self.data[byte_idx];
let (mut low, mut high) = T::unpack_pair(byte);
if index.is_multiple_of(2) {
low = val;
} else {
high = val;
}
self.data[byte_idx] = T::pack_pair(low, high);
}
}
#[inline]
pub fn as_packed_slice(&self) -> &[u8] {
&self.data
}
#[inline]
pub fn as_packed_slice_mut(&mut self) -> &mut [u8] {
&mut self.data
}
#[inline]
pub fn as_view(&self) -> Packed4Slice<'_, T> {
Packed4Slice {
data: &self.data,
len: self.len,
_marker: core::marker::PhantomData,
}
}
#[inline]
pub fn as_view_mut(&mut self) -> Packed4SliceMut<'_, T> {
Packed4SliceMut {
data: &mut self.data,
len: self.len,
_marker: core::marker::PhantomData,
}
}
}
impl<T: Packable4> Default for Packed4Vec<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
pub struct Packed4Iter<'a, T: Packable4> {
pub(crate) view: Packed4Slice<'a, T>,
pub(crate) index: usize,
}
impl<'a, T: Packable4> Iterator for Packed4Iter<'a, T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let val = self.view.get(self.index);
if val.is_some() {
self.index += 1;
}
val
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let rem = self.view.len() - self.index;
(rem, Some(rem))
}
}
impl<'a, T: Packable4> ExactSizeIterator for Packed4Iter<'a, T> {}
impl<'a, T: Packable4> IntoIterator for Packed4Slice<'a, T> {
type Item = T;
type IntoIter = Packed4Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
Packed4Iter {
view: self,
index: 0,
}
}
}
impl<'a, T: Packable4> core::iter::FusedIterator for Packed4Iter<'a, T> {}
impl<T: Packable4> IntoIterator for Packed4Vec<T> {
type Item = T;
type IntoIter = Packed4OwnedIter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
Packed4OwnedIter {
vec: self,
index: 0,
}
}
}
pub struct Packed4OwnedIter<T: Packable4> {
vec: Packed4Vec<T>,
index: usize,
}
impl<T: Packable4> Iterator for Packed4OwnedIter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.index >= self.vec.len() {
return None;
}
let val = self.vec.get(self.index)?;
self.index += 1;
Some(val)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let rem = self.vec.len() - self.index;
(rem, Some(rem))
}
}
impl<T: Packable4> ExactSizeIterator for Packed4OwnedIter<T> {}
impl<T: Packable4> core::iter::FusedIterator for Packed4OwnedIter<T> {}
impl<T: Packable4> Extend<T> for Packed4Vec<T> {
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (lower, _) = iter.size_hint();
let extra_bytes = lower.div_ceil(2);
self.data.reserve(extra_bytes);
for item in iter {
self.push(item);
}
}
}
impl<T: Packable4> FromIterator<T> for Packed4Vec<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut vec = Self::new();
vec.extend(iter);
vec
}
}
pub type PackedBf4Vec = Packed4Vec<Bf4>;
pub type PackedF4Vec = Packed4Vec<F4>;