use std::marker::PhantomData;
use rawdb::{Reader, Region};
use crate::{AnyStoredVec, HEADER_OFFSET, ReadOnlyRawVec, VecIndex, VecValue};
use super::super::{RawStrategy, ReadWriteRawVec};
pub struct VecReader<I, T, S> {
_reader: Reader,
data: *const u8,
stored_len: usize,
_marker: PhantomData<(I, T, S)>,
}
unsafe impl<I: Send, T: Send, S: Send> Send for VecReader<I, T, S> {}
unsafe impl<I: Sync, T: Sync, S: Sync> Sync for VecReader<I, T, S> {}
impl<I, T, S> VecReader<I, T, S>
where
T: VecValue,
S: RawStrategy<T>,
{
const SIZE_OF_T: usize = size_of::<T>();
pub(crate) fn from_region(region: &Region, stored_len: usize) -> Self {
let reader = region.create_reader();
let slice = reader.prefixed(HEADER_OFFSET);
let ptr = slice.as_ptr();
Self {
_reader: reader,
data: ptr,
stored_len,
_marker: PhantomData,
}
}
pub fn from_read_write(vec: &ReadWriteRawVec<I, T, S>) -> Self
where
I: VecIndex,
{
Self::from_region(vec.region(), vec.stored_len())
}
pub fn from_read_only(vec: &ReadOnlyRawVec<I, T, S>) -> Self
where
I: VecIndex,
{
Self::from_region(vec.region(), vec.stored_len())
}
#[inline(always)]
pub fn get(&self, index: usize) -> T {
assert!(
index < self.stored_len,
"index {index} out of bounds (len {})",
self.stored_len
);
unsafe { S::read_from_ptr(self.data, index * Self::SIZE_OF_T) }
}
#[inline(always)]
pub fn try_get(&self, index: usize) -> Option<T> {
if index >= self.stored_len {
return None;
}
Some(unsafe { S::read_from_ptr(self.data, index * Self::SIZE_OF_T) })
}
#[inline(always)]
pub fn len(&self) -> usize {
self.stored_len
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.stored_len == 0
}
}