0

I want to wrap tag_no_case parsers with specific string values to be able to re-use them:

pub fn schema_parser<???>(???) -> ??? {
    tag_no_case("schema")
}

to be used like this

preceded(multispace0, schema_parser)(input)

I've tried to copy the tag_no_case typings and some other random approaches, but nothing have worked for me.

How should the type declaration look like to be able to use the custom parser like shown?

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
mottosson
  • 3,283
  • 4
  • 35
  • 73

1 Answers1

1

tag_no_case returns a impl Fn(Input) -> IResult<Input, Input, Error> which means we have to return something similar from our wrapper function.

For simplicity and brevity let's skip all the generics and just use &str, at which point the compiler will complain that the returned type is "not general enough" because it isn't generic over lifetimes. We can pin it down to a single lifetime by adding a lifetime parameter to the function signature and using that parameter to annotate the return type.

Final complete working and compiling example:

// nom = "6.1.0"
use nom::{IResult, bytes::complete::tag_no_case, sequence::preceded};

fn schema_parser<'a>() -> impl Fn(&'a str) -> IResult<&'a str, &'a str> {
    tag_no_case("schema")
}

fn main() {
    let string = String::from("exampleschema");
    let mut parser = preceded(tag_no_case("example"), schema_parser());
    assert_eq!(parser(&string), Ok(("", "schema"))); // non-'static str
    assert_eq!(parser("exampleschema"), Ok(("", "schema"))); // 'static str
}
vallentin
  • 23,478
  • 6
  • 59
  • 81
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98