2014-09-05 14 views

risposta

7

Puoi fare la stessa cosa anche con Rust. Devi solo stare attento quando definisci la struttura.

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

Purtroppo, non so come specificare il buffer per essere esattamente size_of::<YourProtoHeader>() dimensioni; la lunghezza del buffer deve essere una costante, ma la chiamata size_of() è tecnicamente una funzione, quindi Rust si lamenta quando lo uso nell'inizializzatore dell'array. Tuttavia, funzionerà anche un buffer abbastanza grande.

Qui stiamo convertendo un puntatore all'inizio del buffer in un puntatore alla struttura. Questa è la stessa cosa che si farebbe in C. La struttura stessa dovrebbe essere annotata con gli attributi #[repr(C)] e #[pack]: la prima non consente il possibile riordino dei campi, la seconda disabilita il riempimento per l'allineamento dei campi.

+0

Immagino che non ci sia davvero modo di aggirare il blocco non sicuro quando si fa questo tipo di analisi. Grazie per la soluzione. – Matt

+4

@Matt, sì, reinterpretare un pezzo di memoria è molto pericoloso. Se non vuoi "non sicuro", puoi racchiudere 'buf' in' BufReader' e usare ['Reader'] (http://doc.rust-lang.org/std/io/trait.Reader.html) metodi, come 'read_be_u32()'. Probabilmente è comunque una buona idea, perché reinterpretare un pezzo di memoria non ti permetterà di modificare l'endianess, quindi il tuo programma non sarà trasferibile. –

Problemi correlati