2015-10-05 15 views
5

A volte voglio leggere un singolo byte da un std::io::Read er. Se provo a fare questo:Posso creare una porzione di un singolo byte (u8)?

use std::io; 
use std::io::Read; 

fn main() { 
    let mut byte: u8 = 0; 
    io::stdin().read(&mut byte).unwrap(); 
    println!("byte: {}", byte); 
} 

ottengo il seguente errore (che è chiaro, come byte non è una fetta):

error[E0308]: mismatched types 
--> src/main.rs:6:22 
    | 
6 |  io::stdin().read(&mut byte).unwrap(); 
    |      ^^^^^^^^^ expected slice, found u8 
    | 
    = note: expected type `&mut [u8]` 
      found type `&mut u8` 

C'è un modo posso mantenere byte come un semplice u8 e basta prenderne una fetta, che poi posso passare a read()? Il modo più ovvio per fare questo lavoro di codice è quello di utilizzare un array di lunghezza 1:

use std::io; 
use std::io::Read; 

fn main() { 
    let mut byte: [u8; 1] = [0]; 
    io::stdin().read(&mut byte).unwrap(); 
    println!("byte: {}", byte[0]); 
} 

Ma è sensazione un po 'strano per tutto il resto del codice, e sarebbe più naturale di utilizzare un unico u8 piuttosto che un [u8; 1] che devo indicizzare.

Se non è possibile creare una sezione dal semplice u8 va bene, ma non so se è possibile o meno e vorrei sapere.

risposta

11

Ma questo è sensazione un po 'strano per tutto il resto del codice, e sarebbe più naturale di utilizzare un unico u8 piuttosto che un [u8; 1] che ho indicizzare in.

Creazione di un array di lunghezza 1 sarebbe il modo più naturale di farlo:

use std::io::{self, Read}; 

fn main() { 
    let mut bytes = [0]; 
    let bytes_read = io::stdin().read(&mut bytes).unwrap(); 
    let valid_bytes = &bytes[..bytes_read]; 
    println!("read bytes: {:?}", valid_bytes); 
} 

Tuttavia, è possibile di non sicuro creare una sezione da un riferimento ad un singolo valore:

use std::io::{self, Read}; 
use std::slice; 

fn mut_ref_slice<T>(x: &mut T) -> &mut [T] { 
    // It's important to wrap this in its own function because this is 
    // the only way to tell the borrow checker what the resulting slice 
    // will refer to. Otherwise you might get mutable aliasing or a 
    // dangling pointer which is what Rust is trying to avoid. 
    unsafe { slice::from_raw_parts_mut(x, 1) } 
} 

fn main() { 
    let mut byte = 0u8; 
    let bytes_read = io::stdin().read(mut_ref_slice(&mut byte)).unwrap(); 
    if bytes_read != 0 { 
     println!("byte: {}", byte); 
    } 
} 

Ricordare che una porzione è fondamentalmente due elementi: un puntatore a un'area di memoria e una lunghezza. Con una porzione di lunghezza uno, è sufficiente aggiungere una lunghezza a un riferimento mutabile e bam! ti sei procurato una fetta.

Versioni precedenti di Rust avevano il ref_slice and mut_ref_slice functions. Sono stati rimossi perché la loro utilità non è mai stata provata (questo non è un problema comune), ma erano sicuri da chiamare.

Le funzioni sono state spostate su ref_slice crate, quindi se si desidera continuare a utilizzarle, questa è una possibilità.

4

Per rispondere alla tua domanda attuale: no, non puoi farlo, e non c'è quasi mai bisogno di farlo. Anche se non è possibile ottenere un iterable da leggibile, è sufficiente inserire byte[0] in un'altra variabile e utilizzarlo.

Invece, è possibile utilizzare the Bytes iterator:

let byte: u8 = io::stdin().bytes().next().unwrap(); 
+0

Mentre questo mi piace come un modo più semplice per far funzionare il codice, non risponde alla mia domanda reale. – Cornstalks

+0

@Cornstalks: per rispondere alla tua domanda effettiva, allora: no, non puoi farlo, e non c'è quasi mai bisogno di farlo. Anche se non riuscissi a ottenere un iterable da una leggibile, potresti semplicemente inserire 'byte [0]' in un'altra variabile e usarlo. – Ryan

+0

Cool, grazie! Questo è un grande commento e penso che sarebbe fantastico se potessi modificarlo nella tua risposta.Come è, lo accetterò, ma quel commento mi completa davvero le cose. Grazie! – Cornstalks

Problemi correlati