Skip to content
File

Blob: firmware/vendor/str0m/src/util/bit_pattern.rs

rust108 lines
1/// One byte bit pattern to allow matching against specific bits.
2#[derive(Copy, Clone)]
3pub(crate) struct BitPattern {
4 mask: u8,
5 masked_value: u8,
6}
7 
8impl BitPattern {
9 pub(crate) fn matches(&self, profile_iop: u8) -> bool {
10 ((profile_iop ^ self.masked_value) & self.mask) == 0x0
11 }
12 
13 /// Create a bit pattern. Use `1` for bits that must be set, `0` for bits that must not be
14 /// set, and `x` for bits that can take any value.
15 ///
16 /// Panics if any other byte values than ASCII `1`, `0`, or `x` is used.
17 pub(crate) const fn new(pattern: [u8; 8]) -> Self {
18 const fn bit_to_mask_bit(pattern: [u8; 8], i: usize) -> u8 {
19 let bit = pattern[7 - i];
20 match bit {
21 b'1' | b'0' => 0x1 << i,
22 b'x' => 0x0 << i,
23 _ => panic!("Invalid bit pattern in IOPPattern only ASCII 1, 0, and x are allowed"),
24 }
25 }
26 
27 const fn to_mask(pattern: [u8; 8]) -> u8 {
28 bit_to_mask_bit(pattern, 7)
29 | bit_to_mask_bit(pattern, 6)
30 | bit_to_mask_bit(pattern, 5)
31 | bit_to_mask_bit(pattern, 4)
32 | bit_to_mask_bit(pattern, 3)
33 | bit_to_mask_bit(pattern, 2)
34 | bit_to_mask_bit(pattern, 1)
35 | bit_to_mask_bit(pattern, 0)
36 }
37 
38 const fn bit_to_mask_value_bit(pattern: [u8; 8], i: usize) -> u8 {
39 let bit = pattern[7 - i];
40 match bit {
41 b'1' => 0x1 << i,
42 b'x' | b'0' => 0x0 << i,
43 _ => panic!("Invalid bit pattern in IOPPattern only ASCII 1, 0, and x are allowed"),
44 }
45 }
46 
47 const fn to_mask_value(pattern: [u8; 8]) -> u8 {
48 bit_to_mask_value_bit(pattern, 7)
49 | bit_to_mask_value_bit(pattern, 6)
50 | bit_to_mask_value_bit(pattern, 5)
51 | bit_to_mask_value_bit(pattern, 4)
52 | bit_to_mask_value_bit(pattern, 3)
53 | bit_to_mask_value_bit(pattern, 2)
54 | bit_to_mask_value_bit(pattern, 1)
55 | bit_to_mask_value_bit(pattern, 0)
56 }
57 let mask = to_mask(pattern);
58 let masked_value = to_mask_value(pattern);
59 
60 Self { mask, masked_value }
61 }
62}
63 
64#[cfg(test)]
65mod test {
66 use super::*;
67 
68 #[test]
69 fn test_iop_pattern_matching() {
70 let all_any = BitPattern::new(*b"xxxxxxxx");
71 for x in 0..255 {
72 assert!(all_any.matches(x));
73 }
74 
75 let stripes = BitPattern::new(*b"10101010");
76 assert!(stripes.matches(0b1010_1010));
77 assert!(!stripes.matches(0b1011_1010));
78 
79 let inverse_stripes = BitPattern::new(*b"01010101");
80 assert!(inverse_stripes.matches(0b0101_0101));
81 assert!(!inverse_stripes.matches(0b0111_0001));
82 
83 let high_bits = BitPattern::new(*b"1101xxxx");
84 assert!(high_bits.matches(0b1101_0101));
85 assert!(!high_bits.matches(0b1001_0101));
86 
87 let mid_bits = BitPattern::new(*b"xx0110xx");
88 assert!(mid_bits.matches(0b0101_1001));
89 assert!(!mid_bits.matches(0b1000_1001));
90 
91 let only_ones = BitPattern::new(*b"11111111");
92 assert!(only_ones.matches(0b1111_1111));
93 assert!(!only_ones.matches(0b1110_1111));
94 
95 let only_zeros = BitPattern::new(*b"00000000");
96 assert!(only_zeros.matches(0b0000_0000));
97 assert!(!only_zeros.matches(0b0000_0010));
98 
99 let mixed_pattern = BitPattern::new(*b"1x0x1x01");
100 assert!(mixed_pattern.matches(0b11011001));
101 assert!(!mixed_pattern.matches(0b11011011));
102 
103 let complex_pattern = BitPattern::new(*b"1xx01x0x");
104 assert!(complex_pattern.matches(0b10001001));
105 assert!(!complex_pattern.matches(0b10101010));
106 }
107}