parsing - 使用 nom 根据先前的元素有条件地解析数组

标签 parsing rust nom

我需要从一个 u8 数组中解析一个 32 位整数数组(小端),但是下一个整数只有在当前整数的第 31 位被设置时才存在。如果其余部分不存在,则应将数组的其余部分设置为零。我不确定如何有条件地解析下一个元素。

假设该字段有 4 个字节长。然后 parse_field 函数的结果将是 4 个字节将用 le_u32 进行解析,这将是 [u32; 中的第一个元素; 8]数组。但是,如果设置了该字段的第 31 位。然后还有另外 4 个字节也类似于这个字段,它进入数组的下一个元素。如果未设置,则函数必须返回,其余元素设置为零的数组。对于每个现有字段,这将继续。

例如对于以下输入:

0x8000000a
0x8000000b
...

你会得到 [0x8000000a, 0x8000000b, 0, 0, 0, 0, 0, 0]

但是如果输入是

0x8000000a
0x8000000b
0x8000000c
0x8000000d
0x8000000e
....

然后你会得到 [0x8000000a, 0x8000000b, 0x8000000c, 0x8000000d, 0x8000000e, 0, 0, 0]

extern crate nom;

use nom::*;

#[derive(Clone, Copy, Debug)]
struct Derp {
    field: [u32; 8]
}

named!(parse_field<[u32; 8]>,

    // what do I do here

);


named!(parse_derp<Derp>,
    do_parse!(
        field: parse_field >>
        (Derp {
            field: field
        })
    )
);

fn main() {
    let temp = [0x0a, 0x00, 0x00, 0x80, 0x0b, 0x00, 0x00, 0x80];
    println!("{:?}", parse_derp(&temp));
}

此外,在这里使用 Vec 可能更好吗?

最佳答案

这是一个匹配您输入的最后一个 u32 的解析器:

named!(last_u32<u32>,
  verify!(le_u32, |n:u32| (n & 0b1) != 0) // Matches iff the 31st bit is set
);

然后你可以像这样使用它:

named!(parse_field<Vec<u32>>,
  map!(
    many_till!(le_u32, last_u32),
    |(mut v,n)| { v.push(n); v } // Add the last u32 to the vector
  ) 
);

关于parsing - 使用 nom 根据先前的元素有条件地解析数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49696838/

相关文章:

c - 使用逗号在 c 中解析 .csv 文件时出现问题

parsing - 如何在 Haskell 中打印 Functor 和 Applicative 的中间结果

parsing - 如何使用 nom 将带符号的字符串解析为 i32?

rust - 如何使用 Rust nom 为这种结构文本编写解析器?

c# - 结合序列化和语法解析的方法?

string - 根据语言环境将货币/浮点字符串解析为浮点类型

rust - 如何修复缺少的生命周期说明符?

closures - 为什么函数参数的生存期与函数内绑定(bind)的生存期不同?

rust - 为什么需要绑定(bind) `T: ' a` 才能存储引用 `&' a T`?