use crate::cons::Cons;
use typenum::{False, True};
use typenum_uuid_trait::{IsTypeEqual, TypeId};
pub trait Contains<Query: TypeId>: Cons {
fn get_first(&self) -> &Query;
}
impl<C: Cons, Query: TypeId + IsTypeEqual<C::Head>> Contains<Query> for C
where
C: ContainsHelper<Query, Query::Value>,
<C as Cons>::Head: TypeId,
{
#[inline(always)]
fn get_first(&self) -> &Query {
ContainsHelper::get_first(self)
}
}
pub trait ContainsHelper<Query: TypeId, IsEqual> {
fn get_first(&self) -> &Query;
}
impl<Query: TypeId, C: Cons<Head = Query>> ContainsHelper<Query, True> for C {
#[inline(always)]
fn get_first(&self) -> &Query {
self.head()
}
}
impl<Query: TypeId, C: Cons> ContainsHelper<Query, False> for C
where
C::Tail: Contains<Query>,
{
#[inline(always)]
fn get_first(&self) -> &Query {
self.tail().get_first()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cons::ConsCell;
use crate::cons::test_types::*;
use crate::cons::types::hcons::HNil;
#[test]
fn get_first_works() {
let x = HNil::new()
.extend(U8(1))
.extend(U16(2))
.extend(U8(3))
.extend(U32(4));
let i: &U8 = Contains::<U8>::get_first(&x);
assert_eq!(i, &U8(3));
}
}