rust - 是否可以在不复制数据的情况下将 Vec<&[u8]> 展平为 &[u8] ?

标签 rust

我想展平包含 &[u8] 的矢量:

fn main() {
    let x: &[u8] = &b"abc"[..];
    let y: &[u8] = &b"def"[..];
    
    let z: Vec<&[u8]> = vec![x, y];
    
    println!("z: {:?}", z);
    
    let z_flat: &[u8] = z.into_iter().flatten().collect();
    
    println!("z_flat: {:?}", z_flat);
}

我得到编译器错误:

error[E0277]: a value of type `&[u8]` cannot be built from an iterator over elements of type `&u8`
 --> src/main.rs:9:49
  |
9 |     let z_flat: &[u8] = z.into_iter().flatten().collect();
  |                                                 ^^^^^^^ value of type `&[u8]` cannot be built from `std::iter::Iterator<Item=&u8>`
  |
  = help: the trait `FromIterator<&u8>` is not implemented for `&[u8]`

我也试过以下方法:

let z_flat: &[u8] = &z.into_iter().map(|x| x.to_vec()).flatten().collect();

编译错误:

error[E0277]: a value of type `[u8]` cannot be built from an iterator over elements of type `u8`
 --> src/main.rs:9:70
  |
9 |     let z_flat: &[u8] = &z.into_iter().map(|x| x.to_vec()).flatten().collect();
  |                                                                      ^^^^^^^ value of type `[u8]` cannot be built from `std::iter::Iterator<Item=u8>`
  |
  = help: the trait `FromIterator<u8>` is not implemented for `[u8]`

以下确实有效(playground):

let z_flat: &[u8] = &z.concat();

我无法使用 concat在我的实际应用程序中,因为我在检索嵌套字节( xy )时使用了另一个结构,并且此结构无法实现 Copy (仅 Clone )因为它包含一个 Vec<u8> field 。我有类似的东西 ( playground ):

#[derive(Clone, Debug)]
struct Foo {
    Bar: Vec<u8>,
}

impl Foo {
    fn baz(&self) -> Vec<u8> {
        self.Bar
    }
}

fn main() {
    let x = Foo { Bar: vec![8u8] };
    let y = Foo { Bar: vec![18u8] };

    let z: Vec<Foo> = vec![x, y];

    println!("z: {:?}", z);

    let z_flat = z
        .into_iter()
        .map(|x| &x.baz()[..])
        .collect::<Vec<&[u8]>>()
        .concat();

    println!("z_flat: {:?}", z_flat);
}

编译错误:

error[E0507]: cannot move out of `self.Bar` which is behind a shared reference
 --> src/main.rs:8:9
  |
8 |         self.Bar
  |         ^^^^^^^^ move occurs because `self.Bar` has type `Vec<u8>`, which does not implement the `Copy` trait

error[E0515]: cannot return value referencing temporary value
  --> src/main.rs:22:18
   |
22 |         .map(|x| &x.baz()[..])
   |                  ^-------^^^^
   |                  ||
   |                  |temporary value created here
   |                  returns a value referencing data owned by the current function

最佳答案

不,这是不可能的。根据定义,切片是一个连续的内存区域。你没有那个开始,所以你不能创建一个切片。

您的解决方法是将所有内容复制到一个连续的内存块中,然后您可以获取其中的一部分。我会这样写:

let z: Vec<&[u8]> = vec![b"abc", b"def"];
let z_alloc: Vec<u8> = z.iter().flat_map(|&x| x).copied().collect();
let z_flat: &[u8] = &z_alloc;

println!("z_flat: {:?}", z_flat);

对于更大的例子:

// fn baz(self) -> Vec<u8>
let z_flat: Vec<u8> = z.into_iter().flat_map(Foo::baz).collect();
// fn baz(&self) -> &[u8]
let z_flat: Vec<u8> = z.iter().flat_map(Foo::baz).copied().collect();

另见:

关于rust - 是否可以在不复制数据的情况下将 Vec<&[u8]> 展平为 &[u8] ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68625669/

相关文章:

rust - 宏生成代码中未使用的变量

rust - 如何从 std::io::Error 获取消息字符串?

rust - 在 Rust 中为 vector 的每个元素添加一个新键

rust - 如何解决 "indicate anonymous lifetime <' _>”错误?

rust - 用什么语言编写 Rust 编译器?

tcp - 简单的 Rust TCP 服务器和客户端不接收消息并且永不终止

assembly - 将 Rust 数组的指针传递到 x86-64 Asm 中——指针减一

linux - 在 i::count 上运行收集时得到 "Illegal instruction"

rust - 不能借用 `*x` 作为可变的,因为它也被借用为不可变的

string - 如何使用另一个 HashSet<String> 扩展 HashSet<String>?