src/filter/dsl/ast/display.rs

//! Pretty-print an [`Expr`] back into canonical DSL syntax.
//!
//! Used by error messages ("near: `status >= 400`") and by `--print-filter`.

use std::fmt;

use super::{Cmp, Expr, Value};

impl fmt::Display for Cmp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Cmp::Eq => "=",
            Cmp::Ne => "!=",
            Cmp::Lt => "<",
            Cmp::Le => "<=",
            Cmp::Gt => ">",
            Cmp::Ge => ">=",
            Cmp::Match => "~",
        };
        f.write_str(s)
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Value::Str(s) => write!(f, "{:?}", s),
            Value::Int(n) => write!(f, "{}", n),
            Value::Regex(r) => write!(f, "/{}/", r),
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Expr::Compare { field, op, value } => {
                write!(f, "{} {} {}", field, op, value)
            }
            Expr::And(l, r) => {
                write_binary(f, l, "and", r)
            }
            Expr::Or(l, r) => {
                write_binary(f, l, "or", r)
            }
            Expr::Not(inner) => write!(f, "not {}", inner),
        }
    }
}

fn write_binary(
    f: &mut fmt::Formatter<'_>,
    l: &Expr,
    joiner: &str,
    r: &Expr,
) -> fmt::Result {
    write!(f, "(")?;
    l.fmt(f)?;
    write!(f, " {} ", joiner)?;
    r.fmt(f)?;
    write!(f, ")")
}