< 返回版块

smile921 发表于 2024-03-07 09:43

Tags:lifetime

在尝试使用nom 解析 curl 命令行遇到生命周期问题代码如下:

use std::collections::HashMap;

use nom::error::Error;
use nom::bytes::complete::{tag, take_until};
use nom::character::complete::{multispace0,char, space0}; 
use nom::multi::separated_list0;
use nom::sequence::{delimited, preceded}; 
use anyhow::Result;

fn test_parse(input:&str)-> Result<()> {
    let first = multispace0::<&str,Error<_>>;
    let second = tag("curl");
    let (_res,_matched)=preceded(first, second)(input)?;
    Ok(())
}

pub fn parse_curl_command12(input: &str) -> Result<(String, (String, HashMap<String, String>))> {
    let (input, _) = tag::<&str, &str, Error<&str>>("curl ")(input)?;
    let (input, url) = delimited(char::<&str,Error<_>>('\''), take_until("'"), char('\''))(input)?;
    let (input, _) = space0::<&str,Error<_>>(input)?;
    let (_input, headers) = separated_list0(
        space0::<&str,Error<_>>,
        preceded(
            tag("-H "),
            delimited(char('\''), take_until("'"), char('\'')),
        ),
    )(input)?;
  
    let headers : HashMap<String,String> = headers
        .into_iter()
        .filter_map(|header| {
            let mut parts = header.splitn(2, ": ");
            let key = parts.next()?.to_string();
            let value = parts.next()?.to_string();
            Some((key, value))
        })
        .collect();
  
    Ok(("".to_string(), (url.to_string(), headers)))
        // Ok(input)
  }

编译器提示: borrowed data escapes outside of function input escapes the function body hererustcClick for full compiler diagnostic xxx.rs(10, 15): input is a reference that is only valid in the function body xxx.rs(10, 21): let's call the lifetime of this reference '1 borrowed data escapes outside of function argument requires that '1 must outlive 'staticrustcClick for full compiler diagnostic xxx.rs(10, 15): input is a reference that is only valid in the function body xxx.rs(10, 21): let's call the lifetime of this reference '1. 两个函数都是这个问题

评论区

写评论
Bai-Jinlin 2024-03-07 12:05

nom的组合子就不要用anyhow了,anyhow的error要求static,在你调用nom parse的函数用anyhow就行。

use anyhow::anyhow;
use nom::bytes::complete::{tag, take_until};
use nom::character::complete::{char, multispace0, space0};
use nom::multi::separated_list0;
use nom::sequence::{delimited, preceded};
use nom::IResult;
use std::collections::HashMap;
fn foo() -> anyhow::Result<()> {
    let a = "asd".to_string();
    let _ = test_parse(&a).map_err(|_| anyhow!("parse error"))?;
    Ok(())
}
fn test_parse(input: &str) -> IResult<&str, ()> {
    let first = multispace0;
    let second = tag("curl");
    let (res, _matched) = preceded(first, second)(input)?;
    Ok((res, ()))
}
pub fn parse_curl_command12(input: &str) -> IResult<&str, (&str, HashMap<String, String>)> {
    let (input, _) = tag("curl ")(input)?;
    let (input, url) = delimited(char('\''), take_until("'"), char('\''))(input)?;
    let (input, _) = space0(input)?;
    let (input, headers) = separated_list0(
        space0,
        preceded(
            tag("-H "),
            delimited(char('\''), take_until("'"), char('\'')),
        ),
    )(input)?;

    let headers: HashMap<String, String> = headers
        .into_iter()
        .filter_map(|header| {
            let mut parts = header.splitn(2, ": ");
            let key = parts.next()?.to_string();
            let value = parts.next()?.to_string();
            Some((key, value))
        })
        .collect();

    Ok((input, (url, headers)))
}
asuper 2024-03-07 10:05

我猜是不是Result的Err里面带出了input的引用,试试给Result带上生命周期,另外test_parse()只会返回一种错误,建议可以不用anyhow::Result

1 共 2 条评论, 1 页