我在用Rust写一个压缩算法。
我有一个“转换表”,它将输入字节映射到输出(每个输出都是代码的u64,而u8是代码的长度,不需要是8的倍数)。对于每个输入字节,我找到相应的输出并将代码转换为一个大型的u64连续数组,然后我想将这个u64数组写入一个文件中。
将[u64; WRITE_CHUNK_SIZE]转换为[u8; 8 * WRITE_CHUNK_SIZE]的最佳方法是什么?
循环遍历[u64; WRITE_CHUNK_SIZE]、在每个u64上调用to_be_bytes()、将每个字节写入[u8; 8*WRITE_CHUNK_SIZE]都是我所能做的最好的吗?
我看到了一些需要不安全的align_to示例,为了转换数据类型,这似乎太过了。我还看到了this,它输出Vec。不过,我认为这只是将问题推到了后面,因为我仍然需要将该Vec<u8>转换为[u8]才能写入文件。我说错了吗?
发布于 2021-11-26 03:38:23
bytemuck机箱提供了一些函数,可以在不使用unsafe的情况下将一种类型重新解释为另一种类型,只要这样做是安全的,因为这两种类型都是“仅仅是字节”(没有无效的值,也没有填充)。只需调用bytemuck::cast在任何整数数组类型之间进行转换,只要这两种类型的总大小相同。(或者,如果有整数或整数数组的片段,则为bytemuck::cast_slice。)
这样的转换完全改变了类型,因此它们没有运行时成本。但是,它们不会将字节重新排序到特定的endianness,因此这暴露了正在运行的机器的本机endianness。在您的情况下,也许您可以重新排列您的表来解决这个问题,而不是显式地交换字节。如果不能,那么循环中的to_be_bytes可能就像它得到的一样好。
const WRITE_CHUNK_SIZE: usize = 4;
fn main() {
let sixtyfours: [u64; WRITE_CHUNK_SIZE] = [1, 2, 3, 0x0102030405060708];
let eights: [u8; 8 * WRITE_CHUNK_SIZE] = bytemuck::cast(sixtyfours);
println!("{:?}", eights);
}这个打印(在一台小终端机器上):
[1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 8, 7, 6, 5, 4, 3, 2, 1]https://stackoverflow.com/questions/70118148
复制相似问题