use core::{
marker::PhantomData,
ops::{Index, IndexMut},
};
pub mod bits;
pub use crate::ops::unchecked::TrustedSizeGrid as _;
use crate::{core::Pos, ops::layout};
mod impl_grid;
mod impl_new;
mod impl_slice;
#[derive(Debug, Clone)]
pub struct GridBuf<T, B, L>
where
L: layout::Linear,
{
buffer: B,
width: usize,
height: usize,
_layout: PhantomData<L>,
_element: PhantomData<T>,
}
impl<T, B, L> GridBuf<T, B, L>
where
L: layout::Linear,
{
#[must_use]
pub fn into_inner(self) -> (B, usize, usize) {
(self.buffer, self.width, self.height)
}
}
impl<T, B, L> Index<Pos> for GridBuf<T, B, L>
where
L: layout::Linear,
B: AsRef<[T]>,
{
type Output = T;
fn index(&self, index: Pos) -> &Self::Output {
&self.buffer.as_ref()[index.y * self.width + index.x]
}
}
impl<T, B, L> IndexMut<Pos> for GridBuf<T, B, L>
where
L: layout::Linear,
B: AsRef<[T]> + AsMut<[T]>,
{
fn index_mut(&mut self, index: Pos) -> &mut Self::Output {
&mut self.buffer.as_mut()[index.y * self.width + index.x]
}
}
#[cfg(test)]
mod tests {
extern crate alloc;
use super::*;
use crate::{
core::{Pos, Rect},
ops::{
ExactSizeGrid as _, GridRead as _,
layout::RowMajor,
unchecked::{GridReadUnchecked as _, GridWriteUnchecked as _},
},
};
use alloc::{vec, vec::Vec};
#[test]
fn into_inner() {
let grid = GridBuf::<u8, _, _>::new(5, 4);
let (buffer, width, height) = grid.into_inner();
assert_eq!(buffer.len(), width * height);
}
#[test]
fn impl_bounded_grid() {
let grid = GridBuf::<u8, _, _>::new(5, 4);
assert_eq!(grid.width(), 5);
assert_eq!(grid.height(), 4);
}
#[test]
fn impl_get_unchecked() {
let grid = GridBuf::new_filled(5, 4, 42);
let pos = Pos::new(2, 3);
assert_eq!(*unsafe { grid.get_unchecked(pos) }, 42);
}
#[test]
fn impl_set_unchecked() {
let mut grid = GridBuf::new(5, 4);
let pos = Pos::new(2, 3);
unsafe { grid.set_unchecked(pos, 99) };
assert_eq!(*unsafe { grid.get_unchecked(pos) }, 99);
}
#[test]
fn with_buffer_col_major() {
let buffer =
GridBuf::<_, _, layout::ColumnMajor>::from_buffer(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], 3);
assert_eq!(buffer.width(), 3);
assert_eq!(buffer.height(), 3);
assert_eq!(buffer.get(Pos::new(0, 0)), Some(&1));
assert_eq!(buffer.get(Pos::new(2, 2)), Some(&9));
}
#[test]
fn rect_iter_unchecked() {
#[rustfmt::skip]
let buffer = GridBuf::<_, _, layout::RowMajor>::from_buffer(vec![
1, 2, 3,
4, 5, 6,
7, 8, 9,
], 3);
assert_eq!(
unsafe {
buffer
.iter_rect_unchecked(Rect::from_ltwh(1, 1, 2, 1))
.collect::<Vec<_>>()
},
vec![&5, &6]
);
assert_eq!(
unsafe {
buffer
.iter_rect_unchecked(Rect::from_ltwh(0, 0, 3, 3))
.copied()
.collect::<Vec<_>>()
},
vec![1, 2, 3, 4, 5, 6, 7, 8, 9]
);
}
#[test]
fn fill_rect_iter_unchecked() {
let mut grid = GridBuf::<_, _, RowMajor>::new(3, 3);
unsafe {
grid.fill_rect_iter_unchecked(Rect::from_ltwh(0, 0, 2, 2), vec![1, 2, 3, 4]);
}
#[rustfmt::skip]
assert_eq!(grid.buffer.as_ref() as &[i32], &[
1, 2, 0,
3, 4, 0,
0, 0, 0,
]);
}
#[test]
fn fill_rect_solid_unchecked() {
let mut grid = GridBuf::<_, _, RowMajor>::new(3, 3);
unsafe {
grid.fill_rect_solid_unchecked(Rect::from_ltwh(0, 0, 2, 2), 42);
}
#[rustfmt::skip]
assert_eq!(grid.buffer.as_ref() as &[i32], &[
42, 42, 0,
42, 42, 0,
0, 0, 0,
]);
}
#[test]
fn index_ops() {
let mut grid = GridBuf::<u8, _, _>::new(3, 3);
grid[Pos::new(1, 1)] = 42;
assert_eq!(grid[Pos::new(1, 1)], 42);
assert_eq!(grid.get(Pos::new(1, 1)), Some(&42));
assert_eq!(grid.get(Pos::new(3, 3)), None); }
}