我想把一个[u32; 4]
转换成一个[u8; 16]
。
我知道可以使用按位操作从4 u8
中获取16 u32
。但是我想把数组转换到适当的位置。如何使用安全锈蚀或不安全锈蚀来做到这一点?
let buffer: [u32; 4] = [1, 2, 3, 4];
let hash: [u8; 16]; // how to convert from buffer to hash?
背景信息:我正在计算一个128位的散列值,其中[u32; 4]
是一个包含4 u32
的缓冲区。我希望将数组转换为[u8; 16]
,作为最后的散列。
发布于 2022-06-15 12:13:33
你可能会被诱惑去做一个转变,但我建议你不要这样做,主要是因为它的能力,也就是说,最终的输出将取决于你的机器是大端还是小端:
pub fn convert(data: &[u32; 4]) -> [u8; 16] {
unsafe { std::mem::transmute(*data) }
}
相反,我只会用无聊的方式做(游乐场)
pub fn convert(data: &[u32; 4]) -> [u8; 16] {
let mut res = [0; 16];
for i in 0..4 {
res[4*i..][..4].copy_from_slice(&data[i].to_le_bytes());
}
res
}
如果需要大端,则将to_le_bytes()
更改为to_be_bytes()
。或者,如果您不关心这个问题,可以使用to_ne_bytes()
来获得本地的endianness。
如果你担心性能(但你为什么要担心呢?)使用本机endianness为x86_64
生成的代码尽可能好:
playground::convert:
movq %rdi, %rax
movups (%rsi), %xmm0
movups %xmm0, (%rdi)
retq
发布于 2022-06-15 12:10:35
使用unsafe
,可以很容易地使用transmute()
pub fn convert(v: [u32; 4]) -> [u8; 16] {
unsafe { std::mem::transmute(v) }
}
我认为没有外部板条箱是没有有效的安全方法的。如果您可以采用外部板条箱,则可以使用bytemuck::cast()
。
pub fn convert(v: [u32; 4]) -> [u8; 16] {
bytemuck::cast(v)
}
发布于 2022-08-29 11:37:14
轻巧地,更简单/更地道地接受当前接受的答案:
pub fn convert(source: &[u32; 4]) -> [u8; 16] {
let mut dest = [0; 16];
for (dest_c, source_e) in dest.chunks_exact_mut(4).zip(source.iter()) {
dest_c.copy_from_slice(&source_e.to_le_bytes())
}
dest
}
基于异议,它似乎生成了更简单的ASM,可能是因为完全基于迭代器的迭代所产生的更强的假设(我已经检查了一个包含64k u32条目的数组,但我还没有彻底分析ASM )。
https://stackoverflow.com/questions/72631065
复制相似问题