use std::ops::{Index, IndexMut};
use crate::directions::Direction;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "serde-1", derive(Serialize, Deserialize))]
pub struct DirectionMap<T> {
arr: [T; 8],
}
impl<T: Default> DirectionMap<T> {
pub fn new() -> Self {
Self::default()
}
}
impl<T> DirectionMap<T> {
pub fn from_array(arr: [T; 8]) -> Self {
DirectionMap { arr }
}
pub fn into_array(self) -> [T; 8] {
self.arr
}
pub fn as_array(&self) -> &[T; 8] {
&self.arr
}
pub fn as_mut_array(&mut self) -> &mut [T; 8] {
&mut self.arr
}
pub fn as_slice(&self) -> &[T] {
&self.arr
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.arr
}
pub fn get(&self, dir: Direction) -> &T {
let idx = dir as u8 as usize;
debug_assert!(idx < 8);
unsafe { self.arr.get_unchecked(idx) }
}
pub fn get_mut(&mut self, dir: Direction) -> &mut T {
let idx = dir as u8 as usize;
debug_assert!(idx < 8);
unsafe { self.arr.get_unchecked_mut(idx) }
}
pub fn with_initializer<F>(mut op: F) -> Self
where
F: FnMut(Direction) -> T,
{
#![allow(clippy::cast_sign_loss)]
use std::mem::MaybeUninit;
let mut arr = MaybeUninit::<[T; 8]>::uninit();
let ptr = arr.as_mut_ptr() as *mut T;
let arr = unsafe {
for i in 0..8 {
let dir = std::mem::transmute::<u8, Direction>(i as u8);
ptr.offset(i).write(op(dir));
}
arr.assume_init()
};
DirectionMap { arr }
}
}
impl<T> Index<Direction> for DirectionMap<T> {
type Output = T;
fn index(&self, d: Direction) -> &T {
&self.arr[d as u8 as usize]
}
}
impl<T> IndexMut<Direction> for DirectionMap<T> {
fn index_mut(&mut self, d: Direction) -> &mut T {
&mut self.arr[d as u8 as usize]
}
}