2

我正在尝试用 nom 编写一个 HTTP2 解析器。我正在实现 HPACK 标头压缩,但无法理解如何使用 nom 中的位字段。

例如,Indexed Header Field Representation从第一位为 1 开始。

fn indexed_header_field_tag(i: &[u8]) -> IResult<&[u8], ()> {
    nom::bits::streaming::tag(1, 1)(i)
}

这给了我一个我不太明白的编译器警告(老实说,我在 nom 的类型上遇到了一些问题):

error[E0308]: mismatched types
   --> src/parser.rs:179:41
    |
179 |         nom::bits::streaming::tag(1, 1)(i)
    |                                         ^ expected tuple, found `&[u8]`
    |
    = note:  expected tuple `(_, usize)`
            found reference `&[u8]`

我应该在这里放什么?

另一个例子是:

fn take_2_bits(input: &[u8]) -> IResult<&[u8], u64> {
    nom::bits::bits(nom::bits::streaming::take::<_, _, _, (_, _)>(2usize))(input)
}

在这里,我的问题是第一个字节的剩余位被丢弃,即使我想进一步处理它们。

我想我可以使用按位与手动进行操作,但使用 nom 会更好。

我尝试过以下方法,但这给了我很多编译器警告:

fn check_tag(input: &[u8]) -> IResult<&[u8], ()> {
    use nom::bits::{bits, bytes, complete::take_bits, complete::tag};
    let converted_bits = bits(take_bits(2usize))(2)?;
    let something = tag(0x80, 2)(converted_bits);
    nom::bits::bytes(something)
}

(灵感来自https://docs.rs/nom/5.1.2/nom/bits/fn.bytes.html)。

它告诉我,没有complete::take_bits(我猜只有文档有点偏离),但它也告诉我:

368 |         let converted_bits = bits(take_bits(2usize))(2)?;
    |                                                      ^ the trait `nom::traits::Slice<std::ops::RangeFrom<usize>>` is not implemented for `{integer}`

和其他错误,但这只是由于第一个错误而导致的。

4

1 回答 1

1

面向位的接口(例如take)接受一个表示(I, usize)的元组,因此您需要使用一个函数,例如将输入从 转换为,然后通过忽略当前字节中的任何剩余位将输出转换回字节。(input, bit_offset)bitsi(i, 0)

对于第二个问题,请参阅关于如何组合 nom 解析器以获得更面向位的数据接口的评论?bits仅在需要在位和字节之间切换时使用,并使面向位的函数使用面向位的输入。

示例代码

use nom::{IResult, bits::{bits, complete::{take, tag}}};

fn take_2_bits(i: (&[u8], usize)) -> IResult<(&[u8], usize), u8> {
    take(2usize)(i)
}

fn check_tag(i: (&[u8], usize)) -> IResult<(&[u8], usize), u8> {
    tag(0x01, 1usize)(i)
}

fn do_everything_bits(i: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, u8)> {
    let (i, a) = take_2_bits(i)?;
    let (i, b) = check_tag(i)?;
    Ok((i, (a, b)))
}

fn do_everything_bytes(i: &[u8]) -> IResult<&[u8], (u8, u8)> {
    bits(do_everything_bits)(i)
}
于 2020-07-07T01:09:33.973 回答