从压缩结构获取原始字节

vir*_*tor 4 serialization rust

我有一个看起来像这样的结构:

#[repr(packed)]
struct Header {
    some: u8,
    thing: u8,
}
Run Code Online (Sandbox Code Playgroud)

如何从中获取原始字节,我可以用于C库或套接字交互?

我希望用来transmute解决问题,但遗憾的是这不起作用:

let header = Header {....}
let header_bytes: &[u8] = unsafe { mem::transmute(header) };
let result = self.socket.write(header_bytes);
Run Code Online (Sandbox Code Playgroud)

这失败了

error: transmute called on types with different sizes: &Header (64 bits) to &[u8] (128 bits)
Run Code Online (Sandbox Code Playgroud)

Vla*_*eev 7

编辑:更新为Rust 1.x.

你无法使任意一点任意东西(如Header&[u8]),因为transmute()是类似于reinterpret_cast在C++:它的字面重新诠释其它的参数包括字节,并且为了这个成功的源和目标类型应该有相同的尺寸.但即使Header并且&[u8]具有相同的大小,在它们之间进行转换也没有意义:Header是实际值,而&[u8]指针是指针后面的数据大小.

为了将一段数据解释为一个字节片,您需要执行三个步骤:获取指向数据的原始指针,将其转换为指针u8,然后将其转换为切片u8.这意味着使用长度增强原始指针值,在这种情况下,长度等于结构大小.最后一步可以通过以下方式轻松完成std::slice::from_raw_parts():

use std::slice;
use std::mem;

let p: *const Header = &header;     // the same operator is used as with references
let p: *const u8 = p as *const u8;  // convert between pointer types
let s: &[u8] = unsafe { 
    slice::from_raw_parts(p, mem::size_of::<Header>())
};
Run Code Online (Sandbox Code Playgroud)

但是,在大多数情况下这样做并不是一个好主意.即使结构被标记为打包,它仍然存在字节顺序的问题,所以至少执行此操作的代码将不可移植(或者更确切地说,它以这种形式序列化的数据可能无法通过为另一个架构编译的相同程序).