Rust 使用nom 5.0解析二进制文件 问题

Rust 使用nom 5.0解析二进制文件 问题,rust,nom,Rust,Nom,有一个文件里面有多个头,但对我来说,它只关心一个头和后面的数据。此头在文件中重复多次 它的幻数是:ASCII格式的A3046,或十六进制格式的0x65 0x51 0x48 0x54 0x52。 找到第一个字节后,解析器必须获取所有字节,直到0xff,然后对剩余的头重复,直到EOF 我的解决方案 首先,我加载了文件: let mut file = OpenOptions::new() .read(true) .open("../assets/sample&

有一个文件里面有多个头,但对我来说,它只关心一个头和后面的数据。此头在文件中重复多次

它的幻数是:ASCII格式的A3046,或十六进制格式的
0x65 0x51 0x48 0x54 0x52。
找到第一个字节后,解析器必须获取所有字节,直到
0xff
,然后对剩余的头重复,直到EOF

我的解决方案 首先,我加载了文件:

let mut file = OpenOptions::new()
        .read(true)
        .open("../assets/sample")
        .unwrap();

    let mut full_file: Vec<u8> = Vec::new();
    file.read_to_end(&mut full_file);
但是,当测试运行时,Ok具有
None
值。它肯定应该找到一些东西。我做错了什么

我没有发现使用nom5解析字节的例子,而且作为一个新手也没有帮助。 如何用这些规则解析所有的块?

nom
version
首先,对此表示歉意,游乐场只有nom 4.0,因此,代码为on

要解析类似的内容,我们需要组合两个不同的解析器:

  • ,以获取字节,直到前导码或EOF
  • ,以隔离序言
还有一个组合符,这样我们就可以去掉一系列解析器的第一个元素

// Our preamble
const MAGIC:&[u8] = &[0x65, 0x51, 0x48, 0x54, 0x52];
// Our EOF byte sequence
const EOF:&[u8] = &[0xff];

// Shorthand to catch EOF
fn match_to_eof(data: &[u8]) -> nom::IResult<&[u8], &[u8]> {
    nom::bytes::complete::take_until(EOF)(data)
}

// Shorthand to catch the preamble
fn take_until_preamble(data: &[u8]) -> nom::IResult<&[u8], &[u8]> {
    nom::bytes::complete::take_until(MAGIC)(data)
}
pub fn extract_from_data(data: &[u8]) -> Option<(&[u8], &[u8])> {
    let preamble_parser = nom::sequence::preceded(
        // Ditch anything before the preamble
        take_until_preamble,
        nom::sequence::preceded(
            // Ditch the preamble
            nom::bytes::complete::tag(MAGIC),
            // And take until the EOF (0xff)
            match_to_eof
        )
    );
    // And we swap the elements because it's confusing AF
    // as a return function
    preamble_parser(data).ok().map(|r| {
        (r.1, r.0)
    })
}
//我们的序言
常量魔法:&[u8]=&[0x65、0x51、0x48、0x54、0x52];
//我们的EOF字节序列
常数EOF:&[u8]=&[0xff];
//抓住EOF的速记
fn匹配到eof(数据:&[u8])->nom::IResult{
nom::bytes::complete::take_直到(EOF)(数据)
}
//抓住序言的速记
fn直到前导(数据:&[u8])->nom::IResult{
nom::bytes::complete::take_直到(MAGIC)(数据)
}
pub fn从_数据中提取_(数据:&[u8])->选项{
让preamble_parser=nom::sequence::preferred(
//在序言之前放弃任何东西
直到序言,
名称::序列::前置(
//放弃序言
nom::bytes::complete::tag(魔术),
//并一直持续到EOF(0xff)
匹配
)
);
//我们交换元素是因为它让人困惑
//作为返回函数
序言|u解析器(data).ok().map(| r|{
(r.1,r.0)
})
}
代码应该有足够好的注释,以便遵循。这将丢弃所有字节,直到找到前导字节,然后丢弃这些字节并保留所有字节,直到找到EOF字节序列(
[0xff]


然后它返回一个反向的
nom
结果,因为这是一个示例。如果愿意,您可以取消反转它,将其与其他解析器组合。第一个元素是序列的内容,第二个元素是EOF之后的内容。这意味着您可以使用这个函数进行迭代(我在我放在github上的repo中的一个测试中这样做了)。

nom
需求是固定的吗?我认为,使用流式迭代器可以更有效地实现这一点。这绝对不是一个要求,只是我想我可以帮助更快地实现我的目标。我会给你们两个,这样你们就可以决定了,在这种情况下:-)
// Our preamble
const MAGIC:&[u8] = &[0x65, 0x51, 0x48, 0x54, 0x52];
// Our EOF byte sequence
const EOF:&[u8] = &[0xff];

// Shorthand to catch EOF
fn match_to_eof(data: &[u8]) -> nom::IResult<&[u8], &[u8]> {
    nom::bytes::complete::take_until(EOF)(data)
}

// Shorthand to catch the preamble
fn take_until_preamble(data: &[u8]) -> nom::IResult<&[u8], &[u8]> {
    nom::bytes::complete::take_until(MAGIC)(data)
}
pub fn extract_from_data(data: &[u8]) -> Option<(&[u8], &[u8])> {
    let preamble_parser = nom::sequence::preceded(
        // Ditch anything before the preamble
        take_until_preamble,
        nom::sequence::preceded(
            // Ditch the preamble
            nom::bytes::complete::tag(MAGIC),
            // And take until the EOF (0xff)
            match_to_eof
        )
    );
    // And we swap the elements because it's confusing AF
    // as a return function
    preamble_parser(data).ok().map(|r| {
        (r.1, r.0)
    })
}