如何在Rust中将字节向量转换为字节数组?

3

我正在尝试做这个,但是不起作用:

fn foo() {
    let v = b"Hello".to_vec();
    let a = v.as_bytes();
}

我正在得到:

error[E0599]: no method named `as_bytes` found for struct `Vec<u8>` in the current scope
  --> foo
   |
26 |     let a = v.as_bytes();
   |               ^^^^^^^^ method not found in `Vec<u8>`

1
为什么要转换它呢?vec<u8>不能满足您的用例吗?而且这通常不被推荐,因为[u8]在编译时需要显式静态大小。 - tieway59
3个回答

5
在Rust中,数组的长度被编码在其类型中 - 例如,[u8; 5] - 是一个编译时属性,而Vec的长度是一个运行时属性。每个字节数组 [u8; N] 都实现了 TryFrom<Vec<u8>>,所以Vec<u8>作为结果实现了TryInto<[u8; N]>。因此,您可以在Vec<u8>上使用 try_into()将其转换为字节数组:
let a: [u8; 5] = v.try_into().unwrap();

请注意,TryInto::try_into() 返回一个 Result,原因如上所述:一个 Vec 和一个数组的长度属性的本质不同 - 运行时和编译时分别为不同。

为什么不将 Vec<u8> 转换为字节切片呢?

请记住,您可以轻松地从 Vec<T> 中创建字节切片(即 &[u8])。Vec<u8> 通过实现 Deref<Target=[u8]> 将其强制转换为 [u8]

let v = b"Hello".to_vec();
let a: &[u8] = &v;

您还可以在 Vec<u8> 上调用 as_slice() 方法:
let a = v.as_slice();

这可能是您想要的,因为您很可能使用了 Vec 以便在运行时更改长度。


3

如果你不想写 [u8; N] 这种类型,你可以选择在开头不使用 '.to_vec()' 方法,直接使用 *b"string" 获取字节数组,无需类型注释。

struct Pack {
    data: Box<[u8]>,
}

fn foo() {
    let mut p = Pack {
        data: Box::new(*b"Hello!"),
    };
    p.data = Box::new(*b"Bye!");
}

#[test]
fn test() {
    let v = *b"Hello!";

    let boxed_v = Box::new(*b"Hello!");

    assert_eq!(
        format!("{} {} {} {} {}", v[0], v[1], v[2], v[3], v[4]),
        "72 101 108 108 111"
    );

    assert_eq!(
        format!(
            "{} {} {} {} {}",
            boxed_v[0], boxed_v[1], boxed_v[2], boxed_v[3], boxed_v[4]
        ),
        "72 101 108 108 111"
    )
}

2

以下是一种将字节向量转换为字节数组的方法:

use std::convert::TryInto;

fn main() {
    let v: Vec<u8> = vec![44u8, 99u8];
    println!("{v:?}");
    let a: [u8; 2] = v.try_into().unwrap();
    println!("{a:?}");
}

但是数组的大小需要在编译时知道。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接