diff --git a/engine/src/ast/field_expr.rs b/engine/src/ast/field_expr.rs index 84d8f5ac..7de49a15 100644 --- a/engine/src/ast/field_expr.rs +++ b/engine/src/ast/field_expr.rs @@ -11,10 +11,11 @@ use crate::{ lex::{expect, skip_space, span, Lex, LexErrorKind, LexResult, LexWith}, range_set::RangeSet, rhs_types::{Bytes, ExplicitIpRange, ListName, Regex, Wildcard}, - scheme::{Field, Identifier, List}, + scheme::Identifier, searcher::{EmptySearcher, TwoWaySearcher}, strict_partial_ord::StrictPartialOrd, types::{GetType, LhsValue, RhsValue, RhsValues, Type}, + Field, List, }; use serde::{Serialize, Serializer}; use sliceslice::MemchrSearcher; @@ -116,7 +117,7 @@ lex_enum!(ComparisonOp { /// comparison expression. #[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize)] #[serde(untagged)] -pub enum ComparisonOpExpr<'s> { +pub enum ComparisonOpExpr { /// Boolean field verification #[serde(serialize_with = "serialize_is_true")] IsTrue, @@ -172,7 +173,7 @@ pub enum ComparisonOpExpr<'s> { #[serde(serialize_with = "serialize_list")] InList { /// `List` from the `Scheme` - list: List<'s>, + list: List, /// List name name: ListName, }, @@ -226,7 +227,7 @@ fn serialize_contains_one_of(rhs: &[Bytes], ser: S) -> Result(_: &List<'_>, name: &ListName, ser: S) -> Result { +fn serialize_list(_: &List, name: &ListName, ser: S) -> Result { serialize_op_rhs("InList", name, ser) } @@ -234,18 +235,18 @@ fn serialize_list(_: &List<'_>, name: &ListName, ser: S) -> Resul /// a function call. #[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize)] #[serde(untagged)] -pub enum IdentifierExpr<'s> { +pub enum IdentifierExpr { /// Field access - Field(Field<'s>), + Field(Field), /// Function call - FunctionCallExpr(FunctionCallExpr<'s>), + FunctionCallExpr(FunctionCallExpr), } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for IdentifierExpr<'s> { +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)?; match item { - Identifier::Field(field) => Ok((IdentifierExpr::Field(field), input)), + Identifier::Field(field) => Ok((IdentifierExpr::Field(field.to_owned()), input)), Identifier::Function(function) => { FunctionCallExpr::lex_with_function(input, parser, function) .map(|(call, input)| (IdentifierExpr::FunctionCallExpr(call), input)) @@ -254,7 +255,7 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for IdentifierExpr<'s> { } } -impl GetType for IdentifierExpr<'_> { +impl GetType for IdentifierExpr { fn get_type(&self) -> Type { match self { IdentifierExpr::Field(field) => field.get_type(), @@ -265,16 +266,16 @@ impl GetType for IdentifierExpr<'_> { /// Comparison expression #[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize)] -pub struct ComparisonExpr<'s> { +pub struct ComparisonExpr { /// Left-hand side of the comparison expression - pub lhs: IndexExpr<'s>, + pub lhs: IndexExpr, /// Operator + right-hand side of the comparison expression #[serde(flatten)] - pub op: ComparisonOpExpr<'s>, + pub op: ComparisonOpExpr, } -impl GetType for ComparisonExpr<'_> { +impl GetType for ComparisonExpr { fn get_type(&self) -> Type { if self.lhs.map_each_count() > 0 { Type::Array(Type::Bool.into()) @@ -287,19 +288,19 @@ impl GetType for ComparisonExpr<'_> { } } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for ComparisonExpr<'s> { - fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { +impl<'i> LexWith<'i, &FilterParser<'_>> for ComparisonExpr { + fn lex_with(input: &'i str, parser: &FilterParser<'_>) -> LexResult<'i, Self> { let (lhs, input) = IndexExpr::lex_with(input, parser)?; Self::lex_with_lhs(input, parser, lhs) } } -impl<'s> ComparisonExpr<'s> { +impl ComparisonExpr { pub(crate) fn lex_with_lhs<'i>( input: &'i str, - parser: &FilterParser<'s>, - lhs: IndexExpr<'s>, + parser: &FilterParser<'_>, + lhs: IndexExpr, ) -> LexResult<'i, Self> { let lhs_type = lhs.get_type(); @@ -336,7 +337,13 @@ impl<'s> ComparisonExpr<'s> { LexErrorKind::UnsupportedOp { lhs_type }, span(initial_input, input), ))?; - (ComparisonOpExpr::InList { name, list }, input) + ( + ComparisonOpExpr::InList { + name, + list: list.to_owned(), + }, + input, + ) } else { let (rhs, input) = RhsValues::lex_with(input, lhs_type)?; (ComparisonOpExpr::OneOf(rhs), input) @@ -383,31 +390,28 @@ impl<'s> ComparisonExpr<'s> { } /// Retrieves the associated left hand side expression. - pub fn lhs_expr(&self) -> &IndexExpr<'s> { + pub fn lhs_expr(&self) -> &IndexExpr { &self.lhs } /// Retrieves the operator applied to the left hand side expression. - pub fn operator(&self) -> &ComparisonOpExpr<'s> { + pub fn operator(&self) -> &ComparisonOpExpr { &self.op } } -impl<'s> Expr<'s> for ComparisonExpr<'s> { +impl Expr for ComparisonExpr { #[inline] - fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V) { + fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { visitor.visit_index_expr(&self.lhs) } #[inline] - fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V) { + fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V) { visitor.visit_index_expr(&mut self.lhs) } - fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> CompiledExpr<'s, C::U> { + fn compile_with_compiler(self, compiler: &mut C) -> CompiledExpr { let lhs = self.lhs; macro_rules! cast_value { @@ -632,7 +636,7 @@ impl<'s> Expr<'s> for ComparisonExpr<'s> { } ComparisonOpExpr::InList { name, list } => { lhs.compile_with(compiler, false, move |val, ctx| { - ctx.get_list_matcher_unchecked(list) + ctx.get_list_matcher_unchecked(&list) .match_value(name.as_str(), val) }) } @@ -660,7 +664,7 @@ mod tests { rhs_types::{IpRange, RegexFormat}, scheme::{FieldIndex, IndexAccessError, Scheme}, types::ExpectedType, - BytesFormat, ParserSettings, + BytesFormat, FieldRef, ParserSettings, }; use cidr::IpCidr; use std::sync::LazyLock; @@ -751,12 +755,16 @@ mod tests { (2, Some(0)) } - fn compile<'s>( - &'s self, + fn compile( + &self, _: &mut dyn ExactSizeIterator>, _: Option, - ) -> Box Fn(FunctionArgs<'_, 'a>) -> Option> + Sync + Send + 's> - { + ) -> Box< + dyn for<'i, 'a> Fn(FunctionArgs<'i, 'a>) -> Option> + + Sync + + Send + + 'static, + > { Box::new(|args| { let value_array = Array::try_from(args.next().unwrap().unwrap()).unwrap(); let keep_array = Array::try_from(args.next().unwrap().unwrap()).unwrap(); @@ -899,7 +907,7 @@ mod tests { builder.build() }); - fn field(name: &'static str) -> Field<'static> { + fn field(name: &'static str) -> FieldRef<'static> { SCHEME.get_field(name).unwrap() } @@ -909,7 +917,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as("ssl"), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("ssl")), + identifier: IdentifierExpr::Field(field("ssl").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::IsTrue @@ -940,7 +948,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as("ip.addr <= 10:20:30:40:50:60:70:80"), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("ip.addr")), + identifier: IdentifierExpr::Field(field("ip.addr").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Ordering { @@ -995,7 +1003,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as("http.host >= 10:20:30:40:50:60:70:80"), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Ordering { @@ -1020,7 +1028,7 @@ mod tests { // just check that parsing doesn't conflict with regular numbers { assert_err!( - FilterParser::new(&SCHEME).lex_as::>(r#"http.host < 12"#), + FilterParser::new(&SCHEME).lex_as::(r#"http.host < 12"#), LexErrorKind::CountMismatch { name: "character", actual: 0, @@ -1033,7 +1041,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.host < 12:13"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Ordering { @@ -1057,7 +1065,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.host == "example.org""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Ordering { @@ -1094,7 +1102,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as("tcp.port & 1"), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("tcp.port")), + identifier: IdentifierExpr::Field(field("tcp.port").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Int { @@ -1129,7 +1137,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"tcp.port in { 80 443 2082..2083 }"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("tcp.port")), + identifier: IdentifierExpr::Field(field("tcp.port").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::OneOf(RhsValues::Int(vec![ @@ -1184,7 +1192,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.host in { "example.org" "example.com" }"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::OneOf(RhsValues::Bytes( @@ -1231,7 +1239,7 @@ mod tests { .lex_as(r#"ip.addr in { 127.0.0.0/8 ::1 10.0.0.0..10.0.255.255 }"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("ip.addr")), + identifier: IdentifierExpr::Field(field("ip.addr").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::OneOf(RhsValues::Ip(vec![ @@ -1287,7 +1295,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.host contains "abc""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Contains("abc".to_owned().into()) @@ -1321,7 +1329,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.host contains 6F:72:67"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Contains(vec![0x6F, 0x72, 0x67].into()), @@ -1355,7 +1363,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"tcp.port < 8000"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("tcp.port")), + identifier: IdentifierExpr::Field(field("tcp.port").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Ordering { @@ -1390,7 +1398,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.cookies[0] contains "abc""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![FieldIndex::ArrayIndex(0)], }, op: ComparisonOpExpr::Contains("abc".to_owned().into()), @@ -1417,7 +1425,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.headers["host"] contains "abc""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.headers")), + identifier: IdentifierExpr::Field(field("http.headers").to_owned()), indexes: vec![FieldIndex::MapKey("host".to_string())], }, op: ComparisonOpExpr::Contains("abc".to_owned().into()), @@ -1465,9 +1473,9 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], })], context: None, @@ -1521,9 +1529,9 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("lowercase").unwrap(), + function: SCHEME.get_function("lowercase").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], })], context: None, @@ -1576,7 +1584,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.cookies[0] == "example.org""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![FieldIndex::ArrayIndex(0)], }, op: ComparisonOpExpr::Ordering { @@ -1612,7 +1620,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.cookies[0] != "example.org""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![FieldIndex::ArrayIndex(0)], }, op: ComparisonOpExpr::Ordering { @@ -1648,7 +1656,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.headers["missing"] == "example.org""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.headers")), + identifier: IdentifierExpr::Field(field("http.headers").to_owned()), indexes: vec![FieldIndex::MapKey("missing".into())], }, op: ComparisonOpExpr::Ordering { @@ -1684,7 +1692,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.headers["missing"] != "example.org""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.headers")), + identifier: IdentifierExpr::Field(field("http.headers").to_owned()), indexes: vec![FieldIndex::MapKey("missing".into())], }, op: ComparisonOpExpr::Ordering { @@ -1721,9 +1729,9 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("concat").unwrap(), + function: SCHEME.get_function("concat").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], })], context: None, @@ -1774,10 +1782,10 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("concat").unwrap(), + function: SCHEME.get_function("concat").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }), FunctionCallArgExpr::Literal(RhsValue::Bytes(Bytes::from( @@ -1839,14 +1847,16 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("filter").unwrap(), + function: SCHEME.get_function("filter").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![], }), FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("array.of.bool")), + identifier: IdentifierExpr::Field( + field("array.of.bool").to_owned() + ), indexes: vec![], }), ], @@ -1912,10 +1922,10 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("concat").unwrap(), + function: SCHEME.get_function("concat").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![FieldIndex::MapEach], }), FunctionCallArgExpr::Literal(RhsValue::Bytes(Bytes::from( @@ -1981,10 +1991,10 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("concat").unwrap(), + function: SCHEME.get_function("concat").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.headers")), + identifier: IdentifierExpr::Field(field("http.headers").to_owned()), indexes: vec![FieldIndex::MapEach], }), FunctionCallArgExpr::Literal(RhsValue::Bytes(Bytes::from( @@ -2055,7 +2065,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.cookies[*] == "three""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![FieldIndex::MapEach], }, op: ComparisonOpExpr::Ordering { @@ -2089,7 +2099,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.headers[*] == "three""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.headers")), + identifier: IdentifierExpr::Field(field("http.headers").to_owned()), indexes: vec![FieldIndex::MapEach], }, op: ComparisonOpExpr::Ordering { @@ -2147,10 +2157,10 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("concat").unwrap(), + function: SCHEME.get_function("concat").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![FieldIndex::MapEach], }), FunctionCallArgExpr::Literal(RhsValue::Bytes(Bytes::from( @@ -2215,9 +2225,9 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("len").unwrap(), + function: SCHEME.get_function("len").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.cookies")), + identifier: IdentifierExpr::Field(field("http.cookies").to_owned()), indexes: vec![FieldIndex::MapEach], }),], context: None, @@ -2270,7 +2280,7 @@ mod tests { #[test] fn test_map_each_error() { assert_err!( - FilterParser::new(&SCHEME).lex_as::>(r#"http.host[*] == "three""#), + FilterParser::new(&SCHEME).lex_as::(r#"http.host[*] == "three""#), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Bytes, @@ -2279,7 +2289,7 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(r#"ip.addr[*] == 127.0.0.1"#), + FilterParser::new(&SCHEME).lex_as::(r#"ip.addr[*] == 127.0.0.1"#), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Ip, @@ -2288,7 +2298,7 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(r#"ssl[*]"#), + FilterParser::new(&SCHEME).lex_as::(r#"ssl[*]"#), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Bool, @@ -2297,7 +2307,7 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(r#"tcp.port[*] == 80"#), + FilterParser::new(&SCHEME).lex_as::(r#"tcp.port[*] == 80"#), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Int, @@ -2351,11 +2361,11 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"tcp.port in $even"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("tcp.port")), + identifier: IdentifierExpr::Field(field("tcp.port").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::InList { - list, + list: list.to_owned(), name: ListName::from("even".to_string()) } } @@ -2385,11 +2395,11 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"tcp.port in $odd"#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("tcp.port")), + identifier: IdentifierExpr::Field(field("tcp.port").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::InList { - list, + list: list.to_owned(), name: ListName::from("odd".to_string()), } } @@ -2415,15 +2425,17 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("any").unwrap(), + function: SCHEME.get_function("any").unwrap().to_owned(), args: vec![FunctionCallArgExpr::Logical(LogicalExpr::Comparison( ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("tcp.ports")), + identifier: IdentifierExpr::Field( + field("tcp.ports").to_owned() + ), indexes: vec![FieldIndex::MapEach], }, op: ComparisonOpExpr::InList { - list, + list: list.to_owned(), name: ListName::from("even".to_string()), }, } @@ -2483,7 +2495,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.parts[*][*] == "[5][5]""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.parts")), + identifier: IdentifierExpr::Field(field("http.parts").to_owned()), indexes: vec![FieldIndex::MapEach, FieldIndex::MapEach], }, op: ComparisonOpExpr::Ordering { @@ -2510,7 +2522,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.parts[5][*] == "[5][5]""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.parts")), + identifier: IdentifierExpr::Field(field("http.parts").to_owned()), indexes: vec![FieldIndex::ArrayIndex(5), FieldIndex::MapEach], }, op: ComparisonOpExpr::Ordering { @@ -2537,7 +2549,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"http.parts[*][5] == "[5][5]""#), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.parts")), + identifier: IdentifierExpr::Field(field("http.parts").to_owned()), indexes: vec![FieldIndex::MapEach, FieldIndex::ArrayIndex(5)], }, op: ComparisonOpExpr::Ordering { @@ -2614,7 +2626,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as("http.host == r###\"ab\"###"), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Ordering { @@ -2649,7 +2661,7 @@ mod tests { parser.lex_as("http.host matches r###\"a.b\"###"), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Matches(r), @@ -2684,7 +2696,7 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#####"http.host wildcard r##"foo*\*\\"##"#####), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::Wildcard(wildcard), @@ -2729,7 +2741,7 @@ mod tests { .lex_as(r#####"http.host strict wildcard r##"foo*\*\\"##"#####), ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }, op: ComparisonOpExpr::StrictWildcard(wildcard), @@ -2769,10 +2781,10 @@ mod tests { ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("concat").unwrap(), + function: SCHEME.get_function("concat").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(field("http.host")), + identifier: IdentifierExpr::Field(field("http.host").to_owned()), indexes: vec![], }), FunctionCallArgExpr::Literal(RhsValue::Bytes(Bytes::new( @@ -2866,7 +2878,7 @@ mod tests { .concat(); for t @ (op, rhs, value, expected) in testcases { - let expr: ComparisonExpr<'_> = FilterParser::new(&SCHEME) + let expr: ComparisonExpr = FilterParser::new(&SCHEME) .lex_as(&format!("http.host {op} {rhs}")) .map(|(e, _)| e) .expect("failed to parse expression"); diff --git a/engine/src/ast/function_expr.rs b/engine/src/ast/function_expr.rs index fdf3b97a..1d9d1637 100644 --- a/engine/src/ast/function_expr.rs +++ b/engine/src/ast/function_expr.rs @@ -19,6 +19,7 @@ use crate::{ lhs_types::Array, scheme::Function, types::{GetType, LhsValue, RhsValue, Type}, + FunctionRef, }; use serde::Serialize; use std::hash::{Hash, Hasher}; @@ -27,9 +28,9 @@ use std::iter::once; /// Represents a function argument in a function call. #[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize)] #[serde(tag = "kind", content = "value")] -pub enum FunctionCallArgExpr<'s> { +pub enum FunctionCallArgExpr { /// A sub-expression which evaluates to a value. - IndexExpr(IndexExpr<'s>), + IndexExpr(IndexExpr), /// A literal value. Literal(RhsValue), /// A sub-expression which evaluates to either `true`/`false` @@ -37,12 +38,12 @@ pub enum FunctionCallArgExpr<'s> { /// and is coerced into a [`CompiledValueExpr`]`. // Renaming is necessary for backward compability. #[serde(rename = "SimpleExpr")] - Logical(LogicalExpr<'s>), + Logical(LogicalExpr), } -impl<'s> ValueExpr<'s> for FunctionCallArgExpr<'s> { +impl ValueExpr for FunctionCallArgExpr { #[inline] - fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V) { + fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { match self { FunctionCallArgExpr::IndexExpr(index_expr) => visitor.visit_index_expr(index_expr), FunctionCallArgExpr::Literal(_) => {} @@ -51,7 +52,7 @@ impl<'s> ValueExpr<'s> for FunctionCallArgExpr<'s> { } #[inline] - fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V) { + fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V) { match self { FunctionCallArgExpr::IndexExpr(index_expr) => visitor.visit_index_expr(index_expr), FunctionCallArgExpr::Literal(_) => {} @@ -59,10 +60,7 @@ impl<'s> ValueExpr<'s> for FunctionCallArgExpr<'s> { } } - fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> CompiledValueExpr<'s, C::U> { + fn compile_with_compiler(self, compiler: &mut C) -> CompiledValueExpr { match self { FunctionCallArgExpr::IndexExpr(index_expr) => compiler.compile_index_expr(index_expr), FunctionCallArgExpr::Literal(literal) => { @@ -88,7 +86,7 @@ impl<'s> ValueExpr<'s> for FunctionCallArgExpr<'s> { } } -impl FunctionCallArgExpr<'_> { +impl FunctionCallArgExpr { pub(crate) fn map_each_count(&self) -> usize { match self { FunctionCallArgExpr::IndexExpr(index_expr) => index_expr.map_each_count(), @@ -109,7 +107,7 @@ impl FunctionCallArgExpr<'_> { } } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FunctionCallArgExpr<'s> { +impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FunctionCallArgExpr { fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { let _initial_input = input; @@ -194,7 +192,7 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FunctionCallArgExpr<'s> { } } -impl GetType for FunctionCallArgExpr<'_> { +impl GetType for FunctionCallArgExpr { fn get_type(&self) -> Type { match self { FunctionCallArgExpr::IndexExpr(index_expr) => index_expr.get_type(), @@ -204,8 +202,8 @@ impl GetType for FunctionCallArgExpr<'_> { } } -impl<'a, 's> From<&'a FunctionCallArgExpr<'s>> for FunctionParam<'a> { - fn from(arg_expr: &'a FunctionCallArgExpr<'s>) -> Self { +impl<'a> From<&'a FunctionCallArgExpr> for FunctionParam<'a> { + fn from(arg_expr: &'a FunctionCallArgExpr) -> Self { match arg_expr { FunctionCallArgExpr::IndexExpr(expr) => FunctionParam::Variable(expr.get_type()), FunctionCallArgExpr::Logical(expr) => FunctionParam::Variable(expr.get_type()), @@ -216,24 +214,24 @@ impl<'a, 's> From<&'a FunctionCallArgExpr<'s>> for FunctionParam<'a> { /// FunctionCallExpr represents a function call expression. #[derive(Clone, Debug, Serialize)] -pub struct FunctionCallExpr<'s> { +pub struct FunctionCallExpr { #[serde(rename = "name")] - pub(crate) function: Function<'s>, - pub(crate) args: Vec>, + pub(crate) function: Function, + pub(crate) args: Vec, #[serde(skip)] pub(crate) context: Option, } -impl PartialEq for FunctionCallExpr<'_> { +impl PartialEq for FunctionCallExpr { #[inline] fn eq(&self, other: &Self) -> bool { self.function == other.function && self.args == other.args } } -impl Eq for FunctionCallExpr<'_> {} +impl Eq for FunctionCallExpr {} -impl Hash for FunctionCallExpr<'_> { +impl Hash for FunctionCallExpr { #[inline] fn hash(&self, state: &mut H) { self.function.hash(state); @@ -241,9 +239,9 @@ impl Hash for FunctionCallExpr<'_> { } } -impl<'s> ValueExpr<'s> for FunctionCallExpr<'s> { +impl ValueExpr for FunctionCallExpr { #[inline] - fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V) { + fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { self.args .iter() .for_each(|arg| visitor.visit_function_call_arg_expr(arg)); @@ -251,17 +249,14 @@ impl<'s> ValueExpr<'s> for FunctionCallExpr<'s> { } #[inline] - fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V) { + fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V) { self.args .iter_mut() .for_each(|arg| visitor.visit_function_call_arg_expr(arg)); visitor.visit_function(&self.function) } - fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> CompiledValueExpr<'s, C::U> { + fn compile_with_compiler(self, compiler: &mut C) -> CompiledValueExpr { let return_type = self.return_type(); let Self { @@ -354,14 +349,14 @@ impl<'s> ValueExpr<'s> for FunctionCallExpr<'s> { } } -impl<'s> FunctionCallExpr<'s> { +impl FunctionCallExpr { pub(crate) fn new( - function: Function<'s>, - args: Vec>, + function: Function, + args: Vec, context: Option, ) -> Self { Self { - function, + function: function.to_owned(), args, context, } @@ -369,8 +364,8 @@ impl<'s> FunctionCallExpr<'s> { pub(crate) fn lex_with_function<'i>( input: &'i str, - parser: &FilterParser<'s>, - function: Function<'s>, + parser: &FilterParser<'_>, + function: FunctionRef<'_>, ) -> LexResult<'i, Self> { let definition = function.as_definition(); @@ -382,7 +377,7 @@ impl<'s> FunctionCallExpr<'s> { let (mandatory_arg_count, optional_arg_count) = definition.arg_count(); - let mut args: Vec> = Vec::new(); + let mut args: Vec = Vec::new(); let mut index = 0; @@ -460,20 +455,20 @@ impl<'s> FunctionCallExpr<'s> { input = expect(input, ")")?; - let function_call = FunctionCallExpr::new(function, args, ctx); + let function_call = FunctionCallExpr::new(function.to_owned(), args, ctx); Ok((function_call, input)) } /// Returns the function being called. #[inline] - pub fn function(&self) -> Function<'s> { - self.function + pub fn function(&self) -> FunctionRef<'_> { + self.function.as_ref() } /// Returns the arguments being passed to the function. #[inline] - pub fn args(&self) -> &[FunctionCallArgExpr<'s>] { + pub fn args(&self) -> &[FunctionCallArgExpr] { &self.args[..] } @@ -510,7 +505,7 @@ fn invalid_args_count<'i>(function: &dyn FunctionDefinition, input: &'i str) -> ) } -impl GetType for FunctionCallExpr<'_> { +impl GetType for FunctionCallExpr { fn get_type(&self) -> Type { if !self.args.is_empty() && self.args[0].map_each_count() > 0 { Type::Array(self.return_type().into()) @@ -520,9 +515,9 @@ impl GetType for FunctionCallExpr<'_> { } } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FunctionCallExpr<'s> { - fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { - let (function, rest) = Function::lex_with(input, parser.scheme)?; +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)?; Self::lex_with_function(rest, parser, function) } @@ -700,10 +695,12 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as(r#"echo ( http.host, 1, 2 );"#), FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("http.host").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("http.host").unwrap().to_owned() + ), indexes: vec![], }), FunctionCallArgExpr::Literal(RhsValue::Int(1)), @@ -741,9 +738,11 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as("echo ( http.host );"), FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("http.host").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("http.host").unwrap().to_owned() + ), indexes: vec![], })], context: None, @@ -771,10 +770,12 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as(r#"echo (http.host,1,2);"#), FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("http.host").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("http.host").unwrap().to_owned() + ), indexes: vec![], }), FunctionCallArgExpr::Literal(RhsValue::Int(1)), @@ -810,7 +811,7 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>("echo ( );"), + FilterParser::new(&SCHEME).lex_as::("echo ( );"), LexErrorKind::InvalidArgumentsCount { expected_min: 1, expected_max: Some(3), @@ -820,7 +821,7 @@ mod tests { assert_err!( FilterParser::new(&SCHEME) - .lex_as::>("echo ( http.host , http.host );"), + .lex_as::("echo ( http.host , http.host );"), LexErrorKind::InvalidArgumentKind { index: 1, mismatch: FunctionArgKindMismatchError { @@ -834,13 +835,13 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as("echo ( echo ( http.host ) );"), FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: [FunctionCallArgExpr::IndexExpr(IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { identifier: IdentifierExpr::Field( - SCHEME.get_field("http.host").unwrap() + SCHEME.get_field("http.host").unwrap().to_owned() ), indexes: vec![], })], @@ -883,7 +884,7 @@ mod tests { r#"any ( ( http.request.headers.is_empty or http.request.headers.is_empty ) )"# ), FunctionCallExpr { - function: SCHEME.get_function("any").unwrap(), + function: SCHEME.get_function("any").unwrap().to_owned(), args: vec![FunctionCallArgExpr::Logical(LogicalExpr::Parenthesized( Box::new(ParenthesizedExpr { expr: LogicalExpr::Combining { @@ -895,6 +896,7 @@ mod tests { SCHEME .get_field("http.request.headers.is_empty") .unwrap() + .to_owned() ), indexes: vec![], }, @@ -906,6 +908,7 @@ mod tests { SCHEME .get_field("http.request.headers.is_empty") .unwrap() + .to_owned() ), indexes: vec![], }, @@ -951,10 +954,13 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as("echo ( http.request.headers.names[*] );"), FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { identifier: IdentifierExpr::Field( - SCHEME.get_field("http.request.headers.names").unwrap() + SCHEME + .get_field("http.request.headers.names") + .unwrap() + .to_owned() ), indexes: vec![FieldIndex::MapEach], })], @@ -982,9 +988,11 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as("echo ( http.headers[*] );"), FunctionCallExpr { - function: SCHEME.get_function("echo").unwrap(), + function: SCHEME.get_function("echo").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("http.headers").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("http.headers").unwrap().to_owned() + ), indexes: vec![FieldIndex::MapEach], })], context: None, @@ -1013,7 +1021,10 @@ mod tests { FunctionCallArgExpr::Logical(LogicalExpr::Comparison(ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::Field( - SCHEME.get_field("http.request.headers.names").unwrap() + SCHEME + .get_field("http.request.headers.names") + .unwrap() + .to_owned() ), indexes: vec![FieldIndex::MapEach], }, @@ -1029,15 +1040,18 @@ mod tests { FilterParser::new(&SCHEME) .lex_as("any(lower(http.request.headers.names[*])[*] contains \"c\")"), FunctionCallExpr { - function: SCHEME.get_function("any").unwrap(), + function: SCHEME.get_function("any").unwrap().to_owned(), args: vec![FunctionCallArgExpr::Logical(LogicalExpr::Comparison( ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("lower").unwrap(), + function: SCHEME.get_function("lower").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { identifier: IdentifierExpr::Field( - SCHEME.get_field("http.request.headers.names").unwrap() + SCHEME + .get_field("http.request.headers.names") + .unwrap() + .to_owned() ), indexes: vec![FieldIndex::MapEach], })], @@ -1091,10 +1105,13 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as("len(http.request.headers.names[*])"), FunctionCallExpr { - function: SCHEME.get_function("len").unwrap(), + function: SCHEME.get_function("len").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { identifier: IdentifierExpr::Field( - SCHEME.get_field("http.request.headers.names").unwrap() + SCHEME + .get_field("http.request.headers.names") + .unwrap() + .to_owned() ), indexes: vec![FieldIndex::MapEach], })], @@ -1114,14 +1131,17 @@ mod tests { FilterParser::new(&SCHEME) .lex_as("any(not(http.request.headers.names[*] in {\"Cookie\" \"Cookies\"}))"), FunctionCallExpr { - function: SCHEME.get_function("any").unwrap(), + function: SCHEME.get_function("any").unwrap().to_owned(), args: vec![FunctionCallArgExpr::Logical(LogicalExpr::Unary { op: UnaryOp::Not, arg: Box::new(LogicalExpr::Parenthesized(Box::new(ParenthesizedExpr { expr: LogicalExpr::Comparison(ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::Field( - SCHEME.get_field("http.request.headers.names").unwrap() + SCHEME + .get_field("http.request.headers.names") + .unwrap() + .to_owned() ), indexes: vec![FieldIndex::MapEach], }, @@ -1172,14 +1192,17 @@ mod tests { FilterParser::new(&SCHEME) .lex_as("any(!(http.request.headers.names[*] in {\"Cookie\" \"Cookies\"}))"), FunctionCallExpr { - function: SCHEME.get_function("any").unwrap(), + function: SCHEME.get_function("any").unwrap().to_owned(), args: vec![FunctionCallArgExpr::Logical(LogicalExpr::Unary { op: UnaryOp::Not, arg: Box::new(LogicalExpr::Parenthesized(Box::new(ParenthesizedExpr { expr: LogicalExpr::Comparison(ComparisonExpr { lhs: IndexExpr { identifier: IdentifierExpr::Field( - SCHEME.get_field("http.request.headers.names").unwrap() + SCHEME + .get_field("http.request.headers.names") + .unwrap() + .to_owned() ), indexes: vec![FieldIndex::MapEach], }, @@ -1232,10 +1255,10 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as("regex_replace(http.host, r\"this is a r##raw## string\", r\"this is a new r##raw## string\") eq \"test\""), FunctionCallExpr { - function: SCHEME.get_function("regex_replace").unwrap(), + function: SCHEME.get_function("regex_replace").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("http.host").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("http.host").unwrap().to_owned()), indexes: vec![], }), FunctionCallArgExpr::Literal(RhsValue::Bytes(Bytes::new("this is a r##raw## string".as_bytes(), BytesFormat::Raw(0)))), @@ -1273,10 +1296,10 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as("regex_replace(http.host, r###\"this is a r##\"raw\"## string\"###, r###\"this is a new r##\"raw\"## string\"###) eq \"test\""), FunctionCallExpr { - function: SCHEME.get_function("regex_replace").unwrap(), + function: SCHEME.get_function("regex_replace").unwrap().to_owned(), args: vec![ FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("http.host").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("http.host").unwrap().to_owned()), indexes: vec![], }), FunctionCallArgExpr::Literal(RhsValue::Bytes(Bytes::new("this is a r##\"raw\"## string".as_bytes(), BytesFormat::Raw(3)))), @@ -1312,25 +1335,22 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>( - "regex_replace(http.host, r#\"a\", \"b\") eq \"c\"" - ), + FilterParser::new(&SCHEME) + .lex_as::("regex_replace(http.host, r#\"a\", \"b\") eq \"c\""), LexErrorKind::MissingEndingQuote {}, "#\"a\", \"b\") eq \"c\"" ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>( - "regex_replace(http.host, r\"a\"#, \"b\") eq \"c\"" - ), + FilterParser::new(&SCHEME) + .lex_as::("regex_replace(http.host, r\"a\"#, \"b\") eq \"c\""), LexErrorKind::ExpectedLiteral(","), "#, \"b\") eq \"c\"" ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>( - "regex_replace(http.host, r##\"a\"#, \"b\") eq \"c\"" - ), + FilterParser::new(&SCHEME) + .lex_as::("regex_replace(http.host, r##\"a\"#, \"b\") eq \"c\""), LexErrorKind::MissingEndingQuote {}, "##\"a\"#, \"b\") eq \"c\"" ); @@ -1339,7 +1359,7 @@ mod tests { #[test] fn test_lex_function_call_expr_failure() { assert_err!( - FilterParser::new(&SCHEME).lex_as::>("echo ( \"test\" );"), + FilterParser::new(&SCHEME).lex_as::("echo ( \"test\" );"), LexErrorKind::InvalidArgumentKind { index: 0, mismatch: FunctionArgKindMismatchError { @@ -1351,7 +1371,7 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>("echo ( 10 );"), + FilterParser::new(&SCHEME).lex_as::("echo ( 10 );"), LexErrorKind::InvalidArgumentKind { index: 0, mismatch: FunctionArgKindMismatchError { @@ -1363,7 +1383,7 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>("echo ( ip.addr );"), + FilterParser::new(&SCHEME).lex_as::("echo ( ip.addr );"), LexErrorKind::InvalidArgumentType { index: 0, mismatch: TypeMismatchError { @@ -1376,7 +1396,7 @@ mod tests { assert_err!( FilterParser::new(&SCHEME) - .lex_as::>("echo ( http.host, 10, 2, \"test\" );"), + .lex_as::("echo ( http.host, 10, 2, \"test\" );"), LexErrorKind::InvalidArgumentsCount { expected_min: 1, expected_max: Some(3), @@ -1385,20 +1405,19 @@ mod tests { ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>("echo ( http.test );"), + FilterParser::new(&SCHEME).lex_as::("echo ( http.test );"), LexErrorKind::UnknownIdentifier, "http.test" ); assert_err!( - FilterParser::new(&SCHEME) - .lex_as::>("echo ( echo ( http.test ) );"), + FilterParser::new(&SCHEME).lex_as::("echo ( echo ( http.test ) );"), LexErrorKind::UnknownIdentifier, "http.test" ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>("echo ( http.host[*] );"), + FilterParser::new(&SCHEME).lex_as::("echo ( http.host[*] );"), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Bytes, @@ -1408,7 +1427,7 @@ mod tests { assert_err!( FilterParser::new(&SCHEME) - .lex_as::>("echo ( http.request.headers.names[0][*] );"), + .lex_as::("echo ( http.request.headers.names[0][*] );"), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Bytes, @@ -1418,7 +1437,7 @@ mod tests { assert_err!( FilterParser::new(&SCHEME) - .lex_as::>("echo ( http.request.headers.names[*][0] );"), + .lex_as::("echo ( http.request.headers.names[*][0] );"), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::ArrayIndex(0), actual: Type::Bytes, @@ -1428,7 +1447,7 @@ mod tests { assert_err!( FilterParser::new(&SCHEME) - .lex_as::>("echo ( http.headers[*][\"host\"] );"), + .lex_as::("echo ( http.headers[*][\"host\"] );"), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapKey("host".to_string()), actual: Type::Bytes, @@ -1438,7 +1457,7 @@ mod tests { assert_err!( FilterParser::new(&SCHEME) - .lex_as::>("echo ( http.host, http.headers[*] );"), + .lex_as::("echo ( http.host, http.headers[*] );"), LexErrorKind::InvalidMapEachAccess, "http.headers[*]" ); diff --git a/engine/src/ast/index_expr.rs b/engine/src/ast/index_expr.rs index cbf64fc8..0e2a8e84 100644 --- a/engine/src/ast/index_expr.rs +++ b/engine/src/ast/index_expr.rs @@ -24,9 +24,9 @@ use serde::{ser::SerializeSeq, Serialize, Serializer}; /// `http.request.headers["Cookie"][0]` would have an IdentifierExpr /// of `http.request.headers` and indexes `["Cookie", 0]`. #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct IndexExpr<'s> { +pub struct IndexExpr { /// The accessed identifier. - pub identifier: IdentifierExpr<'s>, + pub identifier: IdentifierExpr, /// The list of indexes access. pub indexes: Vec, } @@ -72,9 +72,9 @@ where }) } -impl<'s> ValueExpr<'s> for IndexExpr<'s> { +impl ValueExpr for IndexExpr { #[inline] - fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V) { + fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { match self.identifier { IdentifierExpr::Field(ref field) => visitor.visit_field(field), IdentifierExpr::FunctionCallExpr(ref call) => visitor.visit_function_call_expr(call), @@ -82,7 +82,7 @@ impl<'s> ValueExpr<'s> for IndexExpr<'s> { } #[inline] - fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V) { + fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V) { match self.identifier { IdentifierExpr::Field(ref field) => visitor.visit_field(field), IdentifierExpr::FunctionCallExpr(ref mut call) => { @@ -91,10 +91,7 @@ impl<'s> ValueExpr<'s> for IndexExpr<'s> { } } - fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> CompiledValueExpr<'s, C::U> { + fn compile_with_compiler(self, compiler: &mut C) -> CompiledValueExpr { let mut ty = self.get_type(); let map_each_count = self.map_each_count(); let Self { @@ -113,9 +110,9 @@ impl<'s> ValueExpr<'s> for IndexExpr<'s> { if last == Some(0) { // Fast path match identifier { - IdentifierExpr::Field(f) => { - CompiledValueExpr::new(move |ctx| Ok(ctx.get_field_value_unchecked(f).as_ref())) - } + IdentifierExpr::Field(f) => CompiledValueExpr::new(move |ctx| { + Ok(ctx.get_field_value_unchecked(&f).as_ref()) + }), IdentifierExpr::FunctionCallExpr(call) => compiler.compile_function_call_expr(call), } } else if let Some(last) = last { @@ -124,7 +121,7 @@ impl<'s> ValueExpr<'s> for IndexExpr<'s> { IdentifierExpr::Field(f) => CompiledValueExpr::new(move |ctx| { indexes[..last] .iter() - .try_fold(ctx.get_field_value_unchecked(f), |value, index| { + .try_fold(ctx.get_field_value_unchecked(&f), |value, index| { value.get(index).unwrap() }) .map(LhsValue::as_ref) @@ -148,7 +145,7 @@ impl<'s> ValueExpr<'s> for IndexExpr<'s> { match identifier { IdentifierExpr::Field(f) => CompiledValueExpr::new(move |ctx| { let mut iter = MapEachIterator::from_indexes(&indexes[..]); - iter.reset(ctx.get_field_value_unchecked(f).as_ref()); + iter.reset(ctx.get_field_value_unchecked(&f).as_ref()); Ok(LhsValue::Array(Array::try_from_iter(ty, iter).unwrap())) }), IdentifierExpr::FunctionCallExpr(call) => { @@ -171,15 +168,15 @@ fn simplify_indexes(mut indexes: Vec) -> Box<[FieldIndex]> { indexes.into_boxed_slice() } -impl<'s> IndexExpr<'s> { - fn compile_one_with + 's>( +impl IndexExpr { + fn compile_one_with( self, compiler: &mut C, default: bool, func: F, - ) -> CompiledOneExpr<'s, C::U> + ) -> CompiledOneExpr where - F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 's, + F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 'static, { let Self { identifier, @@ -208,12 +205,12 @@ impl<'s> IndexExpr<'s> { } IdentifierExpr::Field(f) => { if indexes.is_empty() { - CompiledOneExpr::new(move |ctx| func(ctx.get_field_value_unchecked(f), ctx)) + CompiledOneExpr::new(move |ctx| func(ctx.get_field_value_unchecked(&f), ctx)) } else { CompiledOneExpr::new(move |ctx| { index_access_one( &indexes, - Some(ctx.get_field_value_unchecked(f)), + Some(ctx.get_field_value_unchecked(&f)), default, ctx, #[inline] @@ -225,13 +222,13 @@ impl<'s> IndexExpr<'s> { } } - pub(crate) fn compile_vec_with + 's>( + pub(crate) fn compile_vec_with( self, compiler: &mut C, func: F, - ) -> CompiledVecExpr<'s, C::U> + ) -> CompiledVecExpr where - F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 's, + F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 'static, { let Self { identifier, @@ -254,7 +251,7 @@ impl<'s> IndexExpr<'s> { IdentifierExpr::Field(f) => CompiledVecExpr::new(move |ctx| { index_access_vec( &indexes, - Some(ctx.get_field_value_unchecked(f)), + Some(ctx.get_field_value_unchecked(&f)), ctx, #[inline] |val, ctx| func(val, ctx), @@ -263,13 +260,13 @@ impl<'s> IndexExpr<'s> { } } - pub(crate) fn compile_iter_with + 's>( + pub(crate) fn compile_iter_with( self, compiler: &mut C, func: F, - ) -> CompiledVecExpr<'s, C::U> + ) -> CompiledVecExpr where - F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 's, + F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 'static, { let Self { identifier, @@ -278,7 +275,7 @@ impl<'s> IndexExpr<'s> { match identifier { IdentifierExpr::Field(f) => CompiledVecExpr::new(move |ctx| { let mut iter = MapEachIterator::from_indexes(&indexes[..]); - iter.reset(ctx.get_field_value_unchecked(f).as_ref()); + iter.reset(ctx.get_field_value_unchecked(&f).as_ref()); TypedArray::from_iter(iter.map(|item| func(&item, ctx))) }), IdentifierExpr::FunctionCallExpr(call) => { @@ -299,14 +296,14 @@ impl<'s> IndexExpr<'s> { /// Compiles an [`IndexExpr`] node into a [`CompiledExpr`] (boxed closure) using the /// provided comparison function that returns a boolean. - pub fn compile_with + 's>( + pub fn compile_with( self, compiler: &mut C, default: bool, func: F, - ) -> CompiledExpr<'s, C::U> + ) -> CompiledExpr where - F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 's, + F: Fn(&LhsValue<'_>, &ExecutionContext<'_, C::U>) -> bool + Sync + Send + 'static, { match self.map_each_count() { 0 => CompiledExpr::One(self.compile_one_with(compiler, default, func)), @@ -325,7 +322,7 @@ impl<'s> IndexExpr<'s> { } /// Returns the associated identifier (field or function call). - pub fn identifier(&self) -> &IdentifierExpr<'s> { + pub fn identifier(&self) -> &IdentifierExpr { &self.identifier } @@ -335,7 +332,7 @@ impl<'s> IndexExpr<'s> { } } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for IndexExpr<'s> { +impl<'i, 's> LexWith<'i, &FilterParser<'s>> for IndexExpr { fn lex_with(mut input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { let (identifier, rest) = IdentifierExpr::lex_with(input, parser)?; @@ -417,7 +414,7 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for IndexExpr<'s> { } } -impl GetType for IndexExpr<'_> { +impl GetType for IndexExpr { fn get_type(&self) -> Type { let mut ty = self.identifier.get_type(); for index in &self.indexes { @@ -433,7 +430,7 @@ impl GetType for IndexExpr<'_> { } } -impl Serialize for IndexExpr<'_> { +impl Serialize for IndexExpr { fn serialize(&self, ser: S) -> Result { if self.indexes.is_empty() { self.identifier.serialize(ser) @@ -622,7 +619,7 @@ mod tests { assert_ok!( FilterParser::new(&SCHEME).lex_as(&filter), IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("test").unwrap().to_owned()), indexes: vec![FieldIndex::ArrayIndex(i)], } ); @@ -636,7 +633,7 @@ mod tests { run(99999); assert_err!( - FilterParser::new(&SCHEME).lex_as::>("test[-1]"), + FilterParser::new(&SCHEME).lex_as::("test[-1]"), LexErrorKind::ExpectedLiteral("expected positive integer as index"), "-1]" ); @@ -647,7 +644,7 @@ mod tests { assert_ok!( FilterParser::new(&SCHEME).lex_as(r#"map["a"]"#), IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("map").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("map").unwrap().to_owned()), indexes: vec![FieldIndex::MapKey("a".to_string())], } ); @@ -655,7 +652,7 @@ mod tests { assert_ok!( FilterParser::new(&SCHEME).lex_as(r#"map["😍"]"#), IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("map").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("map").unwrap().to_owned()), indexes: vec![FieldIndex::MapKey("😍".to_string())], } ); @@ -664,13 +661,13 @@ mod tests { #[test] fn test_access_with_non_string() { assert_err!( - FilterParser::new(&SCHEME).lex_as::>(r#"test[a]"#), + FilterParser::new(&SCHEME).lex_as::(r#"test[a]"#), LexErrorKind::ExpectedLiteral("expected quoted utf8 string or positive integer"), "a]" ); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(r#"map[a]"#), + FilterParser::new(&SCHEME).lex_as::(r#"map[a]"#), LexErrorKind::ExpectedLiteral("expected quoted utf8 string or positive integer"), "a]" ); @@ -682,9 +679,11 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"array(test[0])[0]"#), IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("array").unwrap(), + function: SCHEME.get_function("array").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("test").unwrap().to_owned() + ), indexes: vec![FieldIndex::ArrayIndex(0)], })], context: None @@ -710,9 +709,11 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"array(test[0])[*]"#), IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("array").unwrap(), + function: SCHEME.get_function("array").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("test").unwrap().to_owned() + ), indexes: vec![FieldIndex::ArrayIndex(0)], })], context: None @@ -741,9 +742,11 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"array2(test[0])[*][*]"#), IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("array2").unwrap(), + function: SCHEME.get_function("array2").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("test").unwrap().to_owned() + ), indexes: vec![FieldIndex::ArrayIndex(0)], })], context: None @@ -775,9 +778,11 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"array2(test[0])[*][0]"#), IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("array2").unwrap(), + function: SCHEME.get_function("array2").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("test").unwrap().to_owned() + ), indexes: vec![FieldIndex::ArrayIndex(0)], })], context: None @@ -809,9 +814,11 @@ mod tests { FilterParser::new(&SCHEME).lex_as(r#"array2(test[0])[0][*]"#), IndexExpr { identifier: IdentifierExpr::FunctionCallExpr(FunctionCallExpr { - function: SCHEME.get_function("array2").unwrap(), + function: SCHEME.get_function("array2").unwrap().to_owned(), args: vec![FunctionCallArgExpr::IndexExpr(IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test").unwrap()), + identifier: IdentifierExpr::Field( + SCHEME.get_field("test").unwrap().to_owned() + ), indexes: vec![FieldIndex::ArrayIndex(0)], })], context: None @@ -847,7 +854,7 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as(&filter), IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test2").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("test2").unwrap().to_owned()), indexes: vec![FieldIndex::ArrayIndex(0), FieldIndex::MapEach], } ); @@ -860,7 +867,7 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as(&filter), IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test2").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("test2").unwrap().to_owned()), indexes: vec![FieldIndex::MapEach, FieldIndex::ArrayIndex(0)], } ); @@ -873,7 +880,7 @@ mod tests { let expr = assert_ok!( FilterParser::new(&SCHEME).lex_as(&filter), IndexExpr { - identifier: IdentifierExpr::Field(SCHEME.get_field("test2").unwrap()), + identifier: IdentifierExpr::Field(SCHEME.get_field("test2").unwrap().to_owned()), indexes: vec![FieldIndex::MapEach, FieldIndex::MapEach], } ); @@ -884,7 +891,7 @@ mod tests { let filter = "test2[0][*][*]".to_string(); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(&filter), + FilterParser::new(&SCHEME).lex_as::(&filter), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Bytes @@ -895,7 +902,7 @@ mod tests { let filter = "test2[*][0][*]".to_string(); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(&filter), + FilterParser::new(&SCHEME).lex_as::(&filter), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Bytes @@ -906,7 +913,7 @@ mod tests { let filter = "test2[*][*][0]".to_string(); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(&filter), + FilterParser::new(&SCHEME).lex_as::(&filter), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::ArrayIndex(0), actual: Type::Bytes @@ -917,7 +924,7 @@ mod tests { let filter = "test2[*][*][*]".to_string(); assert_err!( - FilterParser::new(&SCHEME).lex_as::>(&filter), + FilterParser::new(&SCHEME).lex_as::(&filter), LexErrorKind::InvalidIndexAccess(IndexAccessError { index: FieldIndex::MapEach, actual: Type::Bytes diff --git a/engine/src/ast/logical_expr.rs b/engine/src/ast/logical_expr.rs index d03daf5f..73a1f9f4 100644 --- a/engine/src/ast/logical_expr.rs +++ b/engine/src/ast/logical_expr.rs @@ -36,37 +36,37 @@ lex_enum!( /// A parenthesized expression. #[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize)] #[serde(transparent)] -pub struct ParenthesizedExpr<'s> { +pub struct ParenthesizedExpr { /// The inner expression. - pub expr: LogicalExpr<'s>, + pub expr: LogicalExpr, } /// LogicalExpr is a either a generic sub-expression /// or a logical conjunction expression. #[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize)] #[serde(untagged)] -pub enum LogicalExpr<'s> { +pub enum LogicalExpr { /// Logical conjunction expression Combining { /// Logical operator op: LogicalOp, /// List of sub-expressions - items: Vec>, + items: Vec, }, /// A comparison expression. - Comparison(ComparisonExpr<'s>), + Comparison(ComparisonExpr), /// A parenthesized expression. - Parenthesized(Box>), + Parenthesized(Box), /// A unary expression. Unary { /// Unary operator. op: UnaryOp, /// Sub-expression. - arg: Box>, + arg: Box, }, } -impl GetType for LogicalExpr<'_> { +impl GetType for LogicalExpr { fn get_type(&self) -> Type { match &self { LogicalExpr::Combining { ref items, .. } => items[0].get_type(), @@ -77,7 +77,7 @@ impl GetType for LogicalExpr<'_> { } } -impl<'s> LogicalExpr<'s> { +impl LogicalExpr { fn lex_combining_op(input: &str) -> (Option, &str) { match LogicalOp::lex(skip_space(input)) { Ok((op, input)) => (Some(op), skip_space(input)), @@ -85,7 +85,7 @@ impl<'s> LogicalExpr<'s> { } } - fn lex_simple_expr<'i>(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { + fn lex_simple_expr<'i>(input: &'i str, parser: &FilterParser<'_>) -> LexResult<'i, Self> { Ok(if let Ok(input) = expect(input, "(") { let input = skip_space(input); let (expr, input) = LogicalExpr::lex_with(input, parser)?; @@ -113,7 +113,7 @@ impl<'s> LogicalExpr<'s> { fn lex_more_with_precedence<'i>( self, - parser: &FilterParser<'s>, + parser: &FilterParser<'_>, min_prec: Option, mut lookahead: (Option, &'i str), ) -> LexResult<'i, Self> { @@ -177,7 +177,7 @@ impl<'s> LogicalExpr<'s> { } } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for LogicalExpr<'s> { +impl<'i, 's> LexWith<'i, &FilterParser<'s>> for LogicalExpr { fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { let (lhs, input) = Self::lex_simple_expr(input, parser)?; let lookahead = Self::lex_combining_op(input); @@ -185,9 +185,9 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for LogicalExpr<'s> { } } -impl<'s> Expr<'s> for LogicalExpr<'s> { +impl Expr for LogicalExpr { #[inline] - fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V) { + fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { match self { LogicalExpr::Comparison(node) => visitor.visit_comparison_expr(node), LogicalExpr::Parenthesized(node) => visitor.visit_logical_expr(&node.expr), @@ -201,7 +201,7 @@ impl<'s> Expr<'s> for LogicalExpr<'s> { } #[inline] - fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V) { + fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V) { match self { LogicalExpr::Comparison(node) => visitor.visit_comparison_expr(node), LogicalExpr::Parenthesized(node) => visitor.visit_logical_expr(&mut node.expr), @@ -214,10 +214,7 @@ impl<'s> Expr<'s> for LogicalExpr<'s> { } } - fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> CompiledExpr<'s, C::U> { + fn compile_with_compiler(self, compiler: &mut C) -> CompiledExpr { match self { LogicalExpr::Comparison(op) => compiler.compile_comparison_expr(op), LogicalExpr::Parenthesized(node) => compiler.compile_logical_expr(node.expr), @@ -603,7 +600,7 @@ fn test() { { assert_err!( - FilterParser::new(scheme).lex_as::>("t and af"), + FilterParser::new(scheme).lex_as::("t and af"), LexErrorKind::TypeMismatch(TypeMismatchError { expected: Type::Bool.into(), actual: Type::Array(Type::Bool.into()), @@ -612,7 +609,7 @@ fn test() { ); assert_err!( - FilterParser::new(scheme).lex_as::>("at and f"), + FilterParser::new(scheme).lex_as::("at and f"), LexErrorKind::TypeMismatch(TypeMismatchError { expected: Type::Array(Type::Bool.into()).into(), actual: Type::Bool, @@ -623,7 +620,7 @@ fn test() { { assert_err!( - FilterParser::new(scheme).lex_as::>("t or af"), + FilterParser::new(scheme).lex_as::("t or af"), LexErrorKind::TypeMismatch(TypeMismatchError { expected: Type::Bool.into(), actual: Type::Array(Type::Bool.into()), @@ -632,7 +629,7 @@ fn test() { ); assert_err!( - FilterParser::new(scheme).lex_as::>("at or f"), + FilterParser::new(scheme).lex_as::("at or f"), LexErrorKind::TypeMismatch(TypeMismatchError { expected: Type::Array(Type::Bool.into()).into(), actual: Type::Bool, @@ -643,7 +640,7 @@ fn test() { { assert_err!( - FilterParser::new(scheme).lex_as::>("t xor af"), + FilterParser::new(scheme).lex_as::("t xor af"), LexErrorKind::TypeMismatch(TypeMismatchError { expected: Type::Bool.into(), actual: Type::Array(Type::Bool.into()), @@ -652,7 +649,7 @@ fn test() { ); assert_err!( - FilterParser::new(scheme).lex_as::>("at xor f"), + FilterParser::new(scheme).lex_as::("at xor f"), LexErrorKind::TypeMismatch(TypeMismatchError { expected: Type::Array(Type::Bool.into()).into(), actual: Type::Bool, @@ -702,7 +699,7 @@ fn test() { FilterParser::new(scheme).lex_as("at[*]"), LogicalExpr::Comparison(ComparisonExpr { lhs: IndexExpr { - identifier: IdentifierExpr::Field(scheme.get_field("at").unwrap()), + identifier: IdentifierExpr::Field(scheme.get_field("at").unwrap().to_owned()), indexes: vec![FieldIndex::MapEach], }, op: ComparisonOpExpr::IsTrue @@ -726,7 +723,7 @@ fn test() { { assert_err!( - FilterParser::new(scheme).lex_as::>("aat[*]"), + FilterParser::new(scheme).lex_as::("aat[*]"), LexErrorKind::UnsupportedOp { lhs_type: Type::Array(Type::Array(Type::Bool.into()).into()) }, diff --git a/engine/src/ast/mod.rs b/engine/src/ast/mod.rs index 361d0cae..66323bb3 100644 --- a/engine/src/ast/mod.rs +++ b/engine/src/ast/mod.rs @@ -20,40 +20,34 @@ use std::fmt::{self, Debug}; use visitor::{UsesListVisitor, UsesVisitor, Visitor, VisitorMut}; /// Trait used to represent node that evaluates to a [`bool`] (or a [`Vec`]). -pub trait Expr<'s>: - Sized + Eq + Debug + for<'i, 'p> LexWith<'i, &'p FilterParser<'s>> + Serialize +pub trait Expr: + Sized + Eq + Debug + for<'i, 'p, 's> LexWith<'i, &'p FilterParser<'s>> + Serialize { /// Recursively visit all nodes in the AST using a [`Visitor`]. - fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V); + fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V); /// Recursively visit all nodes in the AST using a [`VisitorMut`]. - fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V); + fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V); /// Compiles current node into a [`CompiledExpr`] using [`Compiler`]. - fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> CompiledExpr<'s, C::U>; + fn compile_with_compiler(self, compiler: &mut C) -> CompiledExpr; /// Compiles current node into a [`CompiledExpr`] using [`DefaultCompiler`]. - fn compile(self) -> CompiledExpr<'s> { + fn compile(self) -> CompiledExpr { let mut compiler = DefaultCompiler::new(); self.compile_with_compiler(&mut compiler) } } /// Trait used to represent node that evaluates to an [`crate::LhsValue`]. -pub trait ValueExpr<'s>: - Sized + Eq + Debug + for<'i, 'p> LexWith<'i, &'p FilterParser<'s>> + Serialize +pub trait ValueExpr: + Sized + Eq + Debug + for<'i, 'p, 's> LexWith<'i, &'p FilterParser<'s>> + Serialize { /// Recursively visit all nodes in the AST using a [`Visitor`]. - fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V); + fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V); /// Recursively visit all nodes in the AST using a [`VisitorMut`]. - fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V); + fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V); /// Compiles current node into a [`CompiledValueExpr`] using [`Compiler`]. - fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> CompiledValueExpr<'s, C::U>; + fn compile_with_compiler(self, compiler: &mut C) -> CompiledValueExpr; /// Compiles current node into a [`CompiledValueExpr`] using [`DefaultCompiler`]. - fn compile(self) -> CompiledValueExpr<'s> { + fn compile(self) -> CompiledValueExpr { let mut compiler = DefaultCompiler::new(); self.compile_with_compiler(&mut compiler) } @@ -66,20 +60,20 @@ pub trait ValueExpr<'s>: /// [`crate::ExecutionContext`] is created from the same scheme. #[derive(PartialEq, Eq, Serialize, Clone, Hash)] #[serde(transparent)] -pub struct FilterAst<'s> { +pub struct FilterAst { #[serde(skip)] - scheme: &'s Scheme, + scheme: Scheme, - op: LogicalExpr<'s>, + op: LogicalExpr, } -impl Debug for FilterAst<'_> { +impl Debug for FilterAst { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.op.fmt(f) } } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterAst<'s> { +impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterAst { fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { let (op, input) = LogicalExpr::lex_with(input, parser)?; // LogicalExpr::lex_with can return an AST where the root is an @@ -96,7 +90,7 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterAst<'s> { match ty { Type::Bool => Ok(( FilterAst { - scheme: parser.scheme, + scheme: parser.scheme.clone(), op, }, input, @@ -112,28 +106,28 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterAst<'s> { } } -impl<'s> FilterAst<'s> { +impl FilterAst { /// Returns the associated scheme. #[inline] - pub fn scheme(&self) -> &'s Scheme { - self.scheme + pub fn scheme(&self) -> &Scheme { + &self.scheme } /// Returns the associated expression. #[inline] - pub fn expression(&self) -> &LogicalExpr<'s> { + pub fn expression(&self) -> &LogicalExpr { &self.op } /// Recursively visit all nodes in the AST using a [`Visitor`]. #[inline] - pub fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V) { + pub fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { visitor.visit_logical_expr(&self.op) } /// Recursively visit all nodes in the AST using a [`VisitorMut`]. #[inline] - pub fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V) { + pub fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V) { visitor.visit_logical_expr(&mut self.op) } @@ -158,7 +152,7 @@ impl<'s> FilterAst<'s> { } /// Compiles a [`FilterAst`] into a [`Filter`] using a specific [`Compiler`]. - pub fn compile_with_compiler + 's>(self, compiler: &mut C) -> Filter<'s, C::U> { + pub fn compile_with_compiler(self, compiler: &mut C) -> Filter { match compiler.compile_logical_expr(self.op) { CompiledExpr::One(one) => Filter::new(one, self.scheme), CompiledExpr::Vec(_) => unreachable!(), @@ -166,7 +160,7 @@ impl<'s> FilterAst<'s> { } /// Compiles a [`FilterAst`] into a [`Filter`] using the [`DefaultCompiler`]. - pub fn compile(self) -> Filter<'s> { + pub fn compile(self) -> Filter { let mut compiler = DefaultCompiler::new(); self.compile_with_compiler(&mut compiler) } @@ -179,20 +173,20 @@ impl<'s> FilterAst<'s> { /// [`crate::ExecutionContext`] is created from the same scheme. #[derive(PartialEq, Eq, Serialize, Clone, Hash)] #[serde(transparent)] -pub struct FilterValueAst<'s> { +pub struct FilterValueAst { #[serde(skip)] - scheme: &'s Scheme, + scheme: Scheme, - op: IndexExpr<'s>, + op: IndexExpr, } -impl Debug for FilterValueAst<'_> { +impl Debug for FilterValueAst { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.op.fmt(f) } } -impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterValueAst<'s> { +impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterValueAst { fn lex_with(input: &'i str, parser: &FilterParser<'s>) -> LexResult<'i, Self> { let (op, rest) = IndexExpr::lex_with(input.trim(), parser)?; if op.map_each_count() > 0 { @@ -206,7 +200,7 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterValueAst<'s> { } else { Ok(( FilterValueAst { - scheme: parser.scheme(), + scheme: parser.scheme().clone(), op, }, rest, @@ -215,28 +209,28 @@ impl<'i, 's> LexWith<'i, &FilterParser<'s>> for FilterValueAst<'s> { } } -impl<'s> FilterValueAst<'s> { +impl FilterValueAst { /// Returns the associated scheme. #[inline] - pub fn scheme(&self) -> &'s Scheme { - self.scheme + pub fn scheme(&self) -> &Scheme { + &self.scheme } /// Returns the associated expression. #[inline] - pub fn expression(&self) -> &IndexExpr<'s> { + pub fn expression(&self) -> &IndexExpr { &self.op } /// Recursively visit all nodes in the AST using a [`Visitor`]. #[inline] - pub fn walk<'a, V: Visitor<'s, 'a>>(&'a self, visitor: &mut V) { + pub fn walk<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { visitor.visit_index_expr(&self.op) } /// Recursively visit all nodes in the AST using a [`VisitorMut`]. #[inline] - pub fn walk_mut<'a, V: VisitorMut<'s, 'a>>(&'a mut self, visitor: &mut V) { + pub fn walk_mut<'a, V: VisitorMut<'a>>(&'a mut self, visitor: &mut V) { visitor.visit_index_expr(&mut self.op) } @@ -261,21 +255,18 @@ impl<'s> FilterValueAst<'s> { } /// Compiles a [`FilterValueAst`] into a [`FilterValue`] using a specific [`Compiler`]. - pub fn compile_with_compiler + 's>( - self, - compiler: &mut C, - ) -> FilterValue<'s, C::U> { + pub fn compile_with_compiler(self, compiler: &mut C) -> FilterValue { FilterValue::new(compiler.compile_index_expr(self.op), self.scheme) } /// Compiles a [`FilterValueAst`] into a [`FilterValue`] using the [`DefaultCompiler`]. - pub fn compile(self) -> FilterValue<'s> { + pub fn compile(self) -> FilterValue { let mut compiler = DefaultCompiler::new(); self.compile_with_compiler(&mut compiler) } } -impl GetType for FilterValueAst<'_> { +impl GetType for FilterValueAst { #[inline] fn get_type(&self) -> Type { self.op.get_type() diff --git a/engine/src/ast/parse.rs b/engine/src/ast/parse.rs index 42060461..fb984183 100644 --- a/engine/src/ast/parse.rs +++ b/engine/src/ast/parse.rs @@ -161,12 +161,12 @@ impl<'s> FilterParser<'s> { } /// Parses a filter expression into an AST form. - pub fn parse<'i>(&self, input: &'i str) -> Result, ParseError<'i>> { + pub fn parse<'i>(&self, input: &'i str) -> Result> { complete(self.lex_as(input.trim())).map_err(|err| ParseError::new(input, err)) } /// Parses a value expression into an AST form. - pub fn parse_value<'i>(&self, input: &'i str) -> Result, ParseError<'i>> { + pub fn parse_value<'i>(&self, input: &'i str) -> Result> { complete(self.lex_as(input.trim())).map_err(|err| ParseError::new(input, err)) } diff --git a/engine/src/ast/visitor.rs b/engine/src/ast/visitor.rs index b3f84cb4..22b05f91 100644 --- a/engine/src/ast/visitor.rs +++ b/engine/src/ast/visitor.rs @@ -5,27 +5,27 @@ use super::{ logical_expr::LogicalExpr, Expr, ValueExpr, }; -use crate::scheme::{Field, Function}; +use crate::{Field, FieldRef, Function}; /// Trait used to immutably visit all nodes in the AST. -pub trait Visitor<'s, 'a>: Sized { +pub trait Visitor<'a>: Sized { // `Expr` node visitor methods /// Visit [`Expr`] node. #[inline] - fn visit_expr(&mut self, node: &'a impl Expr<'s>) { + fn visit_expr(&mut self, node: &'a impl Expr) { node.walk(self) } /// Visit [`LogicalExpr`] node. #[inline] - fn visit_logical_expr(&mut self, node: &'a LogicalExpr<'s>) { + fn visit_logical_expr(&mut self, node: &'a LogicalExpr) { self.visit_expr(node) } /// Visit [`ComparisonExpr`] node. #[inline] - fn visit_comparison_expr(&mut self, node: &'a ComparisonExpr<'s>) { + fn visit_comparison_expr(&mut self, node: &'a ComparisonExpr) { self.visit_expr(node) } @@ -33,25 +33,25 @@ pub trait Visitor<'s, 'a>: Sized { /// Visit [`ValueExpr`] node. #[inline] - fn visit_value_expr(&mut self, node: &'a impl ValueExpr<'s>) { + fn visit_value_expr(&mut self, node: &'a impl ValueExpr) { node.walk(self) } /// Visit [`IndexExpr`] node. #[inline] - fn visit_index_expr(&mut self, node: &'a IndexExpr<'s>) { + fn visit_index_expr(&mut self, node: &'a IndexExpr) { self.visit_value_expr(node) } /// Visit [`FunctionCallExpr`] node. #[inline] - fn visit_function_call_expr(&mut self, node: &'a FunctionCallExpr<'s>) { + fn visit_function_call_expr(&mut self, node: &'a FunctionCallExpr) { self.visit_value_expr(node) } /// Visit [`FunctionCallArgExpr`] node. #[inline] - fn visit_function_call_arg_expr(&mut self, node: &'a FunctionCallArgExpr<'s>) { + fn visit_function_call_arg_expr(&mut self, node: &'a FunctionCallArgExpr) { self.visit_value_expr(node) } @@ -59,11 +59,11 @@ pub trait Visitor<'s, 'a>: Sized { /// Visit [`Field`] node. #[inline] - fn visit_field(&mut self, _: &'a Field<'s>) {} + fn visit_field(&mut self, _: &'a Field) {} /// Visit [`Function`] node. #[inline] - fn visit_function(&mut self, _: &'a Function<'s>) {} + fn visit_function(&mut self, _: &'a Function) {} // TODO: add visitor methods for literals? } @@ -73,24 +73,24 @@ pub trait Visitor<'s, 'a>: Sized { /// Note that this trait is dangerous and any modification /// to the AST should be done with cautions and respect /// some invariants such as keeping type coherency. -pub trait VisitorMut<'s, 'a>: Sized { +pub trait VisitorMut<'a>: Sized { // `Expr` node visitor methods /// Visit [`Expr`] node. #[inline] - fn visit_expr(&mut self, node: &'a mut impl Expr<'s>) { + fn visit_expr(&mut self, node: &'a mut impl Expr) { node.walk_mut(self) } /// Visit [`LogicalExpr`] node. #[inline] - fn visit_logical_expr(&mut self, node: &'a mut LogicalExpr<'s>) { + fn visit_logical_expr(&mut self, node: &'a mut LogicalExpr) { self.visit_expr(node) } /// Visit [`ComparisonExpr`] node. #[inline] - fn visit_comparison_expr(&mut self, node: &'a mut ComparisonExpr<'s>) { + fn visit_comparison_expr(&mut self, node: &'a mut ComparisonExpr) { self.visit_expr(node) } @@ -98,25 +98,25 @@ pub trait VisitorMut<'s, 'a>: Sized { /// Visit [`ValueExpr`] node. #[inline] - fn visit_value_expr(&mut self, node: &'a mut impl ValueExpr<'s>) { + fn visit_value_expr(&mut self, node: &'a mut impl ValueExpr) { node.walk_mut(self) } /// Visit [`IndexExpr`] node. #[inline] - fn visit_index_expr(&mut self, node: &'a mut IndexExpr<'s>) { + fn visit_index_expr(&mut self, node: &'a mut IndexExpr) { self.visit_value_expr(node) } /// Visit [`FunctionCallExpr`] node. #[inline] - fn visit_function_call_expr(&mut self, node: &'a mut FunctionCallExpr<'s>) { + fn visit_function_call_expr(&mut self, node: &'a mut FunctionCallExpr) { self.visit_value_expr(node) } /// Visit [`FunctionCallArgExpr`] node. #[inline] - fn visit_function_call_arg_expr(&mut self, node: &'a mut FunctionCallArgExpr<'s>) { + fn visit_function_call_arg_expr(&mut self, node: &'a mut FunctionCallArgExpr) { self.visit_value_expr(node) } @@ -124,23 +124,23 @@ pub trait VisitorMut<'s, 'a>: Sized { /// Visit [`Field`] node. #[inline] - fn visit_field(&mut self, _: &'a Field<'s>) {} + fn visit_field(&mut self, _: &'a Field) {} /// Visit [`Function`] node. #[inline] - fn visit_function(&mut self, _: &'a Function<'s>) {} + fn visit_function(&mut self, _: &'a Function) {} // TODO: add visitor methods for literals? } /// Recursively check if a [`Field`] is being used. pub(crate) struct UsesVisitor<'s> { - field: Field<'s>, + field: FieldRef<'s>, uses: bool, } impl<'s> UsesVisitor<'s> { - pub fn new(field: Field<'s>) -> Self { + pub fn new(field: FieldRef<'s>) -> Self { Self { field, uses: false } } @@ -149,22 +149,22 @@ impl<'s> UsesVisitor<'s> { } } -impl<'s> Visitor<'s, '_> for UsesVisitor<'s> { - fn visit_expr(&mut self, node: &impl Expr<'s>) { +impl Visitor<'_> for UsesVisitor<'_> { + fn visit_expr(&mut self, node: &impl Expr) { // Stop visiting the AST once we have found one occurence of the field if !self.uses { node.walk(self) } } - fn visit_value_expr(&mut self, node: &impl ValueExpr<'s>) { + fn visit_value_expr(&mut self, node: &impl ValueExpr) { // Stop visiting the AST once we have found one occurence of the field if !self.uses { node.walk(self) } } - fn visit_field(&mut self, f: &Field<'s>) { + fn visit_field(&mut self, f: &Field) { if self.field == *f { self.uses = true; } @@ -173,12 +173,12 @@ impl<'s> Visitor<'s, '_> for UsesVisitor<'s> { /// Recursively check if a [`Field`] is being used in a list comparison. pub(crate) struct UsesListVisitor<'s> { - field: Field<'s>, + field: FieldRef<'s>, uses: bool, } impl<'s> UsesListVisitor<'s> { - pub fn new(field: Field<'s>) -> Self { + pub fn new(field: FieldRef<'s>) -> Self { Self { field, uses: false } } @@ -187,22 +187,22 @@ impl<'s> UsesListVisitor<'s> { } } -impl<'s> Visitor<'s, '_> for UsesListVisitor<'s> { - fn visit_expr(&mut self, node: &impl Expr<'s>) { +impl Visitor<'_> for UsesListVisitor<'_> { + fn visit_expr(&mut self, node: &impl Expr) { // Stop visiting the AST once we have found one occurence of the field if !self.uses { node.walk(self) } } - fn visit_value_expr(&mut self, node: &impl ValueExpr<'s>) { + fn visit_value_expr(&mut self, node: &impl ValueExpr) { // Stop visiting the AST once we have found one occurence of the field if !self.uses { node.walk(self) } } - fn visit_comparison_expr(&mut self, comparison_expr: &ComparisonExpr<'s>) { + fn visit_comparison_expr(&mut self, comparison_expr: &ComparisonExpr) { if let ComparisonOpExpr::InList { .. } = comparison_expr.op { let mut visitor = UsesVisitor::new(self.field); visitor.visit_comparison_expr(comparison_expr); diff --git a/engine/src/compiler.rs b/engine/src/compiler.rs index 7f3f6594..3b01ffad 100644 --- a/engine/src/compiler.rs +++ b/engine/src/compiler.rs @@ -4,40 +4,37 @@ use crate::{ }; /// Trait used to drive the compilation of a [`crate::FilterAst`] into a [`crate::Filter`]. -pub trait Compiler<'s>: Sized + 's { +pub trait Compiler: Sized { /// The user data type passed in the [`crate::ExecutionContext`]. - type U; + type U: 'static; /// Compiles a [`Expr`] node into a [`CompiledExpr`] (boxed closure). #[inline] - fn compile_expr(&mut self, node: impl Expr<'s>) -> CompiledExpr<'s, Self::U> { + fn compile_expr(&mut self, node: impl Expr) -> CompiledExpr { node.compile_with_compiler(self) } /// Compiles a [`LogicalExpr`] node into a [`CompiledExpr`] (boxed closure). #[inline] - fn compile_logical_expr(&mut self, node: LogicalExpr<'s>) -> CompiledExpr<'s, Self::U> { + fn compile_logical_expr(&mut self, node: LogicalExpr) -> CompiledExpr { self.compile_expr(node) } /// Compiles a [`ComparisonExpr`] node into a [`CompiledExpr`] (boxed closure). #[inline] - fn compile_comparison_expr(&mut self, node: ComparisonExpr<'s>) -> CompiledExpr<'s, Self::U> { + fn compile_comparison_expr(&mut self, node: ComparisonExpr) -> CompiledExpr { self.compile_expr(node) } /// Compiles a [`ValueExpr`] node into a [`CompiledValueExpr`] (boxed closure). #[inline] - fn compile_value_expr(&mut self, node: impl ValueExpr<'s>) -> CompiledValueExpr<'s, Self::U> { + fn compile_value_expr(&mut self, node: impl ValueExpr) -> CompiledValueExpr { node.compile_with_compiler(self) } /// Compiles a [`FunctionCallExpr`] node into a [`CompiledValueExpr`] (boxed closure). #[inline] - fn compile_function_call_expr( - &mut self, - node: FunctionCallExpr<'s>, - ) -> CompiledValueExpr<'s, Self::U> { + fn compile_function_call_expr(&mut self, node: FunctionCallExpr) -> CompiledValueExpr { self.compile_value_expr(node) } @@ -45,14 +42,14 @@ pub trait Compiler<'s>: Sized + 's { #[inline] fn compile_function_call_arg_expr( &mut self, - node: FunctionCallArgExpr<'s>, - ) -> CompiledValueExpr<'s, Self::U> { + node: FunctionCallArgExpr, + ) -> CompiledValueExpr { self.compile_value_expr(node) } /// Compiles a [`IndexExpr`] node into a [`CompiledValueExpr`] (boxed closure). #[inline] - fn compile_index_expr(&mut self, node: IndexExpr<'s>) -> CompiledValueExpr<'s, Self::U> { + fn compile_index_expr(&mut self, node: IndexExpr) -> CompiledValueExpr { self.compile_value_expr(node) } } @@ -80,6 +77,6 @@ impl DefaultCompiler { } } -impl<'s, U: 's> Compiler<'s> for DefaultCompiler { +impl Compiler for DefaultCompiler { type U = U; } diff --git a/engine/src/execution_context.rs b/engine/src/execution_context.rs index 62f32cd8..6c75011d 100644 --- a/engine/src/execution_context.rs +++ b/engine/src/execution_context.rs @@ -1,7 +1,7 @@ use crate::{ scheme::{Field, List, Scheme, SchemeMismatchError}, types::{GetType, LhsValue, LhsValueSeed, Type, TypeMismatchError}, - ListMatcher, UnknownFieldError, + FieldRef, ListMatcher, ListRef, UnknownFieldError, }; use serde::de::{self, DeserializeSeed, Deserializer, MapAccess, Visitor}; use serde::ser::{SerializeMap, SerializeSeq, Serializer}; @@ -42,7 +42,7 @@ pub struct InvalidListMatcherError { /// index-based access to values for a filter during execution. #[derive(Debug, PartialEq)] pub struct ExecutionContext<'e, U = ()> { - scheme: &'e Scheme, + scheme: Scheme, values: Box<[Option>]>, list_matchers: Box<[Box]>, user_data: U, @@ -52,7 +52,7 @@ impl<'e, U> ExecutionContext<'e, U> { /// Creates an execution context associated with a given scheme. /// /// This scheme will be used for resolving any field names and indices. - pub fn new<'s: 'e>(scheme: &'s Scheme) -> Self + pub fn new(scheme: &Scheme) -> Self where U: Default, { @@ -62,9 +62,9 @@ impl<'e, U> ExecutionContext<'e, U> { /// Creates an execution context associated with a given scheme. /// /// This scheme will be used for resolving any field names and indices. - pub fn new_with<'s: 'e>(scheme: &'s Scheme, f: impl FnOnce() -> U) -> Self { + pub fn new_with(scheme: &Scheme, f: impl FnOnce() -> U) -> Self { ExecutionContext { - scheme, + scheme: scheme.clone(), values: vec![None; scheme.field_count()].into(), list_matchers: scheme .lists() @@ -75,17 +75,17 @@ impl<'e, U> ExecutionContext<'e, U> { } /// Returns the associated scheme. - pub fn scheme(&self) -> &'e Scheme { - self.scheme + pub fn scheme(&self) -> &Scheme { + &self.scheme } /// Sets a runtime value for a given field name. pub fn set_field_value<'v: 'e, V: Into>>( &mut self, - field: Field<'e>, + field: FieldRef<'_>, value: V, ) -> Result>, SetFieldValueError> { - if !std::ptr::eq(self.scheme, field.scheme()) { + if self.scheme != *field.scheme() { return Err(SetFieldValueError::SchemeMismatch(SchemeMismatchError)); } let value = value.into(); @@ -129,7 +129,7 @@ impl<'e, U> ExecutionContext<'e, U> { } #[inline] - pub(crate) fn get_field_value_unchecked(&self, field: Field<'_>) -> &LhsValue<'_> { + pub(crate) fn get_field_value_unchecked(&self, field: &Field) -> &LhsValue<'_> { // This is safe because this code is reachable only from Filter::execute // which already performs the scheme compatibility check, but check that // invariant holds in the future at least in the debug mode. @@ -147,21 +147,21 @@ impl<'e, U> ExecutionContext<'e, U> { } /// Get the value of a field. - pub fn get_field_value(&self, field: Field<'_>) -> Option<&LhsValue<'_>> { + pub fn get_field_value(&self, field: FieldRef<'_>) -> Option<&LhsValue<'_>> { assert!(self.scheme() == field.scheme()); self.values[field.index()].as_ref() } #[inline] - pub(crate) fn get_list_matcher_unchecked(&self, list: List<'_>) -> &dyn ListMatcher { + pub(crate) fn get_list_matcher_unchecked(&self, list: &List) -> &dyn ListMatcher { debug_assert!(self.scheme() == list.scheme()); &*self.list_matchers[list.index()] } /// Get the list matcher object for the specified list type. - pub fn get_list_matcher(&self, list: List<'_>) -> &dyn ListMatcher { + pub fn get_list_matcher(&self, list: ListRef<'_>) -> &dyn ListMatcher { assert!(self.scheme() == list.scheme()); &*self.list_matchers[list.index()] @@ -174,7 +174,7 @@ impl<'e, U> ExecutionContext<'e, U> { } /// Get the list matcher object for the specified list type. - pub fn get_list_matcher_mut(&mut self, list: List<'_>) -> &mut dyn ListMatcher { + pub fn get_list_matcher_mut(&mut self, list: ListRef<'_>) -> &mut dyn ListMatcher { assert!(self.scheme() == list.scheme()); &mut *self.list_matchers[list.index()] @@ -238,7 +238,7 @@ pub struct ExecutionContextGuard<'a, 'e, U, T> { impl<'a, 'e, U, T> ExecutionContextGuard<'a, 'e, U, T> { fn new(old: &'a mut ExecutionContext<'e, U>, user_data: T) -> Self { - let scheme = old.scheme(); + let scheme = old.scheme().clone(); let values = std::mem::take(&mut old.values); let list_matchers = std::mem::take(&mut old.list_matchers); @@ -385,7 +385,7 @@ impl Serialize for ExecutionContext<'_> { if !self.list_matchers.is_empty() { map.serialize_entry( "$lists", - &ListMatcherSlice(self.scheme, &self.list_matchers), + &ListMatcherSlice(&self.scheme, &self.list_matchers), )?; } map.end() diff --git a/engine/src/filter.rs b/engine/src/filter.rs index 736bf778..7f3c5bee 100644 --- a/engine/src/filter.rs +++ b/engine/src/filter.rs @@ -13,13 +13,13 @@ use crate::{ }; use std::fmt; -type BoxedClosureToOneBool<'s, U> = - Box Fn(&'e ExecutionContext<'e, U>) -> bool + Sync + Send + 's>; +type BoxedClosureToOneBool = + Box Fn(&'e ExecutionContext<'e, U>) -> bool + Sync + Send + 'static>; /// Boxed closure for [`crate::Expr`] AST node that evaluates to a simple [`bool`]. -pub struct CompiledOneExpr<'s, U = ()>(BoxedClosureToOneBool<'s, U>); +pub struct CompiledOneExpr(BoxedClosureToOneBool); -impl fmt::Debug for CompiledOneExpr<'_, U> { +impl fmt::Debug for CompiledOneExpr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("CompiledOneExpr") .field(&((&*self.0) as *const _)) @@ -27,10 +27,10 @@ impl fmt::Debug for CompiledOneExpr<'_, U> { } } -impl<'s, U> CompiledOneExpr<'s, U> { +impl CompiledOneExpr { /// Creates a compiled expression IR from a generic closure. pub fn new( - closure: impl for<'e> Fn(&'e ExecutionContext<'e, U>) -> bool + Sync + Send + 's, + closure: impl for<'e> Fn(&'e ExecutionContext<'e, U>) -> bool + Sync + Send + 'static, ) -> Self { CompiledOneExpr(Box::new(closure)) } @@ -41,20 +41,21 @@ impl<'s, U> CompiledOneExpr<'s, U> { } /// Extracts the underlying boxed closure. - pub fn into_boxed_closure(self) -> BoxedClosureToOneBool<'s, U> { + pub fn into_boxed_closure(self) -> BoxedClosureToOneBool { self.0 } } pub(crate) type CompiledVecExprResult = TypedArray<'static, bool>; -type BoxedClosureToVecBool<'s, U> = - Box Fn(&'e ExecutionContext<'e, U>) -> CompiledVecExprResult + Sync + Send + 's>; +type BoxedClosureToVecBool = Box< + dyn for<'e> Fn(&'e ExecutionContext<'e, U>) -> CompiledVecExprResult + Sync + Send + 'static, +>; /// Boxed closure for [`crate::Expr`] AST node that evaluates to a list of [`bool`]. -pub struct CompiledVecExpr<'s, U = ()>(BoxedClosureToVecBool<'s, U>); +pub struct CompiledVecExpr(BoxedClosureToVecBool); -impl fmt::Debug for CompiledVecExpr<'_, U> { +impl fmt::Debug for CompiledVecExpr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("CompiledVecExpr") .field(&((&*self.0) as *const _)) @@ -62,13 +63,13 @@ impl fmt::Debug for CompiledVecExpr<'_, U> { } } -impl<'s, U> CompiledVecExpr<'s, U> { +impl CompiledVecExpr { /// Creates a compiled expression IR from a generic closure. pub fn new( closure: impl for<'e> Fn(&'e ExecutionContext<'e, U>) -> CompiledVecExprResult + Sync + Send - + 's, + + 'static, ) -> Self { CompiledVecExpr(Box::new(closure)) } @@ -79,21 +80,21 @@ impl<'s, U> CompiledVecExpr<'s, U> { } /// Extracts the underlying boxed closure. - pub fn into_boxed_closure(self) -> BoxedClosureToVecBool<'s, U> { + pub fn into_boxed_closure(self) -> BoxedClosureToVecBool { self.0 } } /// Enum of boxed closure for [`crate::Expr`] AST nodes. #[derive(Debug)] -pub enum CompiledExpr<'s, U = ()> { +pub enum CompiledExpr { /// Variant for [`crate::Expr`] AST node that evaluates to a simple [`bool`]. - One(CompiledOneExpr<'s, U>), + One(CompiledOneExpr), /// Variant for [`crate::Expr`] AST node that evaluates to a list of [`bool`]. - Vec(CompiledVecExpr<'s, U>), + Vec(CompiledVecExpr), } -impl CompiledExpr<'_, U> { +impl CompiledExpr { #[cfg(test)] pub(crate) fn execute_one<'e>(&self, ctx: &'e ExecutionContext<'e, U>) -> bool { match self { @@ -128,13 +129,14 @@ impl From for CompiledValueResult<'_> { } } -type BoxedClosureToValue<'s, U> = - Box Fn(&'e ExecutionContext<'e, U>) -> CompiledValueResult<'e> + Sync + Send + 's>; +type BoxedClosureToValue = Box< + dyn for<'e> Fn(&'e ExecutionContext<'e, U>) -> CompiledValueResult<'e> + Sync + Send + 'static, +>; /// Boxed closure for [`crate::ValueExpr`] AST node that evaluates to an [`LhsValue`]. -pub struct CompiledValueExpr<'s, U = ()>(BoxedClosureToValue<'s, U>); +pub struct CompiledValueExpr(BoxedClosureToValue); -impl fmt::Debug for CompiledValueExpr<'_, U> { +impl fmt::Debug for CompiledValueExpr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("CompiledValueExpr") .field(&((&*self.0) as *const _)) @@ -142,13 +144,13 @@ impl fmt::Debug for CompiledValueExpr<'_, U> { } } -impl<'s, U> CompiledValueExpr<'s, U> { +impl CompiledValueExpr { /// Creates a compiled expression IR from a generic closure. pub fn new( closure: impl for<'e> Fn(&'e ExecutionContext<'e, U>) -> CompiledValueResult<'e> + Sync + Send - + 's, + + 'static, ) -> Self { CompiledValueExpr(Box::new(closure)) } @@ -159,7 +161,7 @@ impl<'s, U> CompiledValueExpr<'s, U> { } /// Extracts the underlying boxed closure. - pub fn into_boxed_closure(self) -> BoxedClosureToValue<'s, U> { + pub fn into_boxed_closure(self) -> BoxedClosureToValue { self.0 } } @@ -179,23 +181,23 @@ impl<'s, U> CompiledValueExpr<'s, U> { /// In the future the underlying representation might change, but for now it /// provides the best trade-off between safety and performance of compilation /// and execution. -pub struct Filter<'s, U = ()> { - root_expr: CompiledOneExpr<'s, U>, - scheme: &'s Scheme, +pub struct Filter { + root_expr: CompiledOneExpr, + scheme: Scheme, } -impl std::fmt::Debug for Filter<'_, U> { +impl std::fmt::Debug for Filter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Filter") .field("root", &self.root_expr) - .field("scheme", &(self.scheme as *const _)) + .field("scheme", &self.scheme) .finish() } } -impl<'s, U> Filter<'s, U> { +impl Filter { /// Creates a compiled expression IR from a generic closure. - pub(crate) fn new(root_expr: CompiledOneExpr<'s, U>, scheme: &'s Scheme) -> Self { + pub(crate) fn new(root_expr: CompiledOneExpr, scheme: Scheme) -> Self { Filter { root_expr, scheme } } @@ -204,7 +206,7 @@ impl<'s, U> Filter<'s, U> { &self, ctx: &'e ExecutionContext<'e, U>, ) -> Result { - if ctx.scheme() == self.scheme { + if ctx.scheme() == &self.scheme { Ok(self.root_expr.execute(ctx)) } else { Err(SchemeMismatchError) @@ -213,14 +215,14 @@ impl<'s, U> Filter<'s, U> { } /// An IR for a compiled value expression. -pub struct FilterValue<'s, U = ()> { - root_expr: CompiledValueExpr<'s, U>, - scheme: &'s Scheme, +pub struct FilterValue { + root_expr: CompiledValueExpr, + scheme: Scheme, } -impl<'s, U> FilterValue<'s, U> { +impl FilterValue { /// Creates a compiled expression IR from a generic closure. - pub(crate) fn new(root_expr: CompiledValueExpr<'s, U>, scheme: &'s Scheme) -> Self { + pub(crate) fn new(root_expr: CompiledValueExpr, scheme: Scheme) -> Self { FilterValue { root_expr, scheme } } @@ -229,7 +231,7 @@ impl<'s, U> FilterValue<'s, U> { &self, ctx: &'e ExecutionContext<'e, U>, ) -> Result, Type>, SchemeMismatchError> { - if ctx.scheme() == self.scheme { + if ctx.scheme() == &self.scheme { Ok(self.root_expr.execute(ctx)) } else { Err(SchemeMismatchError) @@ -257,7 +259,7 @@ mod tests { fn is_send() {} fn is_sync() {} - is_send::>>(); - is_sync::>>(); + is_send::>>(); + is_sync::>>(); } } diff --git a/engine/src/functions/all.rs b/engine/src/functions/all.rs index 1dfc0223..f359e260 100644 --- a/engine/src/functions/all.rs +++ b/engine/src/functions/all.rs @@ -62,7 +62,8 @@ impl FunctionDefinition for AllFunction { &'s self, _: &mut dyn ExactSizeIterator>, _: Option, - ) -> Box Fn(FunctionArgs<'_, 'a>) -> Option> + Sync + Send + 's> { + ) -> Box Fn(FunctionArgs<'i, 'a>) -> Option> + Sync + Send + 'static> + { Box::new(all_impl) } } diff --git a/engine/src/functions/any.rs b/engine/src/functions/any.rs index c1d19885..1d0d5497 100644 --- a/engine/src/functions/any.rs +++ b/engine/src/functions/any.rs @@ -62,7 +62,8 @@ impl FunctionDefinition for AnyFunction { &'s self, _: &mut dyn ExactSizeIterator>, _: Option, - ) -> Box Fn(FunctionArgs<'_, 'a>) -> Option> + Sync + Send + 's> { + ) -> Box Fn(FunctionArgs<'i, 'a>) -> Option> + Sync + Send + 'static> + { Box::new(any_impl) } } diff --git a/engine/src/functions/concat.rs b/engine/src/functions/concat.rs index 4b9ae68f..81aa00b4 100644 --- a/engine/src/functions/concat.rs +++ b/engine/src/functions/concat.rs @@ -81,7 +81,8 @@ impl FunctionDefinition for ConcatFunction { &'s self, _: &mut dyn ExactSizeIterator>, _: Option, - ) -> Box Fn(FunctionArgs<'_, 'a>) -> Option> + Sync + Send + 's> { + ) -> Box Fn(FunctionArgs<'i, 'a>) -> Option> + Sync + Send + 'static> + { Box::new(|args| { while let Some(arg) = args.next() { match arg { diff --git a/engine/src/functions/mod.rs b/engine/src/functions/mod.rs index 3fec62a2..52a62174 100644 --- a/engine/src/functions/mod.rs +++ b/engine/src/functions/mod.rs @@ -396,11 +396,11 @@ pub trait FunctionDefinition: Debug + Send + Sync { fn arg_count(&self) -> (usize, Option); /// Compile the function definition down to a closure that is going to be called /// during filter execution. - fn compile<'s>( - &'s self, + fn compile( + &self, params: &mut dyn ExactSizeIterator>, ctx: Option, - ) -> Box Fn(FunctionArgs<'i, 'a>) -> Option> + Sync + Send + 's>; + ) -> Box Fn(FunctionArgs<'i, 'a>) -> Option> + Sync + Send + 'static>; } /* Simple function APIs */ @@ -505,7 +505,7 @@ impl FunctionDefinition for SimpleFunctionDefinition { &self, params: &mut dyn ExactSizeIterator>, _: Option, - ) -> Box Fn(FunctionArgs<'i, 'a>) -> Option> + Sync + Send + '_> + ) -> Box Fn(FunctionArgs<'i, 'a>) -> Option> + Sync + Send + 'static> { let params_count = params.len(); let opt_params = &self.opt_params[(params_count - self.params.len())..]; diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 91addb40..2171868f 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -115,9 +115,9 @@ pub use self::{ RegexFormat, }, scheme::{ - Field, FieldIndex, FieldRedefinitionError, Function, FunctionRedefinitionError, - IdentifierRedefinitionError, IndexAccessError, List, Scheme, SchemeBuilder, - SchemeMismatchError, UnknownFieldError, + Field, FieldIndex, FieldRedefinitionError, FieldRef, Function, FunctionRedefinitionError, + FunctionRef, IdentifierRedefinitionError, IndexAccessError, List, ListRef, Scheme, + SchemeBuilder, SchemeMismatchError, UnknownFieldError, }, types::{ CompoundType, ExpectedType, ExpectedTypeList, GetType, LhsValue, LhsValueMut, RhsValue, diff --git a/engine/src/scheme.rs b/engine/src/scheme.rs index b8b122ca..3955656c 100644 --- a/engine/src/scheme.rs +++ b/engine/src/scheme.rs @@ -19,7 +19,6 @@ use std::{ fmt::{self, Debug, Formatter}, hash::{Hash, Hasher}, iter::Iterator, - ptr, }; use thiserror::Error; @@ -103,24 +102,24 @@ pub struct IndexAccessError { #[derive(PartialEq, Eq, Clone, Copy, Hash)] /// A structure to represent a field inside a [`Scheme`](struct@Scheme). -pub struct Field<'s> { +pub struct FieldRef<'s> { scheme: &'s Scheme, index: usize, } -impl Serialize for Field<'_> { +impl Serialize for FieldRef<'_> { fn serialize(&self, ser: S) -> Result { self.name().serialize(ser) } } -impl Debug for Field<'_> { +impl Debug for FieldRef<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.name()) } } -impl<'i, 's> LexWith<'i, &'s Scheme> for Field<'s> { +impl<'i, 's> LexWith<'i, &'s Scheme> for FieldRef<'s> { fn lex_with(input: &'i str, scheme: &'s Scheme) -> LexResult<'i, Self> { match Identifier::lex_with(input, scheme) { Ok((Identifier::Field(f), rest)) => Ok((f, rest)), @@ -136,7 +135,7 @@ impl<'i, 's> LexWith<'i, &'s Scheme> for Field<'s> { } } -impl<'s> Field<'s> { +impl<'s> FieldRef<'s> { /// Returns the field's name as recorded in the [`Scheme`](struct@Scheme). #[inline] pub fn name(&self) -> &'s str { @@ -154,35 +153,129 @@ impl<'s> Field<'s> { pub fn scheme(&self) -> &'s Scheme { self.scheme } + + /// Converts to an owned [`Field`]. + #[inline] + pub fn to_owned(&self) -> Field { + Field { + scheme: self.scheme.clone(), + index: self.index, + } + } + + /// Reborrows the field relatively to the specified [`Scheme`] reference. + /// + /// Useful when you have a [`FieldRef`] borrowed from an owned [`Field`] + /// but you need to extend/change it's lifetime. + /// + /// Panics if the field doesn't belong to the specified scheme. + #[inline] + pub fn reborrow(self, scheme: &Scheme) -> FieldRef<'_> { + assert!(self.scheme == scheme); + + FieldRef { + scheme, + index: self.index, + } + } } -impl GetType for Field<'_> { +impl GetType for FieldRef<'_> { #[inline] fn get_type(&self) -> Type { self.scheme.inner.fields[self.index].1 } } +impl PartialEq for FieldRef<'_> { + #[inline] + fn eq(&self, other: &Field) -> bool { + self.eq(&other.as_ref()) + } +} + +#[derive(PartialEq, Eq, Clone, Hash)] +/// A structure to represent a field inside a [`Scheme`](struct@Scheme). +pub struct Field { + scheme: Scheme, + index: usize, +} + +impl Serialize for Field { + fn serialize(&self, ser: S) -> Result { + self.name().serialize(ser) + } +} + +impl Debug for Field { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.name()) + } +} + +impl Field { + /// Returns the field's name as recorded in the [`Scheme`](struct@Scheme). + #[inline] + pub fn name(&self) -> &str { + &self.scheme.inner.fields[self.index].0 + } + + /// Get the field's index in the [`Scheme`](struct@Scheme) identifier's list. + #[inline] + pub fn index(&self) -> usize { + self.index + } + + /// Returns the [`Scheme`](struct@Scheme) to which this field belongs to. + #[inline] + pub fn scheme(&self) -> &Scheme { + &self.scheme + } + + /// Converts to a borrowed [`Field`]. + #[inline] + pub fn as_ref(&self) -> FieldRef<'_> { + FieldRef { + scheme: &self.scheme, + index: self.index, + } + } +} + +impl GetType for Field { + #[inline] + fn get_type(&self) -> Type { + self.scheme.inner.fields[self.index].1 + } +} + +impl PartialEq> for Field { + #[inline] + fn eq(&self, other: &FieldRef<'_>) -> bool { + self.as_ref().eq(other) + } +} + #[derive(PartialEq, Eq, Clone, Copy, Hash)] /// A structure to represent a function inside a [`Scheme`](struct@Scheme). -pub struct Function<'s> { +pub struct FunctionRef<'s> { scheme: &'s Scheme, index: usize, } -impl Serialize for Function<'_> { +impl Serialize for FunctionRef<'_> { fn serialize(&self, ser: S) -> Result { self.name().serialize(ser) } } -impl Debug for Function<'_> { +impl Debug for FunctionRef<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.name()) } } -impl<'i, 's> LexWith<'i, &'s Scheme> for Function<'s> { +impl<'i, 's> LexWith<'i, &'s Scheme> for FunctionRef<'s> { fn lex_with(input: &'i str, scheme: &'s Scheme) -> LexResult<'i, Self> { match Identifier::lex_with(input, scheme) { Ok((Identifier::Function(f), rest)) => Ok((f, rest)), @@ -198,7 +291,7 @@ impl<'i, 's> LexWith<'i, &'s Scheme> for Function<'s> { } } -impl<'s> Function<'s> { +impl<'s> FunctionRef<'s> { /// Returns the function's name as recorded in the [`Scheme`](struct@Scheme). #[inline] pub fn name(&self) -> &'s str { @@ -221,6 +314,98 @@ impl<'s> Function<'s> { pub(crate) fn as_definition(&self) -> &'s dyn FunctionDefinition { &*self.scheme.inner.functions[self.index].1 } + + /// Converts to an owned [`Function`]. + #[inline] + pub fn to_owned(&self) -> Function { + Function { + scheme: self.scheme.clone(), + index: self.index, + } + } + + /// Reborrows the function relatively to the specified [`Scheme`] reference. + /// + /// Useful when you have a [`FunctionRef`] borrowed from an owned [`Function`] + /// but you need to extend/change it's lifetime. + /// + /// Panics if the function doesn't belong to the specified scheme. + #[inline] + pub fn reborrow(self, scheme: &Scheme) -> FunctionRef<'_> { + assert!(self.scheme == scheme); + + FunctionRef { + scheme, + index: self.index, + } + } +} + +impl PartialEq for FunctionRef<'_> { + #[inline] + fn eq(&self, other: &Function) -> bool { + self.eq(&other.as_ref()) + } +} + +#[derive(PartialEq, Eq, Clone, Hash)] +/// A structure to represent a function inside a [`Scheme`](struct@Scheme). +pub struct Function { + scheme: Scheme, + index: usize, +} + +impl Serialize for Function { + fn serialize(&self, ser: S) -> Result { + self.name().serialize(ser) + } +} + +impl Debug for Function { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.name()) + } +} + +impl Function { + /// Returns the function's name as recorded in the [`Scheme`](struct@Scheme). + #[inline] + pub fn name(&self) -> &str { + &self.scheme.inner.functions[self.index].0 + } + + /// Get the function's index in the [`Scheme`](struct@Scheme) identifier's list. + #[inline] + pub fn index(&self) -> usize { + self.index + } + + /// Returns the [`Scheme`](struct@Scheme) to which this function belongs to. + #[inline] + pub fn scheme(&self) -> &Scheme { + &self.scheme + } + + #[inline] + pub(crate) fn as_definition(&self) -> &dyn FunctionDefinition { + &*self.scheme.inner.functions[self.index].1 + } + + /// Converts to a borrowed [`Function`]. + #[inline] + pub fn as_ref(&self) -> FunctionRef<'_> { + FunctionRef { + scheme: &self.scheme, + index: self.index, + } + } +} + +impl PartialEq> for Function { + #[inline] + fn eq(&self, other: &FunctionRef<'_>) -> bool { + self.as_ref().eq(other) + } } /// An enum to represent an entry inside a [`Scheme`](struct@Scheme). @@ -228,9 +413,9 @@ impl<'s> Function<'s> { #[derive(Debug)] pub(crate) enum Identifier<'s> { /// Identifier is a [`Field`](struct@Field) - Field(Field<'s>), + Field(FieldRef<'s>), /// Identifier is a [`Function`](struct@Function) - Function(Function<'s>), + Function(FunctionRef<'s>), } impl<'i, 's> LexWith<'i, &'s Scheme> for Identifier<'s> { @@ -303,12 +488,12 @@ enum SchemeItem { /// /// See [`Scheme::get_list`](struct.Scheme.html#method.get_list). #[derive(PartialEq, Eq, Clone, Copy, Hash)] -pub struct List<'s> { +pub struct ListRef<'s> { scheme: &'s Scheme, index: usize, } -impl<'s> List<'s> { +impl<'s> ListRef<'s> { pub(crate) fn index(&self) -> usize { self.index } @@ -320,21 +505,103 @@ impl<'s> List<'s> { pub(crate) fn definition(&self) -> &'s dyn ListDefinition { &*self.scheme.inner.lists[self.index].1 } + + /// Converts to an owned [`List`]. + #[inline] + pub fn to_owned(&self) -> List { + List { + scheme: self.scheme.clone(), + index: self.index, + } + } + + /// Reborrows the list relatively to the specified [`Scheme`] reference. + /// + /// Useful when you have a [`ListRef`] borrowed from an owned [`List`] + /// but you need to extend/change it's lifetime. + /// + /// Panics if the list doesn't belong to the specified scheme. + #[inline] + pub fn reborrow(self, scheme: &Scheme) -> ListRef<'_> { + assert!(self.scheme == scheme); + + ListRef { + scheme, + index: self.index, + } + } } -impl Debug for List<'_> { +impl Debug for ListRef<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.scheme.inner.lists[self.index]) } } -impl GetType for List<'_> { +impl GetType for ListRef<'_> { #[inline] fn get_type(&self) -> Type { self.scheme.inner.lists[self.index].0 } } +impl PartialEq for ListRef<'_> { + #[inline] + fn eq(&self, other: &List) -> bool { + self.eq(&other.as_ref()) + } +} + +/// A structure to represent a list inside a [`scheme`](struct.Scheme.html). +/// +/// See [`Scheme::get_list`](struct.Scheme.html#method.get_list). +#[derive(PartialEq, Eq, Clone, Hash)] +pub struct List { + scheme: Scheme, + index: usize, +} + +impl List { + #[inline] + pub(crate) fn index(&self) -> usize { + self.index + } + + #[inline] + pub(crate) fn scheme(&self) -> &Scheme { + &self.scheme + } + + /// Converts to a borrowed [`ListRef`]. + #[inline] + pub fn as_ref(&self) -> ListRef<'_> { + ListRef { + scheme: &self.scheme, + index: self.index, + } + } +} + +impl Debug for List { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.scheme.inner.lists[self.index]) + } +} + +impl GetType for List { + #[inline] + fn get_type(&self) -> Type { + self.scheme.inner.lists[self.index].0 + } +} + +impl PartialEq> for List { + #[inline] + fn eq(&self, other: &ListRef<'_>) -> bool { + self.as_ref().eq(other) + } +} + /// An error that occurs when previously defined list gets redefined. #[derive(Debug, PartialEq, Eq, Error)] #[error("attempt to redefine list for type {0:?}")] @@ -427,7 +694,9 @@ impl SchemeBuilder { /// Build a new [`Scheme`] from this builder. pub fn build(self) -> Scheme { - Scheme { inner: self } + Scheme { + inner: Arc::new(self), + } } } @@ -449,14 +718,14 @@ impl> FromIterator<(N, Type)> for SchemeBuilder { /// This is necessary to provide typechecking for runtime values provided /// to the [`crate::ExecutionContext`] and also to aid parser /// in ambiguous contexts. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Scheme { - inner: SchemeBuilder, + inner: Arc, } impl PartialEq for Scheme { fn eq(&self, other: &Self) -> bool { - ptr::eq(self, other) + Arc::ptr_eq(&self.inner, &other.inner) } } @@ -464,7 +733,7 @@ impl Eq for Scheme {} impl Hash for Scheme { fn hash(&self, state: &mut H) { - (self as *const Scheme).hash(state); + Arc::as_ptr(&self.inner).hash(state); } } @@ -501,11 +770,11 @@ impl<'s> Scheme { /// Returns the [`identifier`](enum@Identifier) with the specified `name`. pub(crate) fn get(&'s self, name: &str) -> Option> { self.inner.items.get(name).map(move |item| match *item { - SchemeItem::Field(index) => Identifier::Field(Field { + SchemeItem::Field(index) => Identifier::Field(FieldRef { scheme: self, index, }), - SchemeItem::Function(index) => Identifier::Function(Function { + SchemeItem::Function(index) => Identifier::Function(FunctionRef { scheme: self, index, }), @@ -513,7 +782,7 @@ impl<'s> Scheme { } /// Returns the [`field`](struct@Field) with the specified `name`. - pub fn get_field(&'s self, name: &str) -> Result, UnknownFieldError> { + pub fn get_field(&'s self, name: &str) -> Result, UnknownFieldError> { match self.get(name) { Some(Identifier::Field(f)) => Ok(f), _ => Err(UnknownFieldError), @@ -522,8 +791,8 @@ impl<'s> Scheme { /// Iterates over fields registered in the [`scheme`](struct@Scheme). #[inline] - pub fn fields(&'s self) -> impl ExactSizeIterator> + 's { - (0..self.inner.fields.len()).map(|index| Field { + pub fn fields(&'s self) -> impl ExactSizeIterator> + 's { + (0..self.inner.fields.len()).map(|index| FieldRef { scheme: self, index, }) @@ -542,7 +811,7 @@ impl<'s> Scheme { } /// Returns the [`function`](struct@Function) with the specified `name`. - pub fn get_function(&'s self, name: &str) -> Result, UnknownFunctionError> { + pub fn get_function(&'s self, name: &str) -> Result, UnknownFunctionError> { match self.get(name) { Some(Identifier::Function(f)) => Ok(f), _ => Err(UnknownFunctionError), @@ -551,8 +820,8 @@ impl<'s> Scheme { /// Iterates over functions registered in the [`scheme`](struct@Scheme). #[inline] - pub fn functions(&'s self) -> impl ExactSizeIterator> + 's { - (0..self.inner.functions.len()).map(|index| Function { + pub fn functions(&'s self) -> impl ExactSizeIterator> + 's { + (0..self.inner.functions.len()).map(|index| FunctionRef { scheme: self, index, }) @@ -569,12 +838,12 @@ impl<'s> Scheme { } /// Parses a filter expression into an AST form. - pub fn parse<'i>(&'s self, input: &'i str) -> Result, ParseError<'i>> { + pub fn parse<'i>(&'s self, input: &'i str) -> Result> { FilterParser::new(self).parse(input) } /// Parses a value expression into an AST form. - pub fn parse_value<'i>(&'s self, input: &'i str) -> Result, ParseError<'i>> { + pub fn parse_value<'i>(&'s self, input: &'i str) -> Result> { FilterParser::new(self).parse_value(input) } @@ -585,16 +854,16 @@ impl<'s> Scheme { } /// Returns the [`list`](struct.List.html) for a given [`type`](enum.Type.html). - pub fn get_list(&self, ty: &Type) -> Option> { - self.inner.list_types.get(ty).map(move |index| List { + pub fn get_list(&self, ty: &Type) -> Option> { + self.inner.list_types.get(ty).map(move |index| ListRef { scheme: self, index: *index, }) } /// Iterates over all registered [`lists`](trait.ListDefinition.html). - pub fn lists(&self) -> impl ExactSizeIterator> { - (0..self.inner.lists.len()).map(|index| List { + pub fn lists(&self) -> impl ExactSizeIterator> { + (0..self.inner.lists.len()).map(|index| ListRef { scheme: self, index, }) @@ -1382,37 +1651,37 @@ fn test_field() { .build(); assert_ok!( - Field::lex_with("x;", scheme), + FieldRef::lex_with("x;", scheme), scheme.get_field("x").unwrap(), ";" ); assert_ok!( - Field::lex_with("x.y.z0-", scheme), + FieldRef::lex_with("x.y.z0-", scheme), scheme.get_field("x.y.z0").unwrap(), "-" ); assert_ok!( - Field::lex_with("is_TCP", scheme), + FieldRef::lex_with("is_TCP", scheme), scheme.get_field("is_TCP").unwrap(), "" ); assert_err!( - Field::lex_with("x..y", scheme), + FieldRef::lex_with("x..y", scheme), LexErrorKind::ExpectedName("identifier character"), ".y" ); assert_err!( - Field::lex_with("x.#", scheme), + FieldRef::lex_with("x.#", scheme), LexErrorKind::ExpectedName("identifier character"), "#" ); assert_err!( - Field::lex_with("x.y.z;", scheme), + FieldRef::lex_with("x.y.z;", scheme), LexErrorKind::UnknownField(UnknownFieldError), "x.y.z" ); @@ -1426,12 +1695,14 @@ fn test_static_field_type_override() { #[test] fn test_field_type_override() { - let mut scheme = Scheme! { foo: Int }; + let mut builder = Scheme! { foo: Int }; assert_eq!( - scheme.add_field("foo", Type::Bytes).unwrap_err(), - IdentifierRedefinitionError::Field(FieldRedefinitionError("foo".into())) - ) + builder.add_field("foo", Type::Bytes), + Err(IdentifierRedefinitionError::Field(FieldRedefinitionError( + "foo".into() + ))) + ); } #[test] diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index c1eddbdb..83b59faa 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -218,15 +218,15 @@ impl<'s> From> for LhsValue<'s> { #[derive(Debug, PartialEq)] #[repr(Rust)] -pub struct FilterAst<'s>(wirefilter::FilterAst<'s>); +pub struct FilterAst(wirefilter::FilterAst); -wrap_type!(FilterAst<'s>); +wrap_type!(FilterAst); #[derive(Debug)] #[repr(Rust)] -pub struct Filter<'s>(wirefilter::Filter<'s, ()>); +pub struct Filter(wirefilter::Filter<()>); -wrap_type!(Filter<'s>); +wrap_type!(Filter); /// Represents the status of an operation. #[derive(Debug, PartialEq)] @@ -391,9 +391,9 @@ pub extern "C" fn wirefilter_free_string(s: RustAllocatedString) { #[derive(Debug, PartialEq)] #[repr(C)] -pub struct ParsingResult<'a> { +pub struct ParsingResult { pub status: Status, - pub ast: Option>>, + pub ast: Option>, } #[no_mangle] @@ -401,7 +401,7 @@ pub extern "C" fn wirefilter_parse_filter( scheme: &Scheme, input_ptr: *const c_char, input_len: usize, -) -> ParsingResult<'_> { +) -> ParsingResult { let input = to_str!( input_ptr, input_len, @@ -433,7 +433,7 @@ pub extern "C" fn wirefilter_parse_filter( } #[no_mangle] -pub extern "C" fn wirefilter_free_parsed_filter(ast: Box>) { +pub extern "C" fn wirefilter_free_parsed_filter(ast: Box) { drop(ast); } @@ -465,7 +465,7 @@ pub struct HashingResult { } #[no_mangle] -pub extern "C" fn wirefilter_get_filter_hash(filter_ast: &FilterAst<'_>) -> HashingResult { +pub extern "C" fn wirefilter_get_filter_hash(filter_ast: &FilterAst) -> HashingResult { let mut hasher = FnvHasher::default(); // Serialize JSON to our Write-compatible wrapper around FnvHasher, // effectively calculating a hash for our filter in a streaming fashion @@ -512,9 +512,7 @@ impl From> for SerializingResult { } #[no_mangle] -pub extern "C" fn wirefilter_serialize_filter_to_json( - filter_ast: &FilterAst<'_>, -) -> SerializingResult { +pub extern "C" fn wirefilter_serialize_filter_to_json(filter_ast: &FilterAst) -> SerializingResult { serde_json::to_string(filter_ast.deref()).into() } @@ -573,11 +571,7 @@ pub extern "C" fn wirefilter_add_int_value_to_execution_context( value: i64, ) -> bool { let name = to_str!(name_ptr, name_len); - let field = match exec_context.scheme().get_field(name) { - Ok(f) => f, - Err(_) => return false, - }; - exec_context.set_field_value(field, value).is_ok() + exec_context.set_field_value_from_name(name, value).is_ok() } #[no_mangle] @@ -591,11 +585,7 @@ pub extern "C" fn wirefilter_add_bytes_value_to_execution_context( let name = to_str!(name_ptr, name_len); assert!(!value_ptr.is_null()); let value = unsafe { std::slice::from_raw_parts(value_ptr, value_len) }; - let field = match exec_context.scheme().get_field(name) { - Ok(f) => f, - Err(_) => return false, - }; - exec_context.set_field_value(field, value).is_ok() + exec_context.set_field_value_from_name(name, value).is_ok() } #[no_mangle] @@ -606,12 +596,8 @@ pub extern "C" fn wirefilter_add_ipv6_value_to_execution_context( value: &[u8; 16], ) -> bool { let name = to_str!(name_ptr, name_len); - let field = match exec_context.scheme().get_field(name) { - Ok(f) => f, - Err(_) => return false, - }; exec_context - .set_field_value(field, IpAddr::from(*value)) + .set_field_value_from_name(name, IpAddr::from(*value)) .is_ok() } @@ -623,12 +609,8 @@ pub extern "C" fn wirefilter_add_ipv4_value_to_execution_context( value: &[u8; 4], ) -> bool { let name = to_str!(name_ptr, name_len); - let field = match exec_context.scheme().get_field(name) { - Ok(f) => f, - Err(_) => return false, - }; exec_context - .set_field_value(field, IpAddr::from(*value)) + .set_field_value_from_name(name, IpAddr::from(*value)) .is_ok() } @@ -640,11 +622,7 @@ pub extern "C" fn wirefilter_add_bool_value_to_execution_context( value: bool, ) -> bool { let name = to_str!(name_ptr, name_len); - let field = match exec_context.scheme().get_field(name) { - Ok(f) => f, - Err(_) => return false, - }; - exec_context.set_field_value(field, value).is_ok() + exec_context.set_field_value_from_name(name, value).is_ok() } #[no_mangle] @@ -655,11 +633,7 @@ pub extern "C" fn wirefilter_add_map_value_to_execution_context<'a>( value: Box>, ) -> bool { let name = to_str!(name_ptr, name_len); - let field = match exec_context.scheme().get_field(name) { - Ok(f) => f, - Err(_) => return false, - }; - exec_context.set_field_value(field, *value).is_ok() + exec_context.set_field_value_from_name(name, *value).is_ok() } #[no_mangle] @@ -670,11 +644,7 @@ pub extern "C" fn wirefilter_add_array_value_to_execution_context<'a>( value: Box>, ) -> bool { let name = to_str!(name_ptr, name_len); - let field = match exec_context.scheme().get_field(name) { - Ok(f) => f, - Err(_) => return false, - }; - exec_context.set_field_value(field, *value).is_ok() + exec_context.set_field_value_from_name(name, *value).is_ok() } #[no_mangle] @@ -856,13 +826,13 @@ pub extern "C" fn wirefilter_free_array(array: Box>) { #[derive(Debug)] #[repr(C)] -pub struct CompilingResult<'a> { +pub struct CompilingResult { pub status: Status, - pub filter: Option>>, + pub filter: Option>, } #[no_mangle] -pub extern "C" fn wirefilter_compile_filter(filter_ast: Box>) -> CompilingResult<'_> { +pub extern "C" fn wirefilter_compile_filter(filter_ast: Box) -> CompilingResult { match catch_panic(std::panic::AssertUnwindSafe(|| { wirefilter::FilterAst::from(*filter_ast).compile() })) { @@ -909,9 +879,9 @@ impl MatchingResult { } #[no_mangle] -pub extern "C" fn wirefilter_match<'e, 's: 'e>( - filter: &Filter<'s>, - exec_context: &ExecutionContext<'e>, +pub extern "C" fn wirefilter_match( + filter: &Filter, + exec_context: &ExecutionContext<'_>, ) -> MatchingResult { match catch_panic(std::panic::AssertUnwindSafe(|| { filter.execute(exec_context) @@ -932,7 +902,7 @@ pub extern "C" fn wirefilter_match<'e, 's: 'e>( } #[no_mangle] -pub extern "C" fn wirefilter_free_compiled_filter(filter: Box>) { +pub extern "C" fn wirefilter_free_compiled_filter(filter: Box) { drop(filter); } @@ -966,7 +936,7 @@ impl UsingResult { #[no_mangle] pub extern "C" fn wirefilter_filter_uses( - filter_ast: &FilterAst<'_>, + filter_ast: &FilterAst, field_name_ptr: *const c_char, field_name_len: usize, ) -> UsingResult { @@ -989,7 +959,7 @@ pub extern "C" fn wirefilter_filter_uses( #[no_mangle] pub extern "C" fn wirefilter_filter_uses_list( - filter_ast: &FilterAst<'_>, + filter_ast: &FilterAst, field_name_ptr: *const c_char, field_name_len: usize, ) -> UsingResult { @@ -1214,7 +1184,7 @@ mod ffi_test { exec_context } - fn parse_filter<'s>(scheme: &'s Scheme, input: &'static str) -> ParsingResult<'s> { + fn parse_filter(scheme: &Scheme, input: &'static str) -> ParsingResult { wirefilter_parse_filter(scheme, input.as_ptr().cast(), input.len()) }