#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use crate::matrix::{Matrix, MatrixLike};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Flags<const N: usize>([u8; N]);
impl<const N: usize> Flags<N> {
const VALID_N: () = assert!(N >= 1 && N <= 255, "Flags dimension must be 1..=255");
pub fn set_at(&mut self, pos: usize, value: u8) {
if pos < N {
self.0[pos] = value;
}
}
pub fn get_at(&self, pos: usize) -> u8 {
if pos < N {
self.0[pos]
} else {
0
}
}
}
impl<const N: usize> Default for Flags<N> {
fn default() -> Self {
const { Self::VALID_N };
Self([0u8; N])
}
}
impl<const N: usize> From<Flags<N>> for Vec<u8> {
fn from(flags: Flags<N>) -> Self {
flags.0.to_vec()
}
}
impl<T, const N: usize> From<[T; N]> for Flags<N>
where
T: Into<u8>,
{
fn from(arr: [T; N]) -> Self {
const { Self::VALID_N };
let mut bytes = [0u8; N];
for (i, item) in arr.into_iter().enumerate() {
bytes[i] = item.into();
}
Flags(bytes)
}
}
impl<const N: usize> From<&[u8]> for Flags<N> {
fn from(bytes: &[u8]) -> Self {
const { Self::VALID_N };
let mut array = [0; N];
let len = bytes.len().min(N);
array[..len].copy_from_slice(&bytes[..len]);
Self(array)
}
}
impl<const N: usize> AsRef<[u8]> for Flags<N> {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
pub trait FlagSet<T> {
fn set(&mut self, flag: T);
fn unset(&mut self);
fn contains(&self, flag: T) -> bool;
}
impl<const N: usize> MatrixLike for Flags<N> {
fn n(&self) -> u8 {
N as u8
}
fn get(&self, r: u8, c: u8) -> u8 {
if r == c && (r as usize) < N {
self.0[r as usize]
} else {
0
}
}
fn set(&mut self, r: u8, c: u8, value: u8) {
if r == c && (r as usize) < N {
self.0[r as usize] = value;
}
}
fn fill(&mut self, value: u8) {
for i in 0..N {
self.0[i] = value;
}
}
}
macro_rules! flags_to_matrix_impl {
($flags:expr, $matrix_type:ty, $n:expr) => {{
let mut m = <$matrix_type>::default();
for i in 0..$n {
m.set(i as u8, i as u8, $flags.get_at(i));
}
m
}};
}
macro_rules! flags_to_matrix_dyn_impl {
($flags:expr, $n:expr) => {{
let n = $n as u8;
let mut m = crate::matrix::MatrixDyn::try_from(n)?;
for i in 0..$n {
m.set(i as u8, i as u8, $flags.get_at(i));
}
Ok(m)
}};
}
impl<const N: usize> From<crate::flags::Flags<N>> for Matrix<N> {
fn from(flags: crate::flags::Flags<N>) -> Self {
flags_to_matrix_impl!(flags, Matrix<N>, N)
}
}
impl<const N: usize> From<&crate::flags::Flags<N>> for Matrix<N> {
fn from(flags: &crate::flags::Flags<N>) -> Self {
flags_to_matrix_impl!(flags, Matrix<N>, N)
}
}
impl<const N: usize> TryFrom<crate::flags::Flags<N>> for crate::matrix::MatrixDyn {
type Error = crate::matrix::MatrixError;
fn try_from(flags: crate::flags::Flags<N>) -> Result<Self, Self::Error> {
flags_to_matrix_dyn_impl!(flags, N)
}
}
impl<const N: usize> TryFrom<&crate::flags::Flags<N>> for crate::matrix::MatrixDyn {
type Error = crate::matrix::MatrixError;
fn try_from(flags: &crate::flags::Flags<N>) -> Result<Self, Self::Error> {
flags_to_matrix_dyn_impl!(flags, N)
}
}