1#[derive(Debug, Default)]
2pub struct OneWireCrc(u8);
4
5impl OneWireCrc {
6 pub fn value(&self) -> u8 {
8 self.0
9 }
10
11 #[inline(always)]
20 pub fn update(&mut self, byte: u8) {
21 #[cfg(feature = "crc-table")]
22 {
23 self.update_table(byte); }
25 #[cfg(not(feature = "crc-table"))]
26 {
27 self.update_calc(byte); }
29 }
30
31 pub fn validate(sequence: &[u8]) -> bool {
37 let mut crc = OneWireCrc(0);
38 for &byte in sequence.iter() {
39 crc.update(byte); }
41 crc.0 == 0x0 }
43
44 #[allow(dead_code)]
45 pub(crate) fn update_table(&mut self, byte: u8) {
46 const ONEWIRE_SRC_TABLE: [u8; 256] = [
47 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33,
48 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28,
49 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124,
50 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102,
51 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196,
52 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166,
53 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237,
54 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146,
55 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209,
56 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207,
57 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87,
58 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11,
59 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169,
60 247, 182, 232, 10, 84, 215, 137, 107, 53,
61 ];
62 self.0 = ONEWIRE_SRC_TABLE[(self.0 ^ byte) as usize];
63 }
64
65 #[allow(dead_code)]
66 pub(crate) fn update_calc(&mut self, byte: u8) {
67 let mut crc = self.0 ^ byte;
68 for _ in 0..8 {
69 if crc & 0x01 == 0x01 {
70 crc = (crc >> 1) ^ 0x8C; } else {
72 crc >>= 1;
73 }
74 }
75 self.0 = crc;
76 }
77}
78
79mod test {
80 #[test]
81 fn test_crc_update() {
82 use super::OneWireCrc;
83 #[cfg(test)]
84 extern crate std;
85 use rand::prelude::*;
86 let mut rng = rand::rng();
87 let buf = (0..100)
88 .map(|_| rng.random::<u8>())
89 .collect::<std::vec::Vec<u8>>();
90 let mut crc = OneWireCrc::default();
91 for &byte in buf.iter() {
92 crc.update(byte);
93 }
94 let table = crc.value();
95 std::println!("CRC after calc: {table:#04x}");
96 let mut crc = OneWireCrc::default();
97 for &byte in buf.iter() {
98 crc.update_table(byte);
99 }
100 let calc = crc.value();
101 std::println!("CRC after table: {calc:#04x}");
102 assert_eq!(table, calc, "CRC values do not match");
103 }
104}