use std::{
fmt,
mem::size_of,
ops::{Deref, DerefMut},
slice::{Iter, IterMut, from_raw_parts, from_raw_parts_mut},
};
use wram::{DirectVirtualMemory, DirectVmBlock};
use crate::{Result, bucket::HashBucket, error::Error};
pub struct HashBuckets {
block: DirectVmBlock,
len: usize,
}
impl HashBuckets {
pub fn new(len: usize) -> Result<Self> {
if len == 0 {
return Err(Error::InvalidBucketCount(0));
}
let size_bytes = len
.checked_mul(size_of::<HashBucket>())
.ok_or(Error::InvalidBucketCount(len))?;
let block = DirectVirtualMemory::allocate(size_bytes, 64)?;
Ok(Self { block, len })
}
#[inline(always)]
pub const fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline(always)]
pub fn as_slice(&self) -> &[HashBucket] {
if self.len == 0 {
&[]
} else {
unsafe { from_raw_parts(self.block.aligned_ptr as *const HashBucket, self.len) }
}
}
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [HashBucket] {
if self.len == 0 {
&mut []
} else {
unsafe { from_raw_parts_mut(self.block.aligned_ptr as *mut HashBucket, self.len) }
}
}
#[inline(always)]
pub fn as_ptr(&self) -> *const HashBucket {
self.block.aligned_ptr as *const HashBucket
}
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut HashBucket {
self.block.aligned_ptr as *mut HashBucket
}
#[inline(always)]
pub unsafe fn get_unchecked(&self, index: usize) -> &HashBucket {
unsafe { &*(self.block.aligned_ptr as *const HashBucket).add(index) }
}
}
impl Deref for HashBuckets {
type Target = [HashBucket];
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl DerefMut for HashBuckets {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
impl AsRef<[HashBucket]> for HashBuckets {
#[inline(always)]
fn as_ref(&self) -> &[HashBucket] {
self.as_slice()
}
}
impl AsMut<[HashBucket]> for HashBuckets {
#[inline(always)]
fn as_mut(&mut self) -> &mut [HashBucket] {
self.as_mut_slice()
}
}
impl<'a> IntoIterator for &'a HashBuckets {
type Item = &'a HashBucket;
type IntoIter = Iter<'a, HashBucket>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<'a> IntoIterator for &'a mut HashBuckets {
type Item = &'a mut HashBucket;
type IntoIter = IterMut<'a, HashBucket>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.as_mut_slice().iter_mut()
}
}
impl fmt::Debug for HashBuckets {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HashBuckets")
.field("len", &self.len)
.field("aligned_ptr", &self.block.aligned_ptr)
.finish()
}
}