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
use bit_field::BitField;
pub struct WiegandFormat {
pub parity_even: usize,
pub parity_odd: usize,
pub facility_code: (usize, usize),
pub card_number: (usize, usize),
}
#[derive(Debug)]
pub enum WiegandError {
InvalidParity,
InvalidRange,
}
impl WiegandFormat {
pub fn decode(self, i: u32) -> Result<(u8, u16), WiegandError> {
let facility_code = i.get_bits(self.facility_code.0..self.facility_code.1) as u8;
let card_number = i.get_bits(self.card_number.0..self.card_number.1) as u16;
Ok((facility_code, card_number))
}
pub fn to_string(self, i: u32) -> String {
let parity_bit_odd = parity_sum(i, self.card_number) % 2 == 0;
let parity_bit_even = parity_sum(i, self.facility_code) % 2 == 1;
format!(
"{:b}{:b}{:b}",
parity_bit_even as u8, i, parity_bit_odd as u8
)
}
}
fn parity_sum(i: u32, range: (usize, usize)) -> u8 {
let mut sum = 0;
for bit_index in range.0..=range.1 {
let bit_set = i & (1 << bit_index) != 0;
sum += if bit_set { 1 } else { 0 };
}
sum % 2
}
#[cfg(test)]
mod tests {
use super::WiegandFormat;
#[test]
fn standard_format() {
let standard_wiegand = WiegandFormat {
parity_even: 0,
parity_odd: 25,
card_number: (0, 16),
facility_code: (16, 24),
};
let rfid_payload = 5666862u32;
assert_eq!(standard_wiegand.decode(rfid_payload).unwrap(), (86u8, 30766u16));
}
}