假设我们有以下 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; }
}
}
这是一个函数,它接受一个源和一个目标,并将源与某个值进行异或 函数计算。当 source 设置为 NULL 指针时,dst 只是计算值。
在 rust 中,当 src 不能为 null 时,这样做非常简单,我们可以这样做:
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.
(标准库中也没有将迭代器分块的函数)。
有什么好的方法可以解决这个问题,还是我应该在匹配语句的每个分支中复制代码?
最佳答案
您可以调用一个通用的内部函数,而不是在每个臂中重复代码:
fn stream(dst: &mut[u8], osrc: Option<&[u8]>) {
fn inner<T>(dst: &mut[u8], srciter: T) where T: Iterator<u8> {
let mut block = [0u8, ..64];
//...
}
match osrc {
None => inner(dst, repeat(0)),
Some(src) => inner(dst, src.iter().map(|a| *a))
}
}
注意附加的 map
使两个迭代器兼容(Iterator<u8>
)。
如您所述,Iterator
没有内置的分块方法。让我们合并 Vladimir 的解决方案并对 block 使用迭代器:
fn stream(dst: &mut[u8], osrc: Option<&[u8]>) {
const CHUNK_SIZE: uint = 64;
fn inner<'a, T>(dst: &mut[u8], srciter: T) where T: Iterator<&'a [u8]> {
let mut block = [0u8, ..CHUNK_SIZE];
for (dstchunk, srcchunk) in dst.chunks_mut(CHUNK_SIZE).zip(srciter) {
some_function_that_initializes_block(block);
for (d, (&s, &b)) in dstchunk.iter_mut().zip(srcchunk.iter().zip(block.iter())) {
*d = s ^ b;
}
}
}
static ZEROES: &'static [u8] = &[0u8, ..CHUNK_SIZE];
match osrc {
None => inner(dst, repeat(ZEROES)),
Some(src) => inner(dst, src.chunks(CHUNK_SIZE))
}
}
关于rust - 遍历选项的内容或特定值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26974226/