muninn_query 0.5.0

Query langugage for muninn logging stack
Documentation
use crate::ast::visit::AstVisitor;
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime};
#[cfg(feature = "serde")]
use serde_crate::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum Value {
  Null,
  Bool(bool),
  Int(i64),
  Float(f64),
  String(String),
  Date(NaiveDate),
  DateTime(DateTime<FixedOffset>),
  NaiveDateTime(NaiveDateTime),
  RelativeTime(RelativeTime),
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum RelativeTime {
  Now,
  Duration(Duration, TimeAnchor),
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum Duration {
  Seconds(i16),
  Minutes(i16),
  Hours(i16),
  Days(i16),
  Weeks(i16),
  Months(i16),
  Years(i16),
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum TimeAnchor {
  Ago,
}

pub type AbsolutePath = Vec<String>;
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub struct WildcardPath(pub Vec<PathElement>);
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum PathElement {
  Field(String),
  Wildcard,
  RecursiveWildcard,
}
impl From<AbsolutePath> for WildcardPath {
  fn from(vec: Vec<String>) -> WildcardPath {
    WildcardPath(vec.into_iter().map(PathElement::Field).collect())
  }
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub struct UnaryExpression {
  pub op: UnaryOperator,
  pub expr: Expression,
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum UnaryOperator {
  Not,
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub struct BinaryExpression {
  pub lhs: Expression,
  pub op: BinaryOperator,
  pub rhs: Expression,
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum BinaryOperator {
  Eq,
  Ne,
  Lt,
  Gt,
  Lte,
  Gte,
  Match,
  IMatch,
  And,
  Or,
}
impl BinaryOperator {
  pub fn precedence(&self) -> u8 {
    match self {
      BinaryOperator::Or => 1,
      BinaryOperator::And => 2,
      BinaryOperator::Eq | BinaryOperator::Ne => 3,
      BinaryOperator::Lt
      | BinaryOperator::Gt
      | BinaryOperator::Lte
      | BinaryOperator::Gte
      | BinaryOperator::Match
      | BinaryOperator::IMatch => 4,
    }
  }
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum Expression {
  AbsolutePath(AbsolutePath),
  WildcardPath(WildcardPath),
  Value(Value),
  UnaryExpression(Box<UnaryExpression>),
  BinaryExpression(Box<BinaryExpression>),
  Error(ErrorToken),
}

impl Expression {
  pub fn is_error(&self) -> bool {
    let mut is_error_visitor = IsErrorVisitor::default();
    is_error_visitor.visit_expression(self);
    is_error_visitor.is_error
  }
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
  feature = "serde",
  serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum ErrorToken {
  PathStart,
  Identifier(String),
  List(Vec<Expression>),
  Unexpected,
}

#[derive(Default)]
struct IsErrorVisitor {
  is_error: bool,
}

impl<'a> AstVisitor<'a> for IsErrorVisitor {
  fn visit_expression(&mut self, expression: &'a Expression) {
    if !self.is_error {
      visit::walk_expression(self, expression)
    }
  }

  fn visit_error_token(&mut self, _: &'a ErrorToken) {
    self.is_error = true;
  }
}

pub mod visit {
  use super::*;

  pub trait AstVisitor<'a> {
    fn visit_expression(&mut self, expression: &'a Expression) {
      walk_expression(self, expression)
    }
    fn visit_unary_expression(&mut self, unary_expression: &'a UnaryExpression) {
      walk_unary_expression(self, unary_expression)
    }
    fn visit_unary_operator(&mut self, _op: &'a UnaryOperator) {}
    fn visit_binary_expression(&mut self, binary_expression: &'a BinaryExpression) {
      walk_binary_expression(self, binary_expression)
    }
    fn visit_binary_operator(&mut self, _op: &'a BinaryOperator) {}
    fn visit_absolute_path(&mut self, _path: &'a AbsolutePath) {}
    fn visit_wildcard_path(&mut self, _path: &'a WildcardPath) {}
    fn visit_value(&mut self, _value: &'a Value) {}

    fn visit_error_token(&mut self, error: &'a ErrorToken) {
      walk_error_token(self, error)
    }

    fn should_continue(&self) -> bool {
      true
    }
  }

  pub fn walk_expression<'a, V: AstVisitor<'a> + ?Sized>(
    visitor: &mut V,
    expression: &'a Expression,
  ) -> () {
    if !visitor.should_continue() {
      return;
    }
    match *expression {
      Expression::AbsolutePath(ref path) => visitor.visit_absolute_path(path),
      Expression::WildcardPath(ref path) => visitor.visit_wildcard_path(path),
      Expression::Value(ref value) => visitor.visit_value(value),
      Expression::UnaryExpression(ref unary_expression) => {
        visitor.visit_unary_expression(unary_expression)
      }
      Expression::BinaryExpression(ref binary_expression) => {
        visitor.visit_binary_expression(binary_expression)
      }
      Expression::Error(ref error) => visitor.visit_error_token(error),
    }
  }

  pub fn walk_unary_expression<'a, V: AstVisitor<'a> + ?Sized>(
    visitor: &mut V,
    unary_expression: &'a UnaryExpression,
  ) -> () {
    if !visitor.should_continue() {
      return;
    }
    visitor.visit_unary_operator(&unary_expression.op);
    if !visitor.should_continue() {
      return;
    }
    visitor.visit_expression(&unary_expression.expr);
  }

  pub fn walk_binary_expression<'a, V: AstVisitor<'a> + ?Sized>(
    visitor: &mut V,
    binary_expression: &'a BinaryExpression,
  ) -> () {
    if !visitor.should_continue() {
      return;
    }
    visitor.visit_expression(&binary_expression.lhs);
    if !visitor.should_continue() {
      return;
    }
    visitor.visit_binary_operator(&binary_expression.op);
    if !visitor.should_continue() {
      return;
    }
    visitor.visit_expression(&binary_expression.rhs);
  }

  pub fn walk_error_token<'a, V: AstVisitor<'a> + ?Sized>(
    visitor: &mut V,
    error: &'a ErrorToken,
  ) -> () {
    match *error {
      ErrorToken::List(ref expressions) => {
        for expression in expressions {
          if !visitor.should_continue() {
            return;
          }
          visitor.visit_expression(&expression);
        }
      }
      _ => {}
    }
  }
}