如何在 nom 的解析器中使用解析器?

时间:2021-03-27 16:05:13

标签: rust nom

我正在尝试解析包含一些压缩格式数据的格式。作为常规解析的一部分,如何解析解压部分?目前我遇到了借用检查器的问题,因为 nom 的错误部分在从 compressed_data 返回时想要引用 parse_header 部分,这会超出范围。

#[macro_use]
use nom::combinator::map_res;
use nom::number::complete::le_u32;
use nom::IResult;
use nom::bytes::complete::take;
use std::io::prelude::*;
use std::io;
use flate2::bufread::DeflateDecoder;

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Replay {
  header_length: u32
, header: Header
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Header {
  version: String
}

fn decode_reader(bytes: &[u8]) -> io::Result<Vec<u8>> {
   let mut deflater = DeflateDecoder::new(&bytes[..]);
   let mut s = Vec::new();
   deflater.read(&mut s)?;
   Ok(s)
}

pub fn parse_header(input: &[u8]) -> IResult<&[u8],Header> {
  let (input, version) = map_res(take(8u8), std::str::from_utf8)(input)?;
  Ok((input, Header { version: version.to_string() }))
}

pub fn parse_replay(input: &[u8]) -> IResult<&[u8],Replay> {
  let (input, header_length) = le_u32(input)?;
  let (input, _) = le_u32(input)?;
  let (input, compressed_data) = map_res(take(header_length), decode_reader)(input)?;
  let compressed_ary: &[_] = &compressed_data;
  let (com_input, header) = parse_header(compressed_ary)?;
  
  Ok((input, Replay { header_length, header }))
}
cannot return value referencing local variable `compressed_data`

returns a value referencing data owned by the current function
rustc(E0515)

1 个答案:

答案 0 :(得分:0)

不确定您是否已经解决了这个问题,但该问题是由在 ? 中使用 parse_header(compressed_ary)? 引起的,它会在出错时返回引用拥有的数据的 nom::Err(nom::error::Error<&[u8]>)通过 compressed_data 变量。您可以使用 .unwrap(),但您可能希望将错误映射到引用 input 而不是 compressed_data 的内容,但这可能意味着匹配 nom::Err 并映射每个nom::Err 的 3 个变体中的等价物,但替换了对 input 的引用。如果您不希望出现不完整或失败的情况,您也可以只返回一个特定的 nom 错误而不是映射每个枚举变体

相关问题