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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ outer-regex.workspace = true
rand.workspace = true
regex-automata = { workspace = true, optional = true }
serde.workspace = true
serde_json.workspace = true
simdutf8.workspace = true
sliceslice.workspace = true
thiserror.workspace = true
Expand All @@ -46,7 +47,6 @@ wildcard.workspace = true
[dev-dependencies]
criterion.workspace = true
indoc.workspace = true
serde_json.workspace = true

[target.'cfg(target_family = "wasm")'.dependencies]
# By default, getrandom doesn't have any source of randomness on wasm32-unknown.
Expand Down
8 changes: 3 additions & 5 deletions engine/src/functions/json_lookup_integer.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::iter;

use crate::lhs_types::Bytes;
use crate::{LhsValue, Type};

use super::{FunctionArgKind, FunctionArgs, FunctionDefinition};
use crate::{LhsValue, Type};
use std::iter;

/// Returns the integer value associated with the supplied key in `field`.
///
Expand Down Expand Up @@ -134,6 +131,7 @@ impl FunctionDefinition for JsonLookupIntegerFunction {
#[cfg(test)]
mod tests {
use super::*;
use crate::lhs_types::Bytes;

#[test]
fn test_lookup_json_integer_basic() {
Expand Down
26 changes: 17 additions & 9 deletions engine/src/functions/json_lookup_string.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::iter;

use super::{FunctionArgKind, FunctionArgs, FunctionDefinition};
use crate::lhs_types::Bytes;
use crate::{LhsValue, Type};

use super::{FunctionArgKind, FunctionArgs, FunctionDefinition};
use std::iter;

/// Returns the string value associated with the supplied key in `field`.
///
Expand Down Expand Up @@ -144,7 +142,9 @@ mod tests {
.into_iter();
assert_eq!(
json_lookup_string_impl(&mut args),
Some(LhsValue::Bytes(Bytes::Owned(b"cloudflare".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"cloudflare".to_vec().into_boxed_slice()
)))
);
}

Expand All @@ -159,7 +159,9 @@ mod tests {
.into_iter();
assert_eq!(
json_lookup_string_impl(&mut args),
Some(LhsValue::Bytes(Bytes::Owned(b"cloudflare".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"cloudflare".to_vec().into_boxed_slice()
)))
);
}

Expand All @@ -173,7 +175,9 @@ mod tests {
.into_iter();
assert_eq!(
json_lookup_string_impl(&mut args),
Some(LhsValue::Bytes(Bytes::Owned(b"cloudflare".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"cloudflare".to_vec().into_boxed_slice()
)))
);
}

Expand All @@ -188,7 +192,9 @@ mod tests {
.into_iter();
assert_eq!(
json_lookup_string_impl(&mut args),
Some(LhsValue::Bytes(Bytes::Owned(b"cloudflare".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"cloudflare".to_vec().into_boxed_slice()
)))
);
}

Expand All @@ -203,7 +209,9 @@ mod tests {
.into_iter();
assert_eq!(
json_lookup_string_impl(&mut args),
Some(LhsValue::Bytes(Bytes::Owned(b"cloudflare".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"cloudflare".to_vec().into_boxed_slice()
)))
);
}
}
10 changes: 10 additions & 0 deletions engine/src/functions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ pub(crate) mod cidr;
pub(crate) mod concat;
pub(crate) mod decode_base64;
pub(crate) mod ends_with;
pub(crate) mod json_lookup_integer;
pub(crate) mod json_lookup_string;
pub(crate) mod len;
pub(crate) mod lower;
pub(crate) mod regex_replace;
pub(crate) mod remove_bytes;
pub(crate) mod remove_query_args;
pub(crate) mod starts_with;
pub(crate) mod substring;
pub(crate) mod to_string;
pub(crate) mod upper;
pub(crate) mod url_decode;
pub(crate) mod uuid4;
pub(crate) mod wildcard_replace;
Expand All @@ -25,16 +30,21 @@ pub use cidr::CIDRFunction;
pub use concat::ConcatFunction;
pub use decode_base64::DecodeBase64Function;
pub use ends_with::EndsWithFunction;
pub use json_lookup_integer::JsonLookupIntegerFunction;
pub use json_lookup_string::JsonLookupStringFunction;
pub use len::LenFunction;
pub use lower::LowerFunction;
pub use regex_replace::RegexReplaceFunction;
pub use remove_bytes::RemoveBytesFunction;
pub use remove_query_args::RemoveQueryArgsFunction;
pub use starts_with::StartsWithFunction;
use std::any::Any;
use std::fmt::{self, Debug};
use std::iter::once;
pub use substring::SubstringFunction;
use thiserror::Error;
pub use to_string::ToStringFunction;
pub use upper::UpperFunction;
pub use url_decode::UrlDecodeFunction;
pub use uuid4::UUID4Function;
pub use wildcard_replace::WildcardReplaceFunction;
Expand Down
6 changes: 2 additions & 4 deletions engine/src/functions/remove_query_args.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::collections::HashSet;

use super::{FunctionArgKind, FunctionArgs, FunctionDefinition};
use crate::lhs_types::Bytes;
use crate::{LhsValue, Type};

use super::{FunctionArgKind, FunctionArgs, FunctionDefinition};
use std::collections::HashSet;

/// Removes one or more query string parameters from a URI query string.
///
Expand Down
16 changes: 10 additions & 6 deletions engine/src/functions/to_string.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use super::{FunctionArgKind, FunctionArgs, FunctionDefinition};
use crate::lhs_types::Bytes;
use crate::{LhsValue, Type};

use super::{FunctionArgKind, FunctionArgs, FunctionDefinition};

/// Convert an Integer, Boolean, or IP LHS value into its textual representation.
///
/// Usage:
Expand Down Expand Up @@ -39,9 +38,15 @@ fn to_string_impl<'a>(args: FunctionArgs<'_, 'a>) -> Option<LhsValue<'a>> {
}

match arg {
Ok(LhsValue::Int(i)) => Some(LhsValue::Bytes(Bytes::Owned(i.to_string().into_boxed_str().into_boxed_bytes()))),
Ok(LhsValue::Bool(b)) => Some(LhsValue::Bytes(Bytes::Owned(b.to_string().into_boxed_str().into_boxed_bytes()))),
Ok(LhsValue::Ip(ip)) => Some(LhsValue::Bytes(Bytes::Owned(ip.to_string().into_boxed_str().into_boxed_bytes()))),
Ok(LhsValue::Int(i)) => Some(LhsValue::Bytes(Bytes::Owned(
i.to_string().into_boxed_str().into_boxed_bytes(),
))),
Ok(LhsValue::Bool(b)) => Some(LhsValue::Bytes(Bytes::Owned(
b.to_string().into_boxed_str().into_boxed_bytes(),
))),
Ok(LhsValue::Ip(ip)) => Some(LhsValue::Bytes(Bytes::Owned(
ip.to_string().into_boxed_str().into_boxed_bytes(),
))),
Err(Type::Int) | Err(Type::Bool) | Err(Type::Ip) => None,
_ => unreachable!(),
}
Expand Down Expand Up @@ -93,7 +98,6 @@ impl FunctionDefinition for ToStringFunction {
#[cfg(test)]
mod tests {
use super::*;
use std::borrow::Cow;

fn owned(s: &str) -> LhsValue<'_> {
LhsValue::Bytes(Bytes::Owned(s.as_bytes().to_vec().into_boxed_slice()))
Expand Down
34 changes: 24 additions & 10 deletions engine/src/functions/upper.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::iter;

use crate::lhs_types::Bytes;
use crate::{FunctionArgKind, FunctionArgs, FunctionDefinition, LhsValue, Type};
use std::iter;

/// Converts a string field to uppercase. Only lowercase ASCII bytes are converted. All other bytes are unaffected.
/// For example, if http.host is "www.cloudflare.com", then upper(http.host) will return "WWW.CLOUDFLARE.COM".
Expand All @@ -20,7 +19,9 @@ fn upper_impl<'a>(args: FunctionArgs<'_, 'a>) -> Option<LhsValue<'a>> {
Ok(LhsValue::Bytes(bytes)) => {
let bytes_upper: Vec<u8> = bytes.into_owned().to_vec();
let bytes_upper = bytes_upper.to_ascii_uppercase();
Some(LhsValue::Bytes(Bytes::Owned(bytes_upper.into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
bytes_upper.into_boxed_slice(),
)))
}
Err(Type::Bytes) => None,
_ => unreachable!(),
Expand Down Expand Up @@ -78,36 +79,47 @@ mod tests {
let mut args_lower = vec![Ok(LhsValue::Bytes(Bytes::Borrowed(b"hello world")))].into_iter();
assert_eq!(
upper_impl(&mut args_lower),
Some(LhsValue::Bytes(Bytes::Owned(b"HELLO WORLD".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"HELLO WORLD".to_vec().into_boxed_slice()
)))
);

// Test with a mixed-case string
let mut args_mixed = vec![Ok(LhsValue::Bytes(Bytes::Borrowed(b"MiXeD CaSe")))].into_iter();
assert_eq!(
upper_impl(&mut args_mixed),
Some(LhsValue::Bytes(Bytes::Owned(b"MIXED CASE".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"MIXED CASE".to_vec().into_boxed_slice()
)))
);

// Test with an already uppercase string
let mut args_upper = vec![Ok(LhsValue::Bytes(Bytes::Borrowed(b"ALREADY UPPER")))].into_iter();
let mut args_upper =
vec![Ok(LhsValue::Bytes(Bytes::Borrowed(b"ALREADY UPPER")))].into_iter();
assert_eq!(
upper_impl(&mut args_upper),
Some(LhsValue::Bytes(Bytes::Owned(b"ALREADY UPPER".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"ALREADY UPPER".to_vec().into_boxed_slice()
)))
);

// Test with the example from the specification: "www.cloudflare.com"
let mut args_example =
vec![Ok(LhsValue::Bytes(Bytes::Borrowed(b"www.cloudflare.com")))].into_iter();
assert_eq!(
upper_impl(&mut args_example),
Some(LhsValue::Bytes(Bytes::Owned(b"WWW.CLOUDFLARE.COM".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"WWW.CLOUDFLARE.COM".to_vec().into_boxed_slice()
)))
);

// Test with an empty string
let mut args_empty = vec![Ok(LhsValue::Bytes(Bytes::Borrowed(b"")))].into_iter();
assert_eq!(
upper_impl(&mut args_empty),
Some(LhsValue::Bytes(Bytes::Owned(b"".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"".to_vec().into_boxed_slice()
)))
);

// Test with missing field
Expand All @@ -119,7 +131,9 @@ mod tests {
vec![Ok(LhsValue::Bytes(Bytes::Borrowed(b"hello\xc3\xa9world")))].into_iter();
assert_eq!(
upper_impl(&mut args_non_ascii),
Some(LhsValue::Bytes(Bytes::Owned(b"HELLO\xc3\xa9WORLD".to_vec().into_boxed_slice())))
Some(LhsValue::Bytes(Bytes::Owned(
b"HELLO\xc3\xa9WORLD".to_vec().into_boxed_slice()
)))
);
}

Expand Down
9 changes: 5 additions & 4 deletions engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ pub use self::functions::{
AllFunction, AnyFunction, CIDRFunction, CompiledFunction, ConcatFunction, DecodeBase64Function,
EndsWithFunction, FunctionArgInvalidConstantError, FunctionArgKind,
FunctionArgKindMismatchError, FunctionArgs, FunctionDefinition, FunctionDefinitionContext,
FunctionParam, FunctionParamError, LenFunction, LowerFunction, RegexReplaceFunction,
RemoveBytesFunction, SimpleFunctionArgKind, SimpleFunctionDefinition, SimpleFunctionImpl,
SimpleFunctionOptParam, SimpleFunctionParam, StartsWithFunction, SubstringFunction,
UUID4Function, UrlDecodeFunction, WildcardReplaceFunction,
FunctionParam, FunctionParamError, JsonLookupIntegerFunction, JsonLookupStringFunction,
LenFunction, LowerFunction, RegexReplaceFunction, RemoveBytesFunction, RemoveQueryArgsFunction,
SimpleFunctionArgKind, SimpleFunctionDefinition, SimpleFunctionImpl, SimpleFunctionOptParam,
SimpleFunctionParam, StartsWithFunction, SubstringFunction, ToStringFunction, UUID4Function,
UpperFunction, UrlDecodeFunction, WildcardReplaceFunction,
};
pub use self::lex::LexErrorKind;
pub use self::lhs_types::{Array, Bytes, Map, MapIter, TypedArray, TypedMap};
Expand Down
54 changes: 51 additions & 3 deletions ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ use std::net::IpAddr;
use std::ops::{Deref, DerefMut};
use wirefilter::{
AllFunction, AlwaysList, AnyFunction, CIDRFunction, ConcatFunction, DecodeBase64Function,
GetType, LenFunction, LowerFunction, NeverList, RegexReplaceFunction, RemoveBytesFunction,
StartsWithFunction, SubstringFunction, Type, UUID4Function, UrlDecodeFunction,
WildcardReplaceFunction, catch_panic,
EndsWithFunction, GetType, JsonLookupIntegerFunction, JsonLookupStringFunction, LenFunction,
LowerFunction, NeverList, RegexReplaceFunction, RemoveBytesFunction, RemoveQueryArgsFunction,
StartsWithFunction, SubstringFunction, ToStringFunction, Type, UUID4Function, UpperFunction,
UrlDecodeFunction, WildcardReplaceFunction, catch_panic,
};

const VERSION: &str = env!("CARGO_PKG_VERSION");
Expand Down Expand Up @@ -406,6 +407,53 @@ pub extern "C" fn wirefilter_add_function_to_scheme(
false
}
},
"ends_with" => match builder.add_function(name, EndsWithFunction::default()) {
Ok(_) => true,
Err(err) => {
write_last_error!("{}", err);
false
}
},
"upper" => match builder.add_function(name, UpperFunction::default()) {
Ok(_) => true,
Err(err) => {
write_last_error!("{}", err);
false
}
},
"to_string" => match builder.add_function(name, ToStringFunction::default()) {
Ok(_) => true,
Err(err) => {
write_last_error!("{}", err);
false
}
},
"remove_query_args" => match builder.add_function(name, RemoveQueryArgsFunction::default())
{
Ok(_) => true,
Err(err) => {
write_last_error!("{}", err);
false
}
},
"lookup_json_string" => {
match builder.add_function(name, JsonLookupStringFunction::default()) {
Ok(_) => true,
Err(err) => {
write_last_error!("{}", err);
false
}
}
}
"lookup_json_integer" => {
match builder.add_function(name, JsonLookupIntegerFunction::default()) {
Ok(_) => true,
Err(err) => {
write_last_error!("{}", err);
false
}
}
}
_ => {
write_last_error!("Unknown function name provided: {}", name);
false
Expand Down
Loading