use crate::defs::Error;
use crate::defs::Word;
use crate::defs::WORD_BIT_SIZE;
use core::ops::Deref;
use core::ops::DerefMut;
use core::ops::Index;
use core::ops::IndexMut;
use core::slice::SliceIndex;
use crate::common::util::shift_slice_left;
use crate::common::util::shift_slice_right;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[derive(Debug, Hash)]
pub struct WordBuf {
inner: Vec<Word>,
}
impl WordBuf {
#[inline]
pub fn new(sz: usize) -> Result<Self, Error> {
let mut inner = Vec::new();
inner.try_reserve_exact(sz)?;
unsafe {
inner.set_len(sz);
}
Ok(WordBuf { inner })
}
#[inline]
pub fn fill(&mut self, d: Word) {
self.inner.fill(d);
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn trunc_to(&mut self, l: usize) {
let n = (l + WORD_BIT_SIZE - 1) / WORD_BIT_SIZE;
let sz = self.len();
shift_slice_right(&mut self.inner, (sz - n) * WORD_BIT_SIZE);
self.inner.truncate(n);
}
pub fn trunc_to_2(&mut self, l: usize) {
let n = (l + WORD_BIT_SIZE - 1) / WORD_BIT_SIZE;
self.inner.truncate(n);
}
pub fn try_extend(&mut self, p: usize) -> Result<(), Error> {
let n = (p + WORD_BIT_SIZE - 1) / WORD_BIT_SIZE;
let l = self.inner.len();
self.inner.try_reserve(n - l)?;
unsafe {
self.inner.set_len(n);
}
shift_slice_left(&mut self.inner, (n - l) * WORD_BIT_SIZE);
Ok(())
}
pub fn try_extend_2(&mut self, p: usize) -> Result<(), Error> {
let n = (p + WORD_BIT_SIZE - 1) / WORD_BIT_SIZE;
if n > self.inner.capacity() {
self.inner.try_reserve(n - self.inner.capacity())?;
}
if n > self.inner.len() {
self.inner.resize(n, 0);
}
Ok(())
}
pub fn trunc_trailing_zeroes(&mut self) {
let mut n = 0;
for v in self.inner.iter() {
if *v == 0 {
n += 1;
} else {
break;
}
}
if n > 0 {
let sz = self.len();
shift_slice_right(&mut self.inner, n * WORD_BIT_SIZE);
self.inner.truncate(sz - n);
}
}
pub fn trunc_leading_zeroes(&mut self) {
let mut n = 0;
for v in self.inner.iter().rev() {
if *v == 0 {
n += 1;
} else {
break;
}
}
if n > 0 {
let sz = self.len();
self.inner.truncate(sz - n);
}
}
}
impl<I: SliceIndex<[Word]>> IndexMut<I> for WordBuf {
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.inner.index_mut(index)
}
}
impl<I: SliceIndex<[Word]>> Index<I> for WordBuf {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
self.inner.index(index)
}
}
impl Deref for WordBuf {
type Target = [Word];
#[inline]
fn deref(&self) -> &[Word] {
self.inner.deref()
}
}
impl DerefMut for WordBuf {
#[inline]
fn deref_mut(&mut self) -> &mut [Word] {
self.inner.deref_mut()
}
}