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
use typenum::{IsEqual, B0, B1};
use crate::cons::{Cons, Nil};
use crate::label::Label;
pub struct True;
pub struct False;
pub trait Bool {
const VALUE: bool;
}
impl Bool for True {
const VALUE: bool = true;
}
impl Bool for False {
const VALUE: bool = false;
}
pub trait ToBool {
type Output: Bool;
}
impl ToBool for B1 {
type Output = True;
}
impl ToBool for B0 {
type Output = False;
}
pub trait LabelEq<L> {
type Output: Bool;
}
impl<L, M> LabelEq<M> for L
where
L: Label,
M: Label,
L::Uid: IsEqual<M::Uid>,
<L::Uid as IsEqual<M::Uid>>::Output: ToBool,
{
type Output = <<L::Uid as IsEqual<M::Uid>>::Output as ToBool>::Output;
}
pub trait Member<TargetL> {
type Output: Bool;
}
impl<TargetL> Member<TargetL> for Nil {
type Output = False;
}
impl<TargetL, L, T> Member<TargetL> for Cons<L, T>
where
L: Label + LabelEq<TargetL>,
Self: MemberMatch<TargetL, <L as LabelEq<TargetL>>::Output>,
{
type Output = <Self as MemberMatch<TargetL, <L as LabelEq<TargetL>>::Output>>::Output;
}
pub trait MemberMatch<L, HeadMatch> {
type Output: Bool;
}
impl<TargetL, L, T> MemberMatch<TargetL, True> for Cons<L, T> {
type Output = True;
}
impl<TargetL, L, T> MemberMatch<TargetL, False> for Cons<L, T>
where
L: Label,
T: Member<TargetL>,
{
type Output = <T as Member<TargetL>>::Output;
}
#[cfg(test)]
mod tests {
use crate::*;
#[label(name = "My Label", crate=crate)]
struct Label1;
#[label(type=u8, crate=crate)]
struct Label2;
#[label(crate=crate)]
struct Label3;
#[test]
fn label_eq() {
assert!(<Label1 as LabelEq<Label1>>::Output::VALUE);
assert!(<Label2 as LabelEq<Label2>>::Output::VALUE);
assert!(<Label3 as LabelEq<Label3>>::Output::VALUE);
assert!(!<Label1 as LabelEq<Label2>>::Output::VALUE);
assert!(!<Label1 as LabelEq<Label3>>::Output::VALUE);
assert!(!<Label2 as LabelEq<Label1>>::Output::VALUE);
assert!(!<Label2 as LabelEq<Label3>>::Output::VALUE);
assert!(!<Label3 as LabelEq<Label1>>::Output::VALUE);
assert!(!<Label3 as LabelEq<Label2>>::Output::VALUE);
}
#[test]
fn member() {
type TestList = LCons<Label1, LCons<Label2, Nil>>;
assert!(<TestList as Member<Label1>>::Output::VALUE);
assert!(<TestList as Member<Label2>>::Output::VALUE);
assert!(!<TestList as Member<Label3>>::Output::VALUE);
let list = labels![Label1, Label2];
assert!(list.has_label(Label1));
assert!(list.has_label(Label2));
assert!(!list.has_label(Label3));
}
}