我正在试着用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)
}在这里,我的问题是第一个字节的剩余位被丢弃了,即使我想进一步处理它们。
我想我可以使用按位ands手动完成,但使用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}`以及其他错误,但这些错误只是由于第一个错误而导致的。
发布于 2020-07-07 09:09:34
面向位的接口(例如take)接受元组(I, usize),representing (input, bit_offset),因此您需要使用诸如bits之类的函数将输入从i转换为(i, 0),然后通过忽略当前字节中的任何剩余位将输出转换回字节。
有关第二个问题,请参阅How can I combine nom parsers to get a more bit-oriented interface to the data?上的注释:仅当需要在位和字节之间切换时才使用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)
}https://stackoverflow.com/questions/62763705
复制相似问题