id_sys 0.1.0

Provides data structures which can be marked such that they only work with similarly marked integer data types.
Documentation
use crate::{IdSlice, IdSliceIndex};
use std::{
    borrow::{Borrow, BorrowMut},
    cmp::Ordering,
    fmt::{self, Debug, Formatter},
    hash::{Hash, Hasher},
    marker::PhantomData,
    mem::transmute,
    ops::{Index, IndexMut},
};

pub struct IdArray<TMarker: ?Sized, TValue, const N: usize> {
    phantom: PhantomData<TMarker>,
    repr: [TValue; N],
}

impl<TMarker: ?Sized, TValue, const N: usize> IdArray<TMarker, TValue, N> {
    pub const fn as_array(&self) -> &[TValue; N] {
        &self.repr
    }

    pub fn as_mut_array(&mut self) -> &mut [TValue; N] {
        &mut self.repr
    }

    pub fn as_mut_id_slice(&mut self) -> &mut IdSlice<TMarker, TValue> {
        IdSlice::from_mut_slice(self.as_mut_array())
    }

    pub const fn as_id_slice(&self) -> &IdSlice<TMarker, TValue> {
        IdSlice::from_slice(self.as_array())
    }

    pub const fn from_array(repr: [TValue; N]) -> Self {
        Self {
            phantom: PhantomData,
            repr,
        }
    }

    pub const fn from_array_ref(repr: &[TValue; N]) -> &Self {
        unsafe { transmute(repr) }
    }

    pub fn from_mut_array(repr: &mut [TValue; N]) -> &mut Self {
        unsafe { transmute(repr) }
    }

