【发布时间】:2014-11-17 13:54:23
【问题描述】:
假设我们有以下 C 代码(假设 srclen == dstlen 并且长度可以被 64 整除)。
void stream(uint8_t *dst, uint8_t *src, size_t dstlen) {
int i;
uint8_t block[64];
while (dstlen > 64) {
some_function_that_initializes_block(block);
for (i=0; i<64; i++) {
dst[i] = ((src != NULL)?src[i]:0) ^ block[i];
}
dst += 64;
dstlen -= 64;
if (src != NULL) { src += 64; }
}
}
这是一个函数,它接受一个源和一个目标,并 xor 具有某个值的源 函数计算。当 source 设置为 NULL 指针时,dst 只是计算值。
在 rust 中,当 src 不能为空时,这样做很简单,我们可以这样做:
fn stream(dst: &mut [u8], src: &[u8]) {
let mut block = [0u8, ..64];
for (dstchunk, srcchunk) in dst.chunks_mut(64).zip(src.chunks(64)) {
some_function_that_initializes_block(block);
for (d, (&s, &b)) in dstchunk.iter_mut().zip(srcchunk.iter().zip(block.iter())) {
*d = s ^ b;
}
}
}
但是,让我们假设我们希望能够模仿原始的 C 函数。然后我们想做类似的事情:
fn stream(dst: &mut[u8], osrc: Option<&[u8]>) {
let srciter = match osrc {
None => repeat(0),
Some(src) => src.iter()
};
// the rest of the code as above
}
唉,这是行不通的,因为 repeat(0) 和 src.iter() 有不同的类型。然而,似乎不可能通过使用 trait 对象来解决这个问题,因为我们得到一个编译器错误,说 cannot convert to a trait object because trait 'core::iter::Iterator' is not object safe.(标准库中也没有对迭代器进行分块的函数)。
有什么好的方法可以解决这个问题,还是我应该在 match 语句的每个分支中复制代码?
【问题讨论】:
-
C 版本中的循环条件看起来很奇怪。
srclen在循环中永远不会被修改,如果它最初大于 64,则使其无限。 -
谢谢。编辑了帖子
标签: rust