【问题标题】:Can I create a mutable slice &mut [u8] from a single byte (u8)?我可以从单个字节 (u8) 创建一个可变切片 &mut [u8] 吗?
【发布时间】:2017-11-21 13:53:35
【问题描述】:

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

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】:

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

    相反,您可以使用the Bytes iterator:

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

    【讨论】:

    • 虽然我喜欢这种使代码工作的更简单的方法,但它并不能回答我的实际问题。
    • @Cornstalks:要回答你的实际问题,那么:不,你不能那样做,而且几乎没有必要这样做。即使您无法从可读文件中获取可迭代对象,您也可以将 byte[0] 放入另一个变量并使用它。
    • 酷,谢谢!这是一个很好的评论,我认为如果你可以将它编辑到你的答案中会很棒。照原样,我将接受这一点,但该评论确实为我完成了事情。谢谢!
    【解决方案2】:

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

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

    请记住,切片基本上是两件事:指向内存区域的指针和长度。使用长度为 one 的切片,您只需向可变引用添加长度,然后 bam!你得到了自己的一片。

    早期版本的 Rust 有 ref_slice and mut_ref_slice functions。它们被删除是因为它们的实用性尚未得到证实(这不是一个常见问题),但它们可以安全调用。这些功能已移至ref_slice crate,因此如果您想继续使用它们,这是一种可能。

    【讨论】:

      猜你喜欢
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-12
      • 2021-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多