2014-09-05 80 views

回答

7

你也可以在Rust中做同样的事情。您在定义结构时必须小心谨慎。

use std::mem; 

#[repr(C)] 
#[packed] 
struct YourProtoHeader { 
    magic: u8, 
    len: u32 
} 

let mut buf = [0u8, ..1024]; // large enough buffer 

// read header from some Reader (a socket, perhaps) 
reader.read_at_least(mem::size_of::<YourProtoHeader>(), buf.as_mut_slice()).unwrap(); 

let ptr: *const u8 = buf.as_ptr(); 
let ptr: *const YourProtoHeader = ptr as *const YourProtoHeader; 
let ptr: &YourProtoHeader = unsafe { &*ptr }; 

println!("Data length: {}", ptr.len); 

不幸的是,我不知道如何指定缓冲区是完全size_of::<YourProtoHeader>()大小;缓冲区长度必须是一个常量,但size_of()调用在技术上是一个函数,所以Rust在数组初始值设定项中使用它时会抱怨。尽管如此,足够大的缓冲区也可以工作。

这里我们将一个指针指向缓冲区的开头,指向结构的指针。这与C中的操作相同。结构本身应该注释为#[repr(C)]和​​属性:第一个不允许可能的字段重新排序,第二个禁用字段对齐的填充。

+0

我想在这种类型的解析存在的时候,真的没有办法绕过不安全的块。感谢您的解决方案。 – Matt 2014-09-08 12:21:54

+4

@Matt,是的,重新解释一段内存是非常不安全的。如果你不想'unsafe',你可以将'buf'包装到'BufReader'中并使用['Reader'](http://doc.rust-lang.org/std/io/trait.Reader.html)方法,比如'read_be_u32()'。无论如何,这可能是一个好主意,因为重新解释一段内存不会让你调整永恒性,所以你的程序不能移植。 – 2014-09-08 12:59:41

相关问题