2014-09-05 16 views

Trả lời

7

Bạn cũng có thể làm điều tương tự trong Rust. Bạn chỉ cần cẩn thận khi bạn xác định cấu trúc.

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); 

Thật không may, tôi không biết cách xác định bộ đệm chính xác là size_of::<YourProtoHeader>() kích thước; độ dài bộ đệm phải là một hằng số, nhưng cuộc gọi size_of() về mặt kỹ thuật là một hàm, do đó Rust sẽ phàn nàn khi tôi sử dụng nó trong bộ khởi tạo mảng. Tuy nhiên, bộ đệm đủ lớn cũng sẽ hoạt động.

Ở đây chúng tôi đang chuyển đổi con trỏ sang đầu bộ đệm thành con trỏ đến cấu trúc của bạn. Đây là điều tương tự bạn sẽ làm trong C. Cấu trúc chính nó nên được chú thích với các thuộc tính #[repr(C)]#[pack]: trường hợp đầu tiên không cho phép trường có thể sắp xếp lại, lớp thứ hai vô hiệu hóa để căn chỉnh trường.

+0

Tôi đoán thực sự không có cách nào để vượt qua khối không an toàn khi thực hiện loại phân tích cú pháp này. Cảm ơn các giải pháp. – Matt

+4

@Matt, vâng, diễn giải lại một phần của bộ nhớ là rất không an toàn. Nếu bạn không muốn 'unsafe', bạn có thể quấn' buf' vào 'BufReader' và sử dụng [' Reader'] (http://doc.rust-lang.org/std/io/trait.Reader.html) các phương thức, như 'read_be_u32()'. Đây có lẽ là một ý tưởng tốt, bởi vì việc diễn giải lại một phần bộ nhớ sẽ không cho phép bạn tinh chỉnh endianess, vì vậy chương trình của bạn sẽ không thể di chuyển được. –

Các vấn đề liên quan