sud*_*udo 6 rust data-structures
我有一个未知大小的字节缓冲区,我想创建一个指向缓冲区开头内存的本地struct变量.按照我在C中所做的,我在Rust中尝试了很多不同的东西并且不断出错.这是我最近的尝试:
use std::mem::{transmute, size_of};
#[repr(C, packed)]
struct my_struct {
foo: u16,
bar: u8,
}
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
let buffer = v.as_slice();
let s: my_struct = unsafe { transmute(buffer[..size_of::<my_struct>()]) };
}
Run Code Online (Sandbox Code Playgroud)
我收到以下消息的错误:
std::marker::Sized没有实现[u8][u8]在编译时没有已知的常量std::mem::transmute您可以使用std::ptr::read和std::ptr::write直接读取/写入对象(还有其他std::ptr值得检查的方法).
在您的情况下,这很简单:
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
let s: MyStruct = unsafe { std::ptr::read(v.as_ptr() as *const _) };
println!("here is the struct: {:?}", s);
}
Run Code Online (Sandbox Code Playgroud)
我个人会鼓励您在可重用的方法中包装它,并在尝试读取之前对源缓冲区执行长度检查.
如果您不想将数据复制到结构中而是将其保留在原处,则可以使用slice::align_to. 这将创建一个&MyStruct:
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
struct MyStruct {
foo: u16,
bar: u8,
}
fn main() {
let v = vec![1u8, 2, 3];
// I copied this code from Stack Overflow
// without understanding why this case is safe.
let (head, body, _tail) = unsafe { v.align_to::<MyStruct>() };
assert!(head.is_empty(), "Data was not aligned");
let my_struct = &body[0];
println!("{:?}", my_struct);
}
Run Code Online (Sandbox Code Playgroud)
在这里,align_to将一些字节转换为MyStruct是安全的,因为我们已经使用过repr(C, packed)并且所有类型都MyStruct可以是任意字节。
也可以看看: