Goal: To have the map(..) extracted into a function, so that it can be used in an alt(..) statement. There are probably some mistakes here. The code:
fn extract_unsigned_value<'a, I, K, F, P, O>(key: K, parser: P, c: F) -> impl FnMut(I) -> IResult<I, I, Error<I>>
where F: FnMut(O),
P: nom::Parser<&'a str, O, Error<&'a str>>,
I: InputTake + Compare<K>,
K: InputLength + Clone
{
move |i: I| {
map(preceded(
tuple((tag(key), multispace0::<&str, Error<&str>>, char(':'), multispace0)),
parser,
), c,
)
}
}
The compiler error:
error[E0271]: type mismatch resolving `<&str as InputIter>::Item == u8`
--> src/main.rs:75:20
|
75 | tuple((tag(key), multispace0::<&str, Error<&str>>, char(':'), multispace0)),
| ^^^ expected `u8`, found `char`
|
= note: required for `&str` to implement `Compare<K>`
note: required by a bound in `nom::bytes::complete::tag`
--> /home/merlin/.cargo/registry/src/github.com-1ecc6299db9ec823/nom-7.1.3/src/bytes/complete.rs:36:22
|
36 | Input: InputTake + Compare<T>,
| ^^^^^^^^^^ required by this bound in `tag`
I tried a lot in the last couple of days, event crying, did not help. I tried to start implementing this from the inside out, and got this far:
fn extract_unsigned_value<'a, T, F, P,E: ParseError<T>, O>(key: T, parser: P) -> impl FnMut(T) -> IResult<T, T, Error<T>>
where
T: InputTake + Compare<T> + Clone + nom::InputTakeAtPosition + InputLength + nom::Slice<RangeFrom<usize>> + InputIter,
<T as nom::InputTakeAtPosition>::Item: AsChar + Clone,
<T as InputIter>::Item: AsChar,
P: nom::Parser<T, T, E>,
{
move |input: T| {
preceded(
tuple((tag(key.clone()), multispace0::<T, Error<T>>, char(':'), multispace0)),
parser,
)
(input)
}
}
which unhelpful throws:
error[E0277]: expected a `FnMut<(T,)>` closure, found `P`
--> src/main.rs:102:13
|
100 | preceded(
| -------- required by a bound introduced by this call
101 | tuple((tag(key.clone()), multispace0::<T, Error<T>>, char(':'), multispace0)),
102 | parser,
| ^^^^^^ expected an `FnMut<(T,)>` closure, found `P`
|
= note: required for `P` to implement `Parser<T, _, nom::error::Error<T>>`
note: required by a bound in `preceded`
--> /home/merlin/.cargo/registry/src/github.com-1ecc6299db9ec823/nom-7.1.3/src/sequence/mod.rs:69:6
|
69 | G: Parser<I, O2, E>,
| ^^^^^^^^^^^^^^^^ required by this bound in `preceded`
help: consider further restricting this bound
|
97 | P: nom::Parser<T, T, E> + std::ops::FnMut<(T,)>,
| +++++++++++++++++++++++
Because you have used &'a str
in your parser, I guess you don't need it be generic over other input types.
fn extract_unsigned_value<'a, K, F, P, O, O1>(key: K, parser: P, c: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, Error<&'a str>>
where F: FnMut(O1) -> O,
P: nom::Parser<&'a str, O1, Error<&'a str>>,
K: InputLength + Clone,
&'a str : Compare<K>
{
map(preceded(
tuple((tag(key), multispace0, char(':'), multispace0)),
parser,
), c,
)
}
fn main() {
let mut parser = extract_unsigned_value("Test", digit1, |string| string.parse::<u32>().unwrap());
let r = parser("Test : 345");
println!("{r:?}")
}
Also I have removed the closure, because map
already returns one.
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c1c2db4e49973d8f15291cee0b28464d