1#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
9pub struct BitArray {
10 bits: u128,
11}
12
13const WIDTH: u32 = 128;
15
16impl BitArray {
17 pub fn new() -> Self {
19 Self::default()
20 }
21
22 pub fn set_bit(&mut self, index: u32) {
28 if index < WIDTH {
29 self.bits |= 1u128 << (WIDTH - 1 - index);
30 }
31 }
32
33 pub fn bit(&self, index: u32) -> bool {
35 index < WIDTH && (self.bits >> (WIDTH - 1 - index)) & 1 == 1
36 }
37
38 pub fn reset(&mut self) {
40 self.bits = 0;
41 }
42
43 pub fn is_empty(&self) -> bool {
45 self.bits == 0
46 }
47
48 pub fn mask1(&self) -> u16 {
50 (self.bits >> (WIDTH - 15)) as u16
51 }
52
53 pub fn mask2(&self) -> u32 {
55 ((self.bits >> (WIDTH - 46)) & 0x7FFF_FFFF) as u32
56 }
57
58 pub fn mask3(&self) -> u64 {
60 (self.bits >> (WIDTH - 110)) as u64
61 }
62
63 pub fn mask3_draft03(&self) -> u64 {
70 self.mask3() >> 1
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 fn mask_of(set_bits: &[u32]) -> BitArray {
79 let mut mask = BitArray::new();
80 for &bit in set_bits {
81 mask.set_bit(bit);
82 }
83 mask
84 }
85
86 #[test]
87 fn bits_are_indexed_from_the_most_significant() {
88 let mask = mask_of(&[0]);
89 assert!(mask.bit(0), "bit 0 is the leftmost");
90 assert!(!mask.bit(1));
91 assert_eq!(
92 0x4000,
93 mask.mask1(),
94 "and lands at the top of the 15-bit mask"
95 );
96 }
97
98 #[test]
99 fn setting_and_reading_round_trips_across_the_whole_width() {
100 let mut mask = BitArray::new();
101 for index in 0..WIDTH {
102 assert!(!mask.bit(index));
103 mask.set_bit(index);
104 assert!(mask.bit(index), "bit {index}");
105 }
106 for index in 0..WIDTH {
107 assert!(mask.bit(index), "bit {index} still set");
108 }
109 }
110
111 #[test]
112 fn an_out_of_range_index_is_ignored() {
113 let mut mask = BitArray::new();
114 mask.set_bit(WIDTH);
115 mask.set_bit(u32::MAX);
116 assert!(mask.is_empty(), "no bit was set, and nothing panicked");
117 assert!(!mask.bit(WIDTH));
118 }
119
120 #[test]
121 fn reset_clears_everything() {
122 let mut mask = mask_of(&[0, 64, 127]);
123 assert!(!mask.is_empty());
124 mask.reset();
125 assert!(mask.is_empty());
126 assert_eq!(0, mask.mask1());
127 assert_eq!(0, mask.mask3());
128 }
129
130 #[test]
136 fn mask_extraction_matches_upstream_vectors() {
137 struct Case {
138 name: &'static str,
139 set_bits: &'static [u32],
140 mask1: u16,
141 mask2: u32,
142 mask3: u64,
143 mask3_draft03: u64,
144 }
145
146 let cases = [
147 Case {
148 name: "empty",
149 set_bits: &[],
150 mask1: 0,
151 mask2: 0,
152 mask3: 0,
153 mask3_draft03: 0,
154 },
155 Case {
156 name: "one bit in each mask",
157 set_bits: &[5, 20, 50],
158 mask1: 0x200,
159 mask2: 0x2000000,
160 mask3: 0x800000000000000,
161 mask3_draft03: 0x400000000000000,
162 },
163 Case {
164 name: "several bits in each mask",
165 set_bits: &[0, 7, 14, 15, 30, 45, 46, 80, 108, 109],
166 mask1: 0x4081,
167 mask2: 0x40008001,
168 mask3: 0x8000000020000003,
169 mask3_draft03: 0x4000000010000001,
170 },
171 Case {
172 name: "the boundaries of each mask",
173 set_bits: &[0, 14, 15, 45, 46, 108, 109],
174 mask1: 0x4001,
175 mask2: 0x40000001,
176 mask3: 0x8000000000000003,
177 mask3_draft03: 0x4000000000000001,
178 },
179 ];
180
181 for case in cases {
182 let mask = mask_of(case.set_bits);
183 assert_eq!(case.mask1, mask.mask1(), "mask1, {}", case.name);
184 assert_eq!(case.mask2, mask.mask2(), "mask2, {}", case.name);
185 assert_eq!(case.mask3, mask.mask3(), "mask3, {}", case.name);
186 assert_eq!(
187 case.mask3_draft03,
188 mask.mask3_draft03(),
189 "draft-03 mask3, {}",
190 case.name
191 );
192 }
193 }
194
195 #[test]
198 fn the_three_masks_partition_the_covered_range() {
199 for index in 0..15 {
200 let mask = mask_of(&[index]);
201 assert_ne!(0, mask.mask1(), "bit {index} belongs to mask1");
202 assert_eq!(0, mask.mask2());
203 assert_eq!(0, mask.mask3());
204 }
205 for index in 15..46 {
206 let mask = mask_of(&[index]);
207 assert_eq!(0, mask.mask1(), "bit {index} is not in mask1");
208 assert_ne!(0, mask.mask2(), "bit {index} belongs to mask2");
209 assert_eq!(0, mask.mask3());
210 }
211 for index in 46..110 {
212 let mask = mask_of(&[index]);
213 assert_eq!(0, mask.mask1());
214 assert_eq!(0, mask.mask2(), "bit {index} is not in mask2");
215 assert_ne!(0, mask.mask3(), "bit {index} belongs to mask3");
216 }
217 }
218
219 #[test]
222 fn draft03_loses_the_last_bit_the_rfc_mask_carries() {
223 let mask = mask_of(&[109]);
224 assert_eq!(1, mask.mask3(), "the RFC mask carries it");
225 assert_eq!(
226 0,
227 mask.mask3_draft03(),
228 "draft-03's mask is one bit narrower, so it falls off the end"
229 );
230 }
231}