可以使用stdlib 和通用函数来完成大小正确的结构作为零复制字节。
在下面的示例中,有一个名为 any_as_u8_slice 而不是 convert_struct 的可重用函数,因为这是一个用于包装强制转换和切片创建的实用程序。
注意题主问的是converting,这个例子创建了一个只读的slice,所以好处是不需要复制内存。
这是一个基于问题的工作示例:
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
::std::slice::from_raw_parts(
(p as *const T) as *const u8,
::std::mem::size_of::<T>(),
)
}
fn main() {
struct MyStruct {
id: u8,
data: [u8; 1024],
}
let my_struct = MyStruct { id: 0, data: [1; 1024] };
let bytes: &[u8] = unsafe { any_as_u8_slice(&my_struct) };
// tcp_stream.write(bytes);
println!("{:?}", bytes);
}
注意 1) 尽管在某些情况下 3rd 方 crate 可能更好,但这是一个非常原始的操作,知道如何在 Rust 中进行操作很有用。
注 2) 在撰写本文时 (Rust 1.15),不支持 const 函数。一旦有了,就可以转换成固定大小的数组而不是切片。
注 3)any_as_u8_slice 函数被标记为unsafe,因为struct 中的任何填充字节都可能是未初始化的内存(给出未定义的行为)。
如果有办法确保输入参数仅使用 #[repr(packed)] 结构,那么它可能是安全的。
否则该函数是相当安全的,因为它可以防止缓冲区溢出,因为输出是只读的、固定的字节数,并且它的生命周期与输入绑定。
如果您想要一个返回 @ 的版本987654332@,这将非常危险,因为修改很容易创建不一致/损坏的数据。