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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#![doc(html_root_url = "https://docs.rs/bitpat/0.1.1")]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#[macro_export]
macro_rules! bitpat {
( @build $relevant:tt $ones:tt [] ) => {
|value| value & ($relevant) == ($ones)
};
( @build $relevant:tt $ones:tt [$next:tt $($rest:tt)*] ) => {
bitpat!(@build ($relevant << 1 | bitpat!(@relevant $next)) ($ones << 1 | bitpat!(@is_one $next)) [$($rest)*])
};
( @relevant _ ) => { 0 };
( @relevant 0 ) => { 1 };
( @relevant 1 ) => { 1 };
( @is_one _ ) => { 0 };
( @is_one 0 ) => { 0 };
( @is_one 1 ) => { 1 };
( $($part:tt)+ ) => {bitpat!(@build 0 0 [$($part)+])};
}
#[cfg(test)]
mod tests {
#[test]
fn mask() {
assert!(bitpat!(0 0 _ _ 1 _ _ _)(0b00111111));
assert!(bitpat!(0 0 _ _ 1 _ _ _)(0b00001111));
assert!(bitpat!(0 0 _ _ 1 _ _ _)(0b00001000));
assert!(bitpat!(0 0 _ _ 1 _ _ _)(0b00001110));
assert!(!bitpat!(0 0 _ _ 1 _ _ _)(0b01111111));
assert!(!bitpat!(0 0 _ _ 1 _ _ _)(0b10111111));
assert!(!bitpat!(0 0 _ _ 1 _ _ _)(0b00110111));
for b in 0..255u8 {
assert_eq!(bitpat!(1 _ _ _ _ _ _ _)(b), b >= 128);
assert_eq!(bitpat!(0 _ _ _ _ _ _ _)(b), b < 128);
}
for b in 0..255u8 {
assert_eq!(bitpat!(_ _ _ _ _ _ _ 1)(b), b & 1 != 0);
assert_eq!(bitpat!(_ _ _ _ _ _ _ 0)(b), b & 1 == 0);
}
for b in 0..255u8 {
assert!(bitpat!(_ _ _ _ _ _ _ _)(b));
}
for b in 1..255u8 {
assert!(!bitpat!(0 0 0 0 0 0 0 0)(b));
}
}
#[test]
fn mask_too_short() {
assert!(bitpat!(_ _ _ _)(0b11110000));
assert!(bitpat!(_ _ _ _)(0b11111111));
assert!(bitpat!(_ _ _ _)(0b11110001));
assert!(bitpat!(_ _ _ _)(0b0000));
assert!(bitpat!(0 0 0 0)(0b11110000));
assert!(bitpat!(0 0 0 0)(0b1110000));
assert!(bitpat!(0 0 0 0)(0b110000));
assert!(bitpat!(0 0 0 0)(0b10000));
assert!(bitpat!(0 0 0 0)(0b0000));
assert!(bitpat!(1 1 1 1)(0b11111111));
assert!(bitpat!(1 1 1 1)(0b1111111));
assert!(bitpat!(1 1 1 1)(0b111111));
assert!(bitpat!(1 1 1 1)(0b11111));
assert!(bitpat!(1 1 1 1)(0b1111));
}
#[test]
fn mask_too_long() {
assert!(bitpat!(_ _ _ _ _ _ _ _ _)(0b11110000u8));
assert!(bitpat!(0 _ _ _ _ _ _ _ _)(0b11110000u8));
assert!(bitpat!(1 _ _ _ _ _ _ _ _)(0b11110000u8));
assert!(bitpat!(1 1 _ _ _ _ _ _ _)(0b11110000u8));
assert!(bitpat!(0 1 _ _ _ _ _ _ _)(0b11110000u8));
assert!(bitpat!(1 0 _ _ _ _ _ _ _)(0b01110000u8));
assert!(bitpat!(0 0 _ _ _ _ _ _ _)(0b01110000u8));
assert!(!bitpat!(1 1 _ _ _ _ _ _ _)(0b11110000));
assert!( bitpat!(0 1 _ _ _ _ _ _ _)(0b11110000));
assert!( bitpat!(_ 1 _ _ _ _ _ _ _)(0b11110000));
}
}