use std::num::Wrapping;
pub fn crc_ihex<T>(data: T) -> u8
where
T: AsRef<[u8]>,
{
(0_u8).wrapping_sub(
data.as_ref()
.iter()
.fold(0, |acc, &value| acc.wrapping_add(value)),
)
}
pub fn crc_srec<T>(data: T) -> u8
where
T: AsRef<[u8]>,
{
!data
.as_ref()
.iter()
.map(|b| Wrapping(*b))
.sum::<Wrapping<u8>>()
.0
}
pub fn crc_ext_tek_hex<T>(data: T) -> u8
where
T: AsRef<[char]>,
{
let mut sum: u8 = 0;
for char in data.as_ref() {
let value = match char {
x if (&'0'..=&'9').contains(&x) => *x as u8 - b'0',
x if (&'A'..=&'Z').contains(&x) => *x as u8 - b'A' + 10,
'$' => 36,
'%' => 37,
'.' => 38,
'_' => 39,
x if (&'a'..=&'z').contains(&x) => *x as u8 - b'a' + 40,
_ => 0,
};
sum = sum.wrapping_add(value);
}
sum
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_checksum_empty() {
assert_eq!(crc_ihex([]), 0x00);
}
#[test]
fn test_checksum_eof_record() {
assert_eq!(crc_ihex([0x00, 0x00, 0x00, 0x01]), 0xFF);
}
#[test]
fn test_checksum_ela_record() {
assert_eq!(crc_ihex([0x02, 0x00, 0x00, 0x04, 0xFF, 0xFF]), 0xFC);
}
#[test]
fn test_ihex_crc() {
assert_eq!(crc_ihex([0x03, 0x00, 0x30, 0x00, 0x02, 0x33, 0x7a]), 0x1e);
assert_eq!(crc_ihex([0x00; 4]), 0x00);
}
#[test]
fn test_checksum_sla_record() {
assert_eq!(
crc_ihex([0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xCD]),
0x2A
);
}
#[test]
fn checksum_of_returns_correct_value() {
assert_eq!(
crc_srec([
0x13, 0x7a, 0xf0, 0x0a, 0x0a, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00
]),
0x61
);
assert_eq!(
crc_srec([
0x0f, 0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00,
0x00
]),
0x3c
);
assert_eq!(
crc_srec([
0x1f, 0x00, 0x00, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x04, 0x94, 0x21, 0xff,
0xf0, 0x7c, 0x6c, 0x1b, 0x78, 0x7c, 0x8c, 0x23, 0x78, 0x3c, 0x60, 0x00, 0x00, 0x38,
0x63, 0x00, 0x00
]),
0x26
);
assert_eq!(
crc_srec([
0x1f, 0x00, 0x1c, 0x4b, 0xff, 0xff, 0xe5, 0x39, 0x80, 0x00, 0x00, 0x7d, 0x83, 0x63,
0x78, 0x80, 0x01, 0x00, 0x14, 0x38, 0x21, 0x00, 0x10, 0x7c, 0x08, 0x03, 0xa6, 0x4e,
0x80, 0x00, 0x20
]),
0xe9
);
assert_eq!(
crc_srec([
0x11, 0x00, 0x38, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
0x2e, 0x0a, 0x00
]),
0x42
);
assert_eq!(crc_srec([0x03, 0x00, 0x03]), 0xf9);
assert_eq!(crc_srec([0x03, 0x00, 0x00]), 0xfc);
}
}