fn clause_with_map()

in guard/src/rules/parser.rs [841:915]


fn clause_with_map<'loc, A, M, T: 'loc>(input: Span<'loc>,
                         access: A,
                         mapper: M) -> IResult<Span<'loc>, T>
    where A: Fn(Span<'loc>) -> IResult<Span<'loc>, AccessQuery<'loc>>,
          M: Fn(GuardAccessClause<'loc>) -> T + 'loc
{
    let location = FileLocation {
        file_name: input.extra,
        line: input.location_line(),
        column: input.get_utf8_column() as u32,
    };

    let (rest, not) = preceded( zero_or_more_ws_or_comment, opt(not))(input)?;
    let (rest, (query, cmp)) = map(tuple((
        |a| access(a),
        context("expecting one or more WS or comment blocks", zero_or_more_ws_or_comment),
        // error if there is no value_cmp, has to exist
        context("expecting comparison binary operators like >, <= or unary operators KEYS, EXISTS, EMPTY or NOT",
                value_cmp)
    )), |(query, _ign, value)| {
        (query, value)
    })(rest)?;

    if !does_comparator_have_rhs(&cmp.0) {
        let (rest, custom_message) = map(preceded(zero_or_more_ws_or_comment, opt(custom_message)),
                                         |msg| {
                                             msg.map(String::from)
                                         })(rest)?;
        Ok((rest,
            mapper(
                GuardAccessClause {
                    access_clause: AccessClause {
                        query,
                        comparator: cmp,
                        compare_with: None,
                        custom_message,
                        location,
                    },
                    negation: not.is_some() }
            )))
    }
    else {
        let (rest, (compare_with, custom_message)) =
            context("expecting either a property access \"engine.core\" or value like \"string\" or [\"this\", \"that\"]",
                    cut(alt((
                        //
                        // Order does matter here as true/false and other values can be interpreted as access
                        //
                        map(tuple((
                            parse_value, preceded(zero_or_more_ws_or_comment, opt(custom_message)))),
                            move |(rhs, msg)| {
                                (Some(LetValue::Value(rhs)), msg.map(String::from).or(None))
                            }),
                        map(tuple((
                            preceded(zero_or_more_ws_or_comment, access),
                            preceded(zero_or_more_ws_or_comment, opt(custom_message)))),
                            |(rhs, msg)| {
                                (Some(LetValue::AccessClause(rhs)), msg.map(String::from).or(None))
                            }),
                    ))))(rest)?;
        Ok((rest,
            mapper(
                GuardAccessClause {
                    access_clause: AccessClause {
                        query,
                        comparator: cmp,
                        compare_with,
                        custom_message,
                        location,
                    },
                    negation: not.is_some()
                })
        ))
    }
}