use crate::{VolAddress, VolBlock};
pub struct VolMatrix<T, R, W, const WIDTH: usize, const HEIGHT: usize> {
base: VolAddress<T, R, W>,
}
impl<T, R, W, const WIDTH: usize, const HEIGHT: usize>
VolMatrix<T, R, W, WIDTH, HEIGHT>
{
#[inline]
#[must_use]
pub const fn from_block<const B: usize>(block: VolBlock<T, R, W, B>) -> Self {
assert!(B == WIDTH * HEIGHT);
Self { base: block.base }
}
#[inline]
#[must_use]
pub const fn into_block<const B: usize>(self) -> VolBlock<T, R, W, B> {
assert!(B == WIDTH * HEIGHT);
VolBlock { base: self.base }
}
#[inline]
#[must_use]
pub const unsafe fn new(address: usize) -> Self {
Self { base: VolAddress::new(address) }
}
#[inline]
#[must_use]
pub const fn get(self, x: usize, y: usize) -> Option<VolAddress<T, R, W>> {
if x < WIDTH && y < HEIGHT {
Some(unsafe { self.base.add(x + y * WIDTH) })
} else {
None
}
}
#[inline]
#[must_use]
#[track_caller]
pub const fn index(self, x: usize, y: usize) -> VolAddress<T, R, W> {
match self.get(x, y) {
Some(address) => address,
None => {
#[allow(unconditional_panic)]
unsafe {
VolAddress::new([usize::MAX][1])
}
}
}
}
}
impl<T, R, W, const WIDTH: usize, const HEIGHT: usize>
VolMatrix<T, R, W, WIDTH, HEIGHT>
{
#[inline]
#[must_use]
pub const fn get_row(self, y: usize) -> Option<VolBlock<T, R, W, WIDTH>> {
if y < HEIGHT {
Some(unsafe { VolBlock { base: self.base.add(y * WIDTH) } })
} else {
None
}
}
}