【发布时间】:2022-07-06 02:27:53
【问题描述】:
我通过串口发送和接收原始二进制数据,所以我有一个预定义的消息存储在u8 向量中。我需要计算 16 位 CRC 并在发送之前将其附加到末尾,但是我一直遇到强制转换和整数溢出的问题。这就是我之前在 C 中进行计算的方式:
void Serial::AddCRC(void *data, int len, void *checksum)
{
uint8_t *dataPtr = (uint8_t *)data;
uint8_t *crcPtr = (uint8_t *)checksum;
uint16_t crc = 0x0;
unsigned char x;
int byteCount = 0;
while ((len--) > 0) {
x = (unsigned char)(crc >> 8 ^ dataPtr[byteCount++]);
x ^= (unsigned char)(x >> 4);
crc = (uint16_t)((crc << 8) ^ (x << 12) ^ (x << 5) ^ x);
}
crcPtr[0] = crc >> 8;
crcPtr[1] = crc &0x00ff;
}
我尝试在 rust 中做类似的事情,但首先遇到了一些借用检查器问题,所以我尝试简化它,只编写一个函数来计算 crc 并返回 u16 结果,而不需要改变向量:
#[allow(overflowing_literals)]
pub fn checksum(msg: &Vec<u8>) -> u16{
if msg.len() == 0 {return 0}
let crc: u16 = 0x0;
let x: u16;
for byte in msg.iter() {
x = crc >> 8 ^ byte;
x ^= x >> 4;
crc = (crc << 8) ^ (x << 12) ^ (x << 5) ^ x;
}
crc
}
但是我找不到方法来完成这项工作。上面发布的代码无法编译,因为我无法在u8 和u16 之间执行按位异或,但是数据被视为u8s,因为它的原始字节,所以不能改变。我可以将mut 添加到向量并使其可变然后转换为u16 但这似乎是一种冒险的方式,我不应该需要改变向量来计算校验和:
error[E0308]: mismatched types
--> vips_interface/src\beacon_comms.rs:14:24
|
14 | x = crc >> 8 ^ byte;
| ^^^^ expected `u16`, found `u8`
error[E0277]: no implementation for `u16 ^ &u8`
--> vips_interface/src\beacon_comms.rs:14:22
|
14 | x = crc >> 8 ^ byte;
| ^ no implementation for `u16 ^ &u8`
在 rust 中实现类似功能的最佳方法是什么? rust 编译器非常适合捕获整数类型溢出,但不幸的是,这是 CRC 工作原理的关键部分,因此我允许溢出的文字,但这似乎并没有解决它。我查看了一些提到 CRC 计算的 crate,但它们都没有提供我想要的东西,而且它的计算相当简单,所以我宁愿将其用作学习练习。
【问题讨论】: