use compact_str::CompactString;
use nom::{
IResult, Parser,
bytes::complete::{tag, take_until, take_while},
};
fn parse_delimited(input: &str) -> IResult<&str, &str> {
let (input, _) = tag("{{").parse(input)?;
let (input, additional) = take_while(|c| c == '{').parse(input)?;
let n = 2 + additional.len();
let closing_pattern = ['}']
.iter()
.cycle()
.take(n)
.collect::<CompactString>();
let (input, content) = take_until(closing_pattern.as_str()).parse(input)?;
let (input, _) = tag(closing_pattern.as_str()).parse(input)?;
Ok((input, content.trim_ascii()))
}
#[test]
fn test_parse_delimited() {
assert_eq!(parse_delimited("{{ aa }}"), Ok(("", "aa")));
assert_eq!(parse_delimited("{{{ {a} }}}"), Ok(("", "{a}")));
assert_eq!(parse_delimited("{{ {a} }}"), Ok(("", "{a}")));
assert_eq!(parse_delimited("{{ { a } }}"), Ok(("", "{ a }")));
assert_eq!(parse_delimited("{{{{abc}}}}"), Ok(("", "abc")));
assert_eq!(
parse_delimited(
"{{{
{{a}
}}}"
),
Ok(("", "{{a}"))
);
}