2015-10-05 47 views
5

有時我想從std::io::Read er讀取一個字節。如果我試着這樣做:我可以創建一個單字節片段(u8)嗎?

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

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

我得到以下錯誤(這是明顯的,因爲byte不是切片):

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` 

有沒有一種方法可以讓我保持byte作爲一個簡單的u8,只需要一小部分,然後我可以傳遞給read()?使此代碼工作最顯而易見的方法是使用長度爲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]); 
} 

但是,這是整個代碼的其餘部分有點怪異的感覺,這將是更自然的使用單個u8,而不是我必須索引到[u8; 1]

如果無法從簡單的u8創建一個切片,那沒關係,但我不知道是否可以或不想,並且想知道。

回答

11

但是,這是整個代碼的其餘部分有點怪異的感覺,這將是更自然的使用單個u8,而不是一個[u8; 1]我有索引到。

創建長度爲1的陣列將是這樣做的最自然的方式:

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

然而,能夠到不安全從到單個值的參考創建切片:

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

請記住,切片基本上是兩件事:指向內存區域和長度的指針。用一段長度,你只需要添加一個長度到一個可變的引用和巴姆!你得到了一個切片。

Rust的早期版本有ref_slice and mut_ref_slice functions。他們被刪除,因爲他們的效用從未被證實(這不是一個普遍的問題),但他們可以安然地打電話。

函數被移動到ref_slice crate,所以如果你想繼續使用它們,那是一種可能性。

4

要回答你的實際問題:不,你不能這樣做,而且幾乎沒有任何需要。即使你無法讀出可讀的代碼,你也可以將byte[0]放入另一個變量中並使用它。

相反,你可以使用the Bytes iterator

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

雖然我喜歡這是一個更簡單的方法來使代碼工作,但它並沒有回答我的實際問題。 – Cornstalks

+0

@Cornstalks:回答你的實際問題,然後:不,你不能這樣做,幾乎沒有任何需要。即使你不能讀取可讀的迭代,你也可以將'byte [0]'放入另一個變量中並使用它。 – Ryan

+0

很酷,謝謝!這是一個很好的評論,我認爲如果你可以將它編輯成你的答案,那將是非常棒的。因爲,我會接受這一點,但那個評論真的爲我完成了一些事情。謝謝! – Cornstalks

相關問題