use std::{marker, num::NonZero};
use crate::depot::{
capacity::Physical,
index::bitmap::{self, entry},
};
pub struct Row<S, P = (), M = (), W = usize> {
pub(in crate::depot::index::bitmap) phase: Phase<M, W>,
pub(in crate::depot::index::bitmap) plane: P,
pub(in crate::depot) source: S,
pub(in crate::depot::index::bitmap) index: NonZero<u32>,
}
impl<S: Copy, W> Clone for Row<S, (), (), W> {
fn clone(&self) -> Self {
*self
}
}
impl<S: Copy, W> Copy for Row<S, (), (), W> {}
impl<W: bitmap::Width, S: crate::depot::raw::Words<W>> Row<S, (), (), W> {
pub fn from_source(source: crate::depot::raw::Proof<(S, NonZero<u32>), Physical>) -> Self {
let (source, index) = source.into_inner();
Self {
source,
index,
plane: (),
phase: marker::PhantomData,
}
}
pub fn try_new(source: S, index: usize) -> Result<Self, bitmap::Error> {
let capacity = source.shape().bits();
if index >= capacity {
return Err(bitmap::Error { index, capacity });
}
Ok(unsafe { Self::new(source, index) })
}
pub(in crate::depot) unsafe fn new(source: S, index: usize) -> Self {
let index = unsafe { NonZero::new_unchecked(index as u32 + 1) };
Self::from_source(unsafe { crate::depot::raw::Proof::new((source, index)) })
}
}
impl<W: bitmap::Width, S: crate::depot::raw::Words<W>, P, M> Row<S, P, M, W> {
pub(in crate::depot) const fn plane(&self) -> P
where
P: Copy,
{
self.plane
}
pub(in crate::depot::index::bitmap) fn borrow(&self) -> Row<&S, (), (), W> {
Row {
source: &self.source,
index: self.index,
plane: (),
phase: marker::PhantomData,
}
}
pub const fn index(&self) -> usize {
self.index.get() as usize - 1
}
pub fn contains(&self, plane: S::Plane) -> bool {
let index = self.index();
let words = S::row(self.borrow(), plane);
let word = unsafe { words.get_unchecked(index / W::BITS as usize) };
word.get() & (1usize << (index % W::BITS as usize)) != 0
}
}
impl<W: bitmap::Width, S: crate::depot::raw::Words<W>, P> Row<S, P, (), W> {
pub const fn source(&self) -> &S {
&self.source
}
pub(in crate::depot) unsafe fn map<T: crate::depot::raw::Words<W>>(
self,
map: impl FnOnce(S) -> T,
) -> Row<T, (), (), W> {
Row {
source: map(self.source),
index: self.index,
plane: (),
phase: marker::PhantomData,
}
}
}
impl<'a, W: bitmap::Width, S: crate::depot::raw::Bitmap<W>> Row<&'a mut S, (), (), W> {
pub fn occupied(
self,
plane: S::Plane,
) -> Result<Mutable<'a, S, entry::Occupied, W>, Mutable<'a, S, entry::Absent, W>> {
let entry: Row<_, _, (), W> = Row {
source: self.source,
index: self.index,
plane,
phase: marker::PhantomData,
};
if entry.contains(plane) {
Ok(entry.with_phase())
} else {
Err(entry.with_phase())
}
}
}
impl<W: bitmap::Width, S: crate::depot::raw::Words<W, Size = NonZero<u32>>> Row<S, (), (), W> {
pub fn clamp(source: S, index: usize) -> Self {
let capacity = source.shape().bits;
let index = index.min(capacity.get() as usize - 1);
unsafe { Self::new(source, index) }
}
}
impl<S, P, M, W> Row<S, P, M, W> {
pub const fn position(&self) -> NonZero<u32> {
self.index
}
pub(in crate::depot) fn with_phase<N>(self) -> Row<S, P, N, W> {
Row {
source: self.source,
index: self.index,
plane: self.plane,
phase: marker::PhantomData,
}
}
}
type Mutable<'a, S, P, W> = Row<&'a mut S, <S as crate::depot::raw::Words<W>>::Plane, P, W>;
type Phase<M, W> = marker::PhantomData<fn(M, W) -> (M, W)>;
const _: () = {
assert!(size_of::<Row<&()>>() == 2 * size_of::<usize>());
assert!(size_of::<Option<Row<&()>>>() == size_of::<Row<&()>>());
};