首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在nom中获取N位字节?

如何在nom中获取N位字节?
EN

Stack Overflow用户
提问于 2020-07-07 04:07:00
回答 1查看 592关注 0票数 2

我正在试着用nom写一个HTTP2解析器。我正在实现HPACK报头压缩,但在理解如何使用nom中的位域时遇到了问题。

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

代码语言:javascript
复制
fn indexed_header_field_tag(i: &[u8]) -> IResult<&[u8], ()> {
    nom::bits::streaming::tag(1, 1)(i)
}

这给了我一个我不太理解的编译器警告(老实说,我对nom中的类型有一些问题):

代码语言:javascript
复制
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]`

我应该把什么放在这里?

另一个例子是:

代码语言:javascript
复制
fn take_2_bits(input: &[u8]) -> IResult<&[u8], u64> {
    nom::bits::bits(nom::bits::streaming::take::<_, _, _, (_, _)>(2usize))(input)
}

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

我想我可以使用按位ands手动完成,但使用nom会更好。

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

代码语言:javascript
复制
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 (我猜只有文档有点错),但它也告诉我:

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

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

EN

回答 1

Stack Overflow用户

发布于 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,并使面向位的函数使用面向位的输入。

示例代码

代码语言:javascript
复制
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)
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62763705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档