    pub fn into_array(self) -> [TValue; N] {
        self.repr
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> AsMut<IdSlice<TMarker, TValue>>
    for IdArray<TMarker, TValue, N>
{
    fn as_mut(&mut self) -> &mut IdSlice<TMarker, TValue> {
        self.as_mut_id_slice()
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> AsRef<IdSlice<TMarker, TValue>>
    for IdArray<TMarker, TValue, N>
{
    fn as_ref(&self) -> &IdSlice<TMarker, TValue> {
        self.as_id_slice()
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> Borrow<IdSlice<TMarker, TValue>>
    for IdArray<TMarker, TValue, N>
{
    fn borrow(&self) -> &IdSlice<TMarker, TValue> {
        IdSlice::from_slice(self.as_array().borrow())
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> BorrowMut<IdSlice<TMarker, TValue>>
    for IdArray<TMarker, TValue, N>
{
    fn borrow_mut(&mut self) -> &mut IdSlice<TMarker, TValue> {
        IdSlice::from_mut_slice(self.as_mut_array().borrow_mut())
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> Clone for IdArray<TMarker, TValue, N>
where
    [TValue; N]: Clone,
{
    fn clone(&self) -> Self {
        Self::from_array(self.as_array().clone())
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> Copy for IdArray<TMarker, TValue, N> where
    [TValue; N]: Copy
{
}

impl<TMarker: ?Sized, TValue: Debug, const N: usize> Debug for IdArray<TMarker, TValue, N> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Debug::fmt(self.as_id_slice(), f)
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> Default for IdArray<TMarker, TValue, N>
where
    [TValue; N]: Default,
{
    fn default() -> Self {
        Self::from_array(Default::default())
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> Eq for IdArray<TMarker, TValue, N> where
    [TValue; N]: PartialEq
{
}

impl<TMarker: ?Sized, TValue, const N: usize> From<[TValue; N]> for IdArray<TMarker, TValue, N> {
    fn from(value: [TValue; N]) -> Self {
        Self::from_array(value)
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> Hash for IdArray<TMarker, TValue, N>
where
    [TValue; N]: Hash,
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.as_array().hash(state)
    }

    fn hash_slice<H>(data: &[Self], state: &mut H)
    where
        H: Hasher,
    {
        let data = unsafe { transmute(data) };
        <[TValue; N]>::hash_slice(data, state)
    }
}

impl<TMarker: ?Sized, TValue, I: IdSliceIndex<IdSlice<TMarker, TValue>>, const N: usize> Index<I>
    for IdArray<TMarker, TValue, N>
{
    type Output = I::Output;

    fn index(&self, index: I) -> &Self::Output {
        index.index(self.as_id_slice())
    }
}

impl<TMarker: ?Sized, TValue, I: IdSliceIndex<IdSlice<TMarker, TValue>>, const N: usize> IndexMut<I>
    for IdArray<TMarker, TValue, N>
{
    fn index_mut(&mut self, index: I) -> &mut Self::Output {
        index.index_mut(self.as_mut_id_slice())
    }
}

#[allow(clippy::into_iter_on_ref)]
impl<'a, TMarker: ?Sized, TValue, const N: usize> IntoIterator for &'a IdArray<TMarker, TValue, N> {
    type Item = <&'a [TValue; N] as IntoIterator>::Item;
    type IntoIter = <&'a [TValue; N] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.as_array().into_iter()
    }
}

#[allow(clippy::into_iter_on_ref)]
impl<'a, TMarker: ?Sized, TValue, const N: usize> IntoIterator
    for &'a mut IdArray<TMarker, TValue, N>
{
    type Item = <&'a mut [TValue; N] as IntoIterator>::Item;
    type IntoIter = <&'a mut [TValue; N] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.as_mut_array().into_iter()
    }
}

impl<TMarker: ?Sized, TValue, const N: usize> IntoIterator for IdArray<TMarker, TValue, N> {
    type Item = <[TValue; N] as IntoIterator>::Item;
    type IntoIter = <[TValue; N] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.into_array().into_iter()
    }
}

impl<TMarker: ?Sized, TValue: Ord, const N: usize> Ord for IdArray<TMarker, TValue, N> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.as_array().cmp(other.as_array())
    }

    fn max(self, other: Self) -> Self
    where
        Self: Sized,
    {
        Self::from_array(self.into_array().max(other.into_array()))
    }

    fn min(self, other: Self) -> Self
    where
        Self: Sized,
    {
        Self::from_array(self.into_array().min(other.into_array()))
    }

    fn clamp(self, min: Self, max: Self) -> Self
    where
        Self: Sized,
        Self: PartialOrd,
    {
        Self::from_array(self.into_array().clamp(min.into_array(), max.into_array()))
    }
}

impl<'a, TMarker: ?Sized, TValueA, TValueB, const N: usize> PartialEq<&'a IdSlice<TMarker, TValueB>>
    for IdArray<TMarker, TValueA, N>
where
    [TValueA; N]: PartialEq<&'a [TValueB]>,
{
    fn eq(&self, other: &&'a IdSlice<TMarker, TValueB>) -> bool {
        self.as_array().eq(&other.as_slice())
    }

    #[allow(clippy::partialeq_ne_impl)]
    fn ne(&self, other: &&'a IdSlice<TMarker, TValueB>) -> bool {
        self.as_array().ne(&other.as_slice())
    }
}

impl<'a, TMarker: ?Sized, TValueA, TValueB, const N: usize>
    PartialEq<&'a mut IdSlice<TMarker, TValueB>> for IdArray<TMarker, TValueA, N>
where
    [TValueA; N]: PartialEq<&'a mut [TValueB]>,
{
    fn eq(&self, other: &&'a mut IdSlice<TMarker, TValueB>) -> bool {
        let other: &&'a mut _ = unsafe { transmute(other) };
        self.as_array().eq(other)
    }

    #[allow(clippy::partialeq_ne_impl)]
    fn ne(&self, other: &&'a mut IdSlice<TMarker, TValueB>) -> bool {
        let other: &&'a mut _ = unsafe { transmute(other) };
        self.as_array().ne(other)
    }
}

impl<TMarker: ?Sized, TValueA, TValueB, const N: usize> PartialEq<IdSlice<TMarker, TValueB>>
    for IdArray<TMarker, TValueA, N>
where
    [TValueA; N]: PartialEq<[TValueB]>,
{
    fn eq(&self, other: &IdSlice<TMarker, TValueB>) -> bool {
        self.as_array().eq(other.as_slice())
    }

    #[allow(clippy::partialeq_ne_impl)]
    fn ne(&self, other: &IdSlice<TMarker, TValueB>) -> bool {
        self.as_array().ne(other.as_slice())
    }
}

impl<TMarker: ?Sized, TValueA, TValueB, const N: usize> PartialEq<IdArray<TMarker, TValueB, N>>
    for IdArray<TMarker, TValueA, N>
where
    [TValueA; N]: PartialEq<[TValueB; N]>,
{
    fn eq(&self, other: &IdArray<TMarker, TValueB, N>) -> bool {
        self.as_array().eq(other.as_array())
    }

    #[allow(clippy::partialeq_ne_impl)]
    fn ne(&self, other: &IdArray<TMarker, TValueB, N>) -> bool {
        self.as_array().ne(other.as_array())
    }
}

#[allow(clippy::non_canonical_partial_ord_impl)]
impl<TMarker: ?Sized, TValue: PartialOrd, const N: usize> PartialOrd
    for IdArray<TMarker, TValue, N>
{
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_array().partial_cmp(other.as_array())
    }

    fn lt(&self, other: &Self) -> bool {
        self.as_array().lt(other.as_array())
    }

    fn le(&self, other: &Self) -> bool {
        self.as_array().le(other.as_array())
    }

    fn gt(&self, other: &Self) -> bool {
        self.as_array().gt(other.as_array())
    }

    fn ge(&self, other: &Self) -> bool {
        self.as_array().ge(other.as_array())
    }
}