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};
#[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));
}
}