use super::*;
fn kvp_kserd_to_kserd<'a, E: CxErr<'a>>(
force_inline: bool,
) -> impl Fn(&'a str) -> IResult<&'a str, (Kserd<'a>, Kserd<'a>), E> {
move |input: &'a str| {
let value_parser = if force_inline {
kserd_inline
} else {
kserd_concise
};
context(
"kserd-kserd key-value pair",
separated_pair(
alt((kserd_concise, kserd_inline)),
ignore_inline_whitespace(char(':')),
ignore_inline_whitespace(value_parser),
),
)(input)
}
}
fn inline_map_kserds<'a, E: CxErr<'a>>(
i: &'a str,
) -> IResult<&'a str, Vec<(Kserd<'a>, Kserd<'a>)>, E> {
context(
"comma separated kserd-kserd pair",
separated_list0(
ignore_inline_whitespace(char(',')),
ignore_inline_whitespace(kvp_kserd_to_kserd(true)),
),
)(i)
}
fn concise_map_kserds<'a, E: CxErr<'a>>(
i: &'a str,
) -> IResult<&'a str, Vec<(Kserd<'a>, Kserd<'a>)>, E> {
context(
"newline separated (concise) kserd-kserd pair",
preceded(
multiline_whitespace,
terminated(
separated_list0(multiline_whitespace, kvp_kserd_to_kserd(false)),
multiline_whitespace,
),
),
)(i)
}
pub(super) fn delimited<'a, E: CxErr<'a>>(
force_inline: bool,
) -> impl Fn(&'a str) -> IResult<&'a str, Kserd<'a>, E> {
move |i: &'a str| {
let (i, ident) = opt(ident(false))(i)?;
let (i, _) = ignore_inline_whitespace(char('{'))(i)?;
let concise = recognise_concise(i) && !force_inline;
let parser = if concise {
concise_map_kserds
} else {
inline_map_kserds
};
let ctx = if concise { "concise map" } else { "inline map" };
let (i, value) = context(ctx, terminated(parser, ignore_inline_whitespace(char('}'))))(i)?;
let value = Value::Map(value.into_iter().collect());
Ok((i, kserd_ctor(ident, value)))
}
}