使用Rust解析二进制协议的最佳方法是什么?

Mat*_*att 9 rust

基本上我有一个基于tcp的网络协议来解析.

在CI中只能将一些内存转换为我想要的类型.我怎样才能完成与Rust类似的东西.

Vla*_*eev 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);
Run Code Online (Sandbox Code Playgroud)

不幸的是,我不知道如何指定缓冲区的size_of::<YourProtoHeader>()大小; 缓冲区长度必须是常量,但size_of()调用在技术上是一个函数,所以当我在数组初始化程序中使用它时,Rust会抱怨.然而,足够大的缓冲区也可以工作.

这里我们将指向缓冲区开头的指针转换为指向结构的指针.这与你在C中做的一样.结构本身应该用#[repr(C)]#[pack]属性注释:第一个不允许可能的字段重新排序,第二个禁用字段对齐的填充.

  • @Matt,是的,重新解释一块内存是非常不安全的.如果你不想要'unsafe`,你可以将`buf`包装成`BufReader`并使用[`Reader`](http://doc.rust-lang.org/std/io/trait.Reader.html)方法,如`read_be_u32()`.无论如何,这可能是一个好主意,因为重新解释一块内存将不允许你调整endianess,所以你的程序将不可移植. (6认同)