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

use std::io::{self, 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::{self, Read};

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

但在代码的其余部分,这种感觉有点奇怪,使用一个u8而不是我必须索引的[u8; 1]会更自然.

如果不可能从简单的u8中创建一个切片,那没关系,但我不知道是否可能,我想知道.

推荐答案

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

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

但是,不安全地从引用到单个值创建一个切片是非常困难的:

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

请记住,片基本上是两件事:指向内存区域的指针和长度.对于长度为1的切片,只需向可变引用添加长度,然后bam!你吃了一片.

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

Rust相关问答推荐

移植带有可变borrow 的C代码-卸载期间错误(nappgui示例)

如何初始化match声明中的两个变量而不会激怒borrow 判断器?

在Rust中宏的表达式中提取对象

如何用Axum/Tower压缩Html内容?

在本例中,为什么我不能一次多次borrow 可变变量?

如何修复数组中NewType导致的运行时开销

将Vec<;U8&>转换为Vec<;{Float}&>

为什么Option类型try块需要类型注释?

是否可以在不直接重复的情况下为许多特定类型实现一个函数?

我可以解构self 参数吗?

如何以与平台无关的方式将OsString转换为utf-8编码的字符串?

如何在Rust中使用Serde创建一个自定义的反序列化器来处理带有内部标记的枚举

是否可以在 Rust 中的特定字符上实现特征?

Rust 中函数的类型同义词

将一片字节复制到一个大小不匹配的数组中

如何在 Rust 中返回通用 struct

如何使用 rust bindgen 生成的 std_vector

如何在 Rust 中编写涉及异步的重试函数

当 `T` 没有实现 `Debug` 时替代 `unwrap()`

`if let` 只是另一种编写其他 `if` 语句的方式吗?