如何转换[u8;的迭代器; 4] 变成 u8 的迭代器?

问题描述

我有 u8 数据需要扩展为更多字节,[u8; 4] 通过函数并作为迭代器整体传递给使用它的第二个函数

以下编译但不起作用,因为它多次调用消费函数

fn expand(b: u8) -> [u8; 4] {
    const T: [u8; 4] = [0x12,0x34,0x56,0x78];
    [
        T[((b >> 6) & 0b11) as usize],T[((b >> 4) & 0b11) as usize],T[((b >> 2) & 0b11) as usize],T[((b >> 0) & 0b11) as usize],]
}

fn process2(data: impl Iterator<Item = [u8; 4]>) {
    for x in data {
        process(x.iter().cloned());
    }
}

fn process(data: impl Iterator<Item = u8>) { 
    for x in data {
        println!("{:02x}",x);
    }
}

fn main() {
    let xs = [1,2,3,4];
    process2(xs.iter().map(|x| expand(*x)));
}

Playground

flat_map 似乎是答案,但我遇到了终身问题:

    process(xs.iter().map(|x| expand(*x)).flat_map(|x| x.iter().cloned()));

给我:

error[E0515]: cannot return value referencing function parameter `x`
  --> src/main.rs:27:56
   |
27 |     process(xs.iter().map(|x| expand(*x)).flat_map(|x| x.iter().cloned()));
   |                                                        -^^^^^^^^^^^^^^^^
   |                                                        |
   |                                                        returns a value referencing data owned by the current function
   |                                                        `x` is borrowed here

如何将 Iterator<Item=[u8; 4]> 转换为 Iterator<Item=u8>

解决方法

您不能只使用 Rust 1.49 稳定标准库。

每晚

使用array::IntoIter

// 1.52.0-nightly (2021-02-09 097bc6a84f2280a889b9)
use std::array;

fn example() -> impl Iterator<Item = u8> {
    let data: [u8; 4] = [1,2,3,4];
    array::IntoIter::new(data)
}

稳定锈

使用arrayvec

use arrayvec::ArrayVec; // 0.5.2

fn example() -> impl Iterator<Item = u8> {
    let data: [u8; 4] = [1,4];
    ArrayVec::from(data).into_iter()
}

应用

然后您可以将 Iterator::flat_map 用于任一解决方案:

use arrayvec::ArrayVec; // 0.5.2

fn example(data: [u8; 4]) -> impl Iterator<Item = u8> {
    ArrayVec::from(data).into_iter()
}

fn drive_it(i: impl Iterator<Item = [u8; 4]>) -> impl Iterator<Item = u8> {
    i.flat_map(example)
}

另见:

,

我建议创建一个自定义迭代器:

struct NameMe {
    i: u8,v: u8,}

impl NameMe {
    fn new(v: u8) -> Self {
        Self { i: 8,v }
    }
}

impl Iterator for NameMe {
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        const T: [u8; 4] = [0x12,0x34,0x56,0x78];

        if self.i != 0 {
            self.i -= 2;

            Some(T[((self.v >> self.i) & 0b11) as usize])
        } else {
            None
        }
    }
}

fn main() {
    let xs = [1,4];

    let result: Vec<_> = xs.iter().copied().flat_map(NameMe::new).collect();

    let expect = [
        0x12,0x12,0x78,];

    assert_eq!(result,expect);
}