我可以创建单个字节的切片(u8)吗?

Cor*_*lks 7 rust

有时候我想从std::io::Reader 读取一个字节.如果我尝试这样做:

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

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

我得到以下错误(这是明确的,因为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`
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以保持byte简单u8,只需要切片,然后我可以传递给它read()?使这段代码工作的显而易见的方法是使用长度为1的数组:

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

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

但是在整个代码中,这有点奇怪的感觉,使用单个u8而不是[u8; 1]我必须索引的内容会更自然.

如果不可能从简单的方法创建一个切片就u8可以了,但我不知道它是否可能并且想知道.

She*_*ter 13

Rust 1.28+

slice::from_mut 回来了,它很稳定!

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

fn main() {
    let mut byte = 0;
    let bytes_read = io::stdin().read(slice::from_mut(&mut byte)).unwrap();
    if bytes_read == 1 {
        println!("read byte: {:?}", byte);
    }
}
Run Code Online (Sandbox Code Playgroud)

Rust 1.0+

但是在整个代码中,这有点奇怪的感觉,使用单个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);
}
Run Code Online (Sandbox Code Playgroud)

但是,可以从引用到单个值的不安全地创建切片:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住,切片基本上是两件事:指向内存区域和长度的指针.使用一个长度为1的片段,您只需要为可变参考和bam添加长度!你得到了一分.

早期版本的Rust具有ref_slicemut_ref_slice功能.它们被删除了,因为它们的实用程序尚未得到证实(这不是常见问题),但它们可以安全地调用.函数被移动到ref_slice包,所以如果你想继续使用它们,这是一种可能性.


Ry-*_*Ry- 5

要回答您的实际问题:不,您不能那样做,而且几乎没有任何需要。即使您无法从可读性中获得可迭代性,也可以将byte[0]放入另一个变量中并使用它。

相反,你可以使用Bytes迭代器

let byte: u8 = io::stdin().bytes().next().unwrap();
Run Code Online (Sandbox Code Playgroud)