finit 0.4.0

Finit is a library for defining sets of data, and then performing set operations on them. It is designed to be used for permission systems, but can be used for any kind of data that can be represented as a set.
Documentation
use crate::Set;
use crate::operations::{
    Difference, DifferenceAssign, DisjunctiveUnion, DisjunctiveUnionAssign, Intersection,
    IntersectionAssign, Union, UnionAssign,
};
use crate::comparisons::{SetEq, SubsetOf};

impl<const N: usize, Value: Set<Empty = Value>> Set for [Value; N] {
    type Empty = Self;

    fn is_empty(&self) -> bool {
        self.iter().all(|value| value.is_empty())
    }

    fn empty() -> Self::Empty {
        core::array::from_fn(|_| Value::empty())
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set> UnionAssign<[OtherValue; N]>
    for [Value; N]
where
    Value: UnionAssign<OtherValue>,
{
    fn union_assign(&mut self, rhs: [OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.into_iter()) {
            self_i.union_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set> Union<[OtherValue; N]>
    for [Value; N]
where
    Value: UnionAssign<OtherValue>,
{
    type Output = Self;

    fn union(mut self, rhs: [OtherValue; N]) -> Self::Output {
        self.union_assign(rhs);

        self
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    DifferenceAssign<[OtherValue; N]> for [Value; N]
where
    Value: DifferenceAssign<OtherValue>,
{
    fn difference_assign(&mut self, rhs: [OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.into_iter()) {
            self_i.difference_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    Difference<[OtherValue; N]> for [Value; N]
where
    Value: DifferenceAssign<OtherValue>,
{
    type Output = Self;

    fn difference(mut self, rhs: [OtherValue; N]) -> Self::Output {
        self.difference_assign(rhs);

        self
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    IntersectionAssign<[OtherValue; N]> for [Value; N]
where
    Value: IntersectionAssign<OtherValue>,
{
    fn intersection_assign(&mut self, rhs: [OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.into_iter()) {
            self_i.intersection_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    Intersection<[OtherValue; N]> for [Value; N]
where
    Value: IntersectionAssign<OtherValue>,
{
    type Output = Self;
    fn intersection(mut self, other: [OtherValue; N]) -> Self::Output {
        self.intersection_assign(other);

        self
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set>
    DisjunctiveUnionAssign<[OtherValue; N]> for [Value; N]
where
    Value: DisjunctiveUnionAssign<OtherValue>,
{
    fn disjunctive_union_assign(&mut self, rhs: [OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.into_iter()) {
            self_i.disjunctive_union_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set> DisjunctiveUnion<[OtherValue; N]>
    for [Value; N]
where
    Value: DisjunctiveUnionAssign<OtherValue>,
{
    type Output = Self;

    fn disjunctive_union(mut self, rhs: [OtherValue; N]) -> Self::Output {
        self.disjunctive_union_assign(rhs);

        self
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set> UnionAssign<&[OtherValue; N]>
    for [Value; N]
where
    for<'a> Value: UnionAssign<&'a OtherValue>,
{
    fn union_assign(&mut self, rhs: &[OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.iter()) {
            self_i.union_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set> Union<&[OtherValue; N]>
    for [Value; N]
where
    for<'a> Value: UnionAssign<&'a OtherValue>,
{
    type Output = Self;

    fn union(mut self, rhs: &[OtherValue; N]) -> Self::Output {
        self.union_assign(rhs);

        self
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    DifferenceAssign<&[OtherValue; N]> for [Value; N]
where
    for<'a> Value: DifferenceAssign<&'a OtherValue>,
{
    fn difference_assign(&mut self, rhs: &[OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.iter()) {
            self_i.difference_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    Difference<&[OtherValue; N]> for [Value; N]
where
    for<'a> Value: DifferenceAssign<&'a OtherValue>,
{
    type Output = Self;

    fn difference(mut self, rhs: &[OtherValue; N]) -> Self::Output {
        self.difference_assign(rhs);

        self
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    IntersectionAssign<&[OtherValue; N]> for [Value; N]
where
    for<'a> Value: IntersectionAssign<&'a OtherValue>,
{
    fn intersection_assign(&mut self, rhs: &[OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.iter()) {
            self_i.intersection_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set<Empty = OtherValue>>
    Intersection<&[OtherValue; N]> for [Value; N]
where
    for<'a> Value: IntersectionAssign<&'a OtherValue>,
{
    type Output = Self;
    fn intersection(mut self, other: &[OtherValue; N]) -> Self::Output {
        self.intersection_assign(other);

        self
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set>
    DisjunctiveUnionAssign<&[OtherValue; N]> for [Value; N]
where
    for<'a> Value: DisjunctiveUnionAssign<&'a OtherValue>,
{
    fn disjunctive_union_assign(&mut self, rhs: &[OtherValue; N]) {
        for (self_i, rhs_i) in self.iter_mut().zip(rhs.iter()) {
            self_i.disjunctive_union_assign(rhs_i);
        }
    }
}

impl<const N: usize, Value: Set<Empty = Value>, OtherValue: Set> DisjunctiveUnion<&[OtherValue; N]>
    for [Value; N]
where
    for<'a> Value: DisjunctiveUnionAssign<&'a OtherValue>,
{
    type Output = Self;

    fn disjunctive_union(mut self, rhs: &[OtherValue; N]) -> Self::Output {
        self.disjunctive_union_assign(rhs);

        self
    }
}

impl<const N: usize, Value: SetEq<OtherValue>, OtherValue> SetEq<[OtherValue; N]>
    for [Value; N]
{
    fn set_eq(&self, rhs: &[OtherValue; N]) -> bool {
        self.iter().zip(rhs.iter()).all(|(self_v, rhs_v)| self_v.set_eq(rhs_v))
    }
}

impl<const N: usize, Value: SubsetOf<OtherValue>, OtherValue> SubsetOf<[OtherValue; N]>
    for [Value; N]
{
    fn subset_of(&self, rhs: &[OtherValue; N]) -> bool {
        self.iter().zip(rhs.iter()).all(|(self_v, rhs_v)| self_v.subset_of(rhs_v))
    }
}

#[cfg(test)]
mod tests {
    use core::fmt::Debug;

    use rstest::*;

    use crate::operations::Union;

    #[allow(unused_imports)]
    use super::*;

    #[rstest]
    #[case([true, false, false, true], [false, true, false, true], [true, true, false, true])]
    fn union_list_tests<T, U, V>(#[case] a: T, #[case] b: U, #[case] c: V)
    where
        T: for<'a> Union<&'a U, Output = V>,
        V: PartialEq + Debug,
    {
        assert_eq!(a.union(&b), c);
    }

    #[rstest]
    #[case([true, false, false, true], [false, true, false, true], [true, false, false, false])]
    fn difference_list_tests<T, U, V>(#[case] a: T, #[case] b: U, #[case] c: V)
    where
        T: for<'a> Difference<&'a U, Output = V>,
        V: PartialEq + Debug,
    {
        assert_eq!(a.difference(&b), c);
    }

    #[rstest]
    #[case([true, false, false, true], [false, true, false, true], [false, false, false, true])]
    fn intersection_list_tests<T, U, V>(#[case] a: T, #[case] b: U, #[case] c: V)
    where
        T: for<'a> Intersection<&'a U, Output = V>,
        V: PartialEq + Debug,
    {
        assert_eq!(a.intersection(&b), c);
    }
}