1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Marker traits to ease integration with traditional Rust code

use crate::engine::Eval;
use ::typenum as tn;

/// An expression that evaluates to `True`
pub trait Pass: Eval<Result=tn::True> {}
impl<T> Pass for T where T:Eval<Result=tn::True> {}


/// An expression that evaluates to `False`
pub trait Fail: Eval<Result=tn::False> {}
impl<T> Fail for T where T:Eval<Result=tn::False> {}

pub trait List: internal::List {
    type Head;
    type Tail: internal::List;
    type IsEOL;
    const LEN: usize;

    fn split(self)->(<Self as List>::Head, <Self as List>::Tail);

    fn head(&self)->&Self::Head;
    fn tail(&self)->&Self::Tail;

    fn into_iter_as<X>(self)->Self::ListIter where Self:ListOf<X> {
        self.list_of_iter()
    }
}

pub trait ListOf<X>: List + Sized {
    type ListIter: Iterator<Item=X>;
    fn list_of_iter(self)->Self::ListIter;
}

impl<X> ListOf<X> for crate::HNil {
    type ListIter = std::iter::Empty<X>;
    fn list_of_iter(self)->Self::ListIter {
        std::iter::empty()
    }
}

impl<H,T,X> ListOf<X> for crate::HCons<H,T>
where T: ListOf<X>, H:Into<X> {
    type ListIter = std::iter::Chain<std::iter::Once<X>, T::ListIter>;
    fn list_of_iter(self)->Self::ListIter {
        std::iter::once(self.head.into()).chain(self.tail.list_of_iter())
    }
}

pub struct RefIter<'a,X:?Sized>(&'a dyn ListOfRefs<X>);

impl<'a,X:?Sized> Iterator for RefIter<'a,X> {
    type Item = &'a X;
    fn next(&mut self)->Option<&'a X> {
        let result = self.0.head_ref();
        self.0 = self.0.tail_ref();
        result
    }
}

pub trait ListOfRefs<X:?Sized> {
    fn iter(&self)->RefIter<'_,X> where Self:Sized { RefIter(self) }
    fn head_ref(&self)->Option<&X>;
    fn tail_ref(&self)->&dyn ListOfRefs<X>;
}

impl<X:?Sized> ListOfRefs<X> for crate::HNil {
    fn head_ref(&self)->Option<&X> { None }
    fn tail_ref(&self)->&dyn ListOfRefs<X> { self }
}

impl<H,T,X:?Sized> ListOfRefs<X> for crate::HCons<H,T>
where T: ListOfRefs<X>, H:AsRef<X> {
    fn head_ref(&self)->Option<&X> { Some(self.head.as_ref()) }
    fn tail_ref(&self)->&dyn ListOfRefs<X> { &self.tail }
}

impl<T> List for T where T:internal::List {
    type Head = <Self as internal::List>::IHead;
    type Tail = <Self as internal::List>::ITail;
    type IsEOL = <Self as internal::List>::IIsEOL;
    const LEN:usize = <Self as internal::List>::ILEN;

    #[inline(always)]
    fn split(self)->(<Self as List>::Head, <Self as List>::Tail) { self.i_split() }
    #[inline(always)]
    fn head(&self)->&Self::Head { self.i_head() }
    #[inline(always)]
    fn tail(&self)->&Self::Tail { self.i_tail() }
}

mod internal {
    pub trait List {
        type IHead;
        type ITail: List;
        type IIsEOL;
        const ILEN:usize;

        fn i_split(self)->(Self::IHead, Self::ITail);
        fn i_head(&self)->&Self::IHead;
        fn i_tail(&self)->&Self::ITail;
    }

    impl List for crate::HNil {
        type IHead = Self;
        type ITail = Self;
        type IIsEOL = ::typenum::True;
        const ILEN:usize = 0;

        #[inline(always)]
        fn i_split(self)->(Self,Self) { (crate::HNil, crate::HNil) }
        #[inline(always)]
        fn i_head(&self)->&Self::IHead { self }
        #[inline(always)]
        fn i_tail(&self)->&Self::ITail { self }
    }

    impl<H,T:List> List for crate::HCons<H,T>
    {
        type IHead = H;
        type ITail = T;
        type IIsEOL = ::typenum::False;
        const ILEN: usize = 1+T::ILEN;

        #[inline(always)]
        fn i_split(self)->(H,T) { let crate::HCons { head: h, tail: t} = self; (h,t) }
        #[inline(always)]
        fn i_head(&self)->&Self::IHead { &self.head }
        #[inline(always)]
        fn i_tail(&self)->&Self::ITail { &self.tail }
    }
}