1use bit_field::BitField;
2
3pub struct WiegandFormat {
6 pub parity_even: usize,
8 pub parity_odd: usize,
10 pub facility_code: (usize, usize),
12 pub card_number: (usize, usize),
14}
15
16#[derive(Debug)]
18pub enum WiegandError {
19 InvalidParity,
21 InvalidRange,
23}
24
25impl WiegandFormat {
26 pub fn decode(self, i: u32) -> Result<(u8, u16), WiegandError> {
28 let facility_code = i.get_bits(self.facility_code.0..self.facility_code.1) as u8;
29 let card_number = i.get_bits(self.card_number.0..self.card_number.1) as u16;
30
31 Ok((facility_code, card_number))
32 }
33
34 pub fn to_string(self, i: u32) -> String {
36 let parity_bit_odd = parity_sum(i, self.card_number) % 2 == 0;
37 let parity_bit_even = parity_sum(i, self.facility_code) % 2 == 1;
38
39 format!(
40 "{:b}{:b}{:b}",
41 parity_bit_even as u8, i, parity_bit_odd as u8
42 )
43 }
44}
45
46fn parity_sum(i: u32, range: (usize, usize)) -> u8 {
48 let mut sum = 0;
49
50 for bit_index in range.0..=range.1 {
51 let bit_set = i & (1 << bit_index) != 0;
52 sum += if bit_set { 1 } else { 0 };
53 }
54
55 sum % 2
56}
57
58#[cfg(test)]
59mod tests {
60 use super::WiegandFormat;
61
62 #[test]
63 fn standard_format() {
64 let standard_wiegand = WiegandFormat {
65 parity_even: 0,
66 parity_odd: 25,
67 card_number: (0, 16),
68 facility_code: (16, 24),
69 };
70
71 let rfid_payload = 5666862u32;
72
73 assert_eq!(standard_wiegand.decode(rfid_payload).unwrap(), (86u8, 30766u16));
74 }
75}