gpt4 book ai didi

rust - 如何在 nom 中取 N 位字节?

转载 作者:行者123 更新时间:2023-12-03 11:30:50 24 4
gpt4 key购买 nike

我正在尝试使用 nom 编写一个 HTTP2 解析器。我正在实现 HPACK header 压缩,但无法理解如何使用 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}`

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

最佳答案

面向位的接口(interface)(例如 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)
}

关于rust - 如何在 nom 中取 N 位字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62763705/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com