use std::ops::ControlFlow; use nom::{ error::{ErrorKind, ParseError}, Err, InputLength, Parser, }; pub fn fold_till( mut p: P, mut init: F, mut acc: G, ) -> impl FnMut(I) -> nom::IResult where I: InputLength, E: ParseError, P: Parser, F: FnMut() -> St, G: FnMut(St, O) -> ControlFlow, { move |i| { let mut res = init(); let mut input = i; loop { let len = input.input_len(); let (i, o) = p.parse(input)?; if i.input_len() == len { return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many0))); } match acc(res, o) { ControlFlow::Continue(next) => { res = next; input = i; } ControlFlow::Break(res) => return Ok((i, res)), } } } }