Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ cfg-if = "1.0.4"
cidr = { version = "0.2.3", features = ["serde"] }
criterion = "0.8.2"
dyn-clone = "1.0.20"
dyn-eq = "0.1.3"
erased-serde = "0.4.10"
fnv = "1.0.7"
get-size2 = "0.11.0"
Expand Down
1 change: 1 addition & 0 deletions engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
authors.workspace = true
edition.workspace = true
description = "An execution engine for Wireshark-like filters"
readme = "README.md"

Check warning on line 7 in engine/Cargo.toml

View workflow job for this annotation

GitHub Actions / Test with miri

explicit `package.readme` can be inferred

Check warning on line 7 in engine/Cargo.toml

View workflow job for this annotation

GitHub Actions / Test with miri

explicit `package.readme` can be inferred

Check warning on line 7 in engine/Cargo.toml

View workflow job for this annotation

GitHub Actions / Test with -Zsanitizer=address

explicit `package.readme` can be inferred

Check warning on line 7 in engine/Cargo.toml

View workflow job for this annotation

GitHub Actions / Test with -Zsanitizer=leak

explicit `package.readme` can be inferred

Check warning on line 7 in engine/Cargo.toml

View workflow job for this annotation

GitHub Actions / Test with -Zsanitizer=thread

explicit `package.readme` can be inferred
repository = "https://github.com/cloudflare/wirefilter"
license = "MIT"
keywords = ["engine", "filter", "parser", "runtime", "wireshark"]
Expand All @@ -24,6 +24,7 @@
cfg-if.workspace = true
cidr.workspace = true
dyn-clone.workspace = true
dyn-eq.workspace = true
erased-serde.workspace = true
fnv.workspace = true
get-size2 = { workspace = true, optional = true }
Expand Down
18 changes: 11 additions & 7 deletions engine/src/ast/field_expr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::Expr;
use super::function_expr::FunctionCallExpr;
#[cfg(test)]
use super::parse::FilterParser;
use super::parse::ParserContext;
use super::visitor::{Visitor, VisitorMut};
use crate::ast::index_expr::{Compare, IndexExpr};
use crate::compiler::Compiler;
Expand Down Expand Up @@ -249,9 +251,9 @@ impl IdentifierExpr {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for IdentifierExpr {
fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
let (item, input) = Identifier::lex_with(input, parser.scheme)?;
impl<'i> LexWith<'i, &ParserContext<'_>> for IdentifierExpr {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (item, input) = Identifier::lex_with(input, parser.scheme())?;
match item {
Identifier::Field(field) => Ok((IdentifierExpr::Field(field.to_owned()), input)),
Identifier::Function(function) => {
Expand Down Expand Up @@ -296,8 +298,8 @@ impl GetType for ComparisonExpr {
}
}

impl<'i> LexWith<'i, &FilterParser<'_>> for ComparisonExpr {
fn lex_with(input: &'i str, parser: &FilterParser<'_>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for ComparisonExpr {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (lhs, input) = IndexExpr::lex_with(input, parser)?;

Self::lex_with_lhs(input, parser, lhs)
Expand All @@ -307,7 +309,7 @@ impl<'i> LexWith<'i, &FilterParser<'_>> for ComparisonExpr {
impl ComparisonExpr {
pub(crate) fn lex_with_lhs<'i>(
input: &'i str,
parser: &FilterParser<'_>,
parser: &ParserContext<'_>,
lhs: IndexExpr,
) -> LexResult<'i, Self> {
let lhs_type = lhs.get_type();
Expand Down Expand Up @@ -341,7 +343,7 @@ impl ComparisonExpr {
| (Type::Int, ComparisonOp::In) => {
if expect(input, "$").is_ok() {
let (name, input) = ListName::lex(input)?;
let list = parser.scheme.get_list(&lhs_type).ok_or((
let list = parser.scheme().get_list(&lhs_type).ok_or((
LexErrorKind::UnsupportedOp { lhs_type },
span(initial_input, input),
))?;
Expand Down Expand Up @@ -856,6 +858,8 @@ mod tests {
}

impl FunctionDefinition for FilterFunction {
type Settings = ();

fn check_param(
&self,
_: &ParserSettings,
Expand Down
25 changes: 12 additions & 13 deletions engine/src/ast/function_expr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::ValueExpr;
use super::parse::FilterParser;
use super::parse::ParserContext;
use super::visitor::{Visitor, VisitorMut};
use crate::FunctionRef;
use crate::ast::field_expr::{ComparisonExpr, ComparisonOp, ComparisonOpExpr, IdentifierExpr};
Expand All @@ -8,8 +8,8 @@ use crate::ast::logical_expr::{LogicalExpr, QuantifierOp, UnaryOp};
use crate::compiler::Compiler;
use crate::filter::{CompiledExpr, CompiledValueExpr, CompiledValueResult};
use crate::functions::{
CompiledFunction, ExactSizeChain, FunctionDefinition, FunctionDefinitionContext, FunctionParam,
FunctionParamError,
CompiledFunction, ErasedFunctionDefinition, ExactSizeChain, FunctionDefinitionContext,
FunctionParam, FunctionParamError,
};
use crate::lex::{Lex, LexError, LexErrorKind, LexResult, LexWith, expect, skip_space, span};
use crate::lhs_types::Array;
Expand Down Expand Up @@ -115,8 +115,8 @@ impl FunctionCallArgExpr {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FunctionCallArgExpr {
fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for FunctionCallArgExpr {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let _initial_input = input;

macro_rules! c_is_field {
Expand Down Expand Up @@ -409,7 +409,7 @@ impl FunctionCallExpr {

pub(crate) fn lex_with_function<'i>(
input: &'i str,
parser: &FilterParser<'_>,
parser: &ParserContext<'_>,
function: FunctionRef<'_>,
) -> LexResult<'i, Self> {
let definition = function.as_definition();
Expand All @@ -426,7 +426,7 @@ impl FunctionCallExpr {

let mut index = 0;

let mut ctx = definition.context();
let mut ctx = definition.context(parser.settings());

while let Some(c) = input.chars().next() {
if c == ')' {
Expand Down Expand Up @@ -539,7 +539,7 @@ impl FunctionCallExpr {
}
}

fn invalid_args_count<'i>(function: &dyn FunctionDefinition, input: &'i str) -> LexError<'i> {
fn invalid_args_count<'i>(function: &dyn ErasedFunctionDefinition, input: &'i str) -> LexError<'i> {
let (mandatory, optional) = function.arg_count();
(
LexErrorKind::InvalidArgumentsCount {
Expand All @@ -560,9 +560,9 @@ impl GetType for FunctionCallExpr {
}
}

impl<'i> LexWith<'i, &FilterParser<'_>> for FunctionCallExpr {
fn lex_with(input: &'i str, parser: &FilterParser<'_>) -> LexResult<'i, Self> {
let (function, rest) = FunctionRef::lex_with(input, parser.scheme)?;
impl<'i> LexWith<'i, &ParserContext<'_>> for FunctionCallExpr {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (function, rest) = FunctionRef::lex_with(input, parser.scheme())?;
let nested_parser = parser.with_increased_nesting(skip_space(rest))?;

Self::lex_with_function(rest, &nested_parser, function)
Expand Down Expand Up @@ -1144,9 +1144,8 @@ mod tests {
}
);

let expr = FunctionCallArgExpr::lex_with(
let expr = FilterParser::new(&SCHEME).lex_as::<FunctionCallArgExpr>(
"lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(lower(http.host)))))))))))))))))))))))))))))))) contains \"c\"",
&FilterParser::new(&SCHEME),
);
assert!(expr.is_ok());

Expand Down
6 changes: 3 additions & 3 deletions engine/src/ast/index_expr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::ValueExpr;
use super::field_expr::IdentifierExpr;
use super::parse::FilterParser;
use super::parse::ParserContext;
use super::visitor::{Visitor, VisitorMut};
use crate::compiler::Compiler;
use crate::execution_context::ExecutionContext;
Expand Down Expand Up @@ -314,8 +314,8 @@ impl IndexExpr {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for IndexExpr {
fn lex_with(mut input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for IndexExpr {
fn lex_with(mut input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (identifier, rest) = IdentifierExpr::lex_with(input, parser)?;

let mut current_type = identifier.get_type();
Expand Down
16 changes: 9 additions & 7 deletions engine/src/ast/logical_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use super::Expr;
use super::field_expr::ComparisonExpr;
use super::function_expr::FunctionCallArgExpr;
use super::index_expr::IndexExpr;
#[cfg(test)]
use super::parse::FilterParser;
use super::parse::ParserContext;
use super::visitor::{Visitor, VisitorMut};
use crate::compiler::Compiler;
use crate::filter::{CompiledExpr, CompiledOneExpr, CompiledVecExpr};
Expand Down Expand Up @@ -119,8 +121,8 @@ impl GetType for QuantifierArgExpr {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for QuantifierArgExpr {
fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for QuantifierArgExpr {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (arg, rest) = FunctionCallArgExpr::lex_with(input, parser)?;
let arg = match arg {
FunctionCallArgExpr::IndexExpr(index_expr) => Self::IndexExpr(index_expr),
Expand Down Expand Up @@ -208,7 +210,7 @@ impl LogicalExpr {

pub(crate) fn lex_quantifier<'i>(
input: &'i str,
parser: &FilterParser<'_>,
parser: &ParserContext<'_>,
) -> Option<LexResult<'i, (QuantifierOp, Box<QuantifierArgExpr>)>> {
let (op, rest) = QuantifierOp::lex_call(input)?;
let nested_parser = match parser.with_increased_nesting(skip_space(rest)) {
Expand All @@ -226,7 +228,7 @@ impl LogicalExpr {
})())
}

fn lex_simple_expr<'i>(input: &'i str, parser: &FilterParser<'_>) -> LexResult<'i, Self> {
fn lex_simple_expr<'i>(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
Ok(if let Ok(rest) = expect(input, "(") {
let nested_parser = parser.with_increased_nesting(input)?;
let input = skip_space(rest);
Expand Down Expand Up @@ -259,7 +261,7 @@ impl LogicalExpr {

fn lex_more_with_precedence<'i>(
self,
parser: &FilterParser<'_>,
parser: &ParserContext<'_>,
min_prec: Option<LogicalOp>,
mut lookahead: (Option<LogicalOp>, &'i str),
) -> LexResult<'i, Self> {
Expand Down Expand Up @@ -323,8 +325,8 @@ impl LogicalExpr {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for LogicalExpr {
fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for LogicalExpr {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (lhs, input) = Self::lex_simple_expr(input, parser)?;
let lookahead = Self::lex_combining_op(input);
lhs.lex_more_with_precedence(parser, None, lookahead)
Expand Down
24 changes: 10 additions & 14 deletions engine/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod visitor;

use self::index_expr::IndexExpr;
use self::logical_expr::{LogicalExpr, QuantifierArgExpr, QuantifierOp};
use self::parse::FilterParser;
use self::parse::ParserContext;
use self::visitor::{UsesListVisitor, UsesVisitor, Visitor, VisitorMut};
use crate::compiler::{Compiler, DefaultCompiler};
use crate::filter::{CompiledExpr, CompiledValueExpr, Filter, FilterValue};
Expand All @@ -18,9 +18,7 @@ use serde::Serialize;
use std::fmt::{self, Debug};

/// Trait used to represent node that evaluates to a [`bool`] (or a [`Vec<bool>`]).
pub trait Expr:
Sized + Eq + Debug + for<'i, 'p, 's> LexWith<'i, &'p FilterParser<'s>> + Serialize
{
pub trait Expr: Sized + Eq + Debug + Serialize {
/// Recursively visit all nodes in the AST using a [`Visitor`].
fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V);
/// Recursively visit all nodes in the AST using a [`VisitorMut`].
Expand All @@ -35,9 +33,7 @@ pub trait Expr:
}

/// Trait used to represent node that evaluates to an [`crate::LhsValue`].
pub trait ValueExpr:
Sized + Eq + Debug + for<'i, 'p, 's> LexWith<'i, &'p FilterParser<'s>> + Serialize
{
pub trait ValueExpr: Sized + Eq + Debug + Serialize {
/// Recursively visit all nodes in the AST using a [`Visitor`].
fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V);
/// Recursively visit all nodes in the AST using a [`VisitorMut`].
Expand Down Expand Up @@ -71,8 +67,8 @@ impl Debug for FilterAst {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterAst {
fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for FilterAst {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (op, input) = LogicalExpr::lex_with(input, parser)?;
// LogicalExpr::lex_with can return an AST where the root is an
// LogicalExpr::Combining of type [`Array(Bool)`].
Expand All @@ -88,7 +84,7 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterAst {
match ty {
Type::Bool => Ok((
FilterAst {
scheme: parser.scheme.clone(),
scheme: parser.scheme().clone(),
op,
},
input,
Expand Down Expand Up @@ -192,8 +188,8 @@ impl Debug for FilterValueExpr {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterValueExpr {
fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for FilterValueExpr {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
match IndexExpr::lex_with(input, parser) {
Ok((expr, rest)) => Ok((FilterValueExpr::Index(expr), rest)),
Err(index_err) => match LogicalExpr::lex_quantifier(input, parser) {
Expand Down Expand Up @@ -265,8 +261,8 @@ impl Debug for FilterValueAst {
}
}

impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterValueAst {
fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> {
impl<'i> LexWith<'i, &ParserContext<'_>> for FilterValueAst {
fn lex_with(input: &'i str, parser: &ParserContext<'_>) -> LexResult<'i, Self> {
let (op, rest) = FilterValueExpr::lex_with(input.trim(), parser)?;
if let FilterValueExpr::Index(expr) = &op
&& expr.map_each_count() > 0
Expand Down
Loading
Loading