cons_cell 0.1.0

Swiss knife for heterogenous containers
Documentation
use crate::cons::traits::switches::contains_switch::ContainsSwitch;
use crate::cons::{Cons, ConsCell, Extend};
use typenum::{Bit, False, True};
use typenum_uuid_trait::TypeId;

pub trait InsertIfAbsent<T: TypeId>: ConsCell {
    type Result: Cons;

    fn insert_if_absent(self, t: T) -> Self::Result;
}

impl<T: TypeId, C: ConsCell> InsertIfAbsent<T> for C
where
    Self: ContainsSwitch<T>,
    Self: InsertIfAbsentHelper<T, <Self as ContainsSwitch<T>>::Value>,
{
    type Result = <Self as InsertIfAbsentHelper<T, <Self as ContainsSwitch<T>>::Value>>::Result;

    fn insert_if_absent(self, t: T) -> Self::Result {
        <Self as InsertIfAbsentHelper<T, <Self as ContainsSwitch<T>>::Value>>::insert_if_absent(
            self, t,
        )
    }
}

pub trait InsertIfAbsentHelper<T: TypeId, IsAbsent: Bit> {
    type Result: Cons;

    fn insert_if_absent(self, t: T) -> Self::Result;
}

impl<T: TypeId, C: Cons> InsertIfAbsentHelper<T, True> for C {
    type Result = Self;

    fn insert_if_absent(self, _t: T) -> Self::Result {
        self
    }
}

impl<T: TypeId, C: ConsCell> InsertIfAbsentHelper<T, False> for C
where
    Self: Extend<T>,
{
    type Result = <Self as Extend<T>>::Extension;

    fn insert_if_absent(self, t: T) -> Self::Result {
        Self::Result::new(t, self)
    }
}

#[cfg(test)]
mod tests {
    use crate::cons::test_types::{U8, U16};
    use crate::cons::traits::insert_if_absent::InsertIfAbsent;
    use crate::cons::traits::length::Length;
    use crate::cons::types::hcons::HNil;
    use crate::cons::{Cons, ConsCell};

    //TODO: Add tests for Nil.

    #[test]
    fn insert_absent() {
        let c = HNil::new().extend(U8(1));
        let new_c = c.insert_if_absent(U16(2));

        assert_eq!(new_c.len(), 2);
        assert_eq!(new_c.head(), &U16(2u16));
    }

    #[test]
    fn insert_present() {
        let c = HNil::new().extend(U8(1));
        let new_c = c.insert_if_absent(U8(2));

        assert_eq!(new_c.len(), 1);
        assert_eq!(new_c.head(), &U8(1u8));
    }
}