我通过串行端口发送和接收原始二进制数据,因此我在向量中存储了预定义的消息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;
}
Run Code Online (Sandbox Code Playgroud)
我尝试在 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
}
Run Code Online (Sandbox Code Playgroud)
但是我找不到一种方法来完成这项工作。上面发布的代码无法编译,因为我无法在 au8和 a之间执行按位异u16或,但是数据被视为u8s 因为它是原始字节,因此无法更改。我可以将 the 添加mut到向量中并使其可变,然后转换为 au16但这似乎是一种危险的做法,而且我不需要改变向量来计算校验和:
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`
Run Code Online (Sandbox Code Playgroud)
在 Rust 中实现类似功能的最佳方法是什么?rust 编译器非常适合捕获整数类型溢出,但不幸的是,这是 CRC 工作方式的关键部分,因此我允许溢出文字,但这似乎并没有解决它。我查看了一些提到 CRC 计算的包,但没有一个提供我想要的,而且它是一个相当简单的计算,所以我宁愿将其用作学习练习。
我没有看细节,只是编译了一下。
首先,Vec不需要,任何切片都适合(即使它来自 a Vec)。
byteu8是对该切片中a 的引用,因此*byte是 this 的副本u8(因为u8是Copy),然后我们可以将其转换为 a u16。
crc在循环中更新,因此需要限定符mut。
x是循环本地的,并且在几个步骤中更新,因此它mut也需要限定符。
注意:在您的 C++ 代码中,有(x << 12)withx声明为unsigned char。在 C/C++ 中,会发生整数提升,并且x会提升到int移位之前。在 Rust 中,如果x是 a u8,则这种转变在任何情况下都会给出零(Rust 抱怨这一点)。我x设 au16并取消高字节,但我不确定这是否是您想要的。
pub fn checksum(msg: &[u8]) -> u16 {
let mut crc: u16 = 0x0;
for byte in msg.iter() {
let mut x = ((crc >> 8) ^ (*byte as u16)) & 255;
x ^= x >> 4;
crc = (crc << 8) ^ (x << 12) ^ (x << 5) ^ x;
}
crc
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
694 次 |
| 最近记录: |