rust语言nom库常用接口使用示例3

nom库很庞大,有点像c++开源库Boost的子库Spirit。虽然千条小溪才能汇成江海湖泊,但其重要思想的代表者更能学习到其思想核心。今天介绍两个比较有代表性的接口,nom::bytes::streaming::take_while_m_n与nom::bytes::complete::take。虽然路径有点长,但不要紧,在使用时,可以使用模块系统(Module System) 中的 路径导入(Path Importing) 法
nom 库中,这两个函数分别代表了不同的解析哲学(Streaming vs Complete)和不同的匹配逻辑(条件匹配 vs 固定长度)。 
以下是它们的详细对比与使用指南:

1. 核心区别:Streaming(流式)vs Complete(完整)

这是 nom 中最基础的概念区分:
  • nom::bytes::complete
    • 假设: 输入数据是完整的。
    • 行为: 如果数据不足以完成匹配,解析器会直接返回一个 Error
  • nom::bytes::streaming
    • 假设: 输入数据可能是不完整的(例如来自网络 Socket 的数据流)。
    • 行为: 如果当前数据不足,但未来可能通过更多数据满足匹配,它会返回 Incomplete(Needed),提示调用者继续读取更多数据。

2. 函数详解

nom::bytes::complete::take
这是一个最基础的解析器,用于从输入中提取固定数量的字节/字符。
  • 参数count: usize(要提取的数量)。
  • 逻辑

如果输入长度count:提取前 count 个元素,返回剩余部分。

如果输入长度<count:由于是 complete 模块,它认为数据永远不会够了,报错 Error

  • 示例
    use nom::bytes::complete::take;
    // 提取 3 个字节
    let result = take(3usize)("abcdef"); 
    // 返回 Ok(("def", "abc"))
nom::bytes::streaming::take_while_m_n
这是一个更复杂的组合子,用于根据自定义条件提取指定数量范围内的内容。
  • 参数

m: usize:最小匹配数量。

n: usize:最大匹配数量。

list: cond:一个闭包,定义了什么样的字符可以被接受。

  • 逻辑

持续读取满足 cond 的字符,直到达到 n 个或者遇到不满足的字符。

Streaming 特性

如果已读取满足条件的字符<𝑚,且输入已用完,返回 Incomplete

即便已经读取了满足条件的字符≥𝑚,但还不到𝑛且输入已用完,它依然会返回 Incomplete(因为它不确定下一个进来的字节是否依然满足条件)。

  • 示例(解析 Hex 颜色)
    use nom::bytes::streaming::take_while_m_n;
    use nom::character::is_hex_digit;
    
    // 匹配 2 到 2 个十六进制字符
    fn hex_pair(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
        take_while_m_n(2, 2, is_hex_digit)(input)
    }

3. 对比总结表

特性
complete::takestreaming::take_while_m_n
模块 complete (数据已就绪) streaming (数据持续流入)
匹配准则 长度 (只要有 N 个就行) 条件 + 长度范围 (满足条件且在 m~n 之间)
数据不足时 返回 Err 返回 Incomplete
典型场景 解析固定长度的头部字段 解析变长的协议字段(如 Hex 字符串、特定 ID)

4. 选择建议 

  1. 大多数情况使用 complete:如果你是解析内存中的 PCAP 文件、配置文件或已知大小的 Buffer,请优先选择 nom::bytes::complete 下的对应版本。
  2. 网络解析使用 streaming:只有当你是在处理实时 TCP 流,且解析器需要告诉底层“我还需要更多数据包才能解析出这个字段”时,才使用 streaming
  3. 精确控制:如果你需要提取“正好 5 个字母”,请使用 take_while_m_n(5, 5, is_alphabetic)。如果你不在乎内容,只想要“接下来 5 个字节”,直接用 take(5usize)
参考资料:

nom 官方文档 (docs.rs)

 

posted @ 2025-12-16 11:17  PKICA  阅读(11)  评论(0)    收藏  举报