Skip to content

Commit

Permalink
Added second arg to skip param repeating
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Snaps <[email protected]>
  • Loading branch information
alexsnaps committed Nov 5, 2024
1 parent cdc899d commit a8632ce
Showing 1 changed file with 35 additions and 10 deletions.
45 changes: 35 additions & 10 deletions src/data/cel.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::data::get_attribute;
use crate::data::property::{host_get_map, Path};
use cel_interpreter::extractors::This;
use cel_interpreter::extractors::{Arguments, This};
use cel_interpreter::objects::{Key, Map, ValueType};
use cel_interpreter::{Context, ExecutionError, ResolveResult, Value};
use cel_parser::{parse, Expression as CelExpression, Member, ParseError};
Expand Down Expand Up @@ -85,23 +85,34 @@ impl Expression {

/// Decodes the query string and returns a Map where the key is the parameter's name and
/// the value is either a [`Value::String`] or a [`Value::List`] if the parameter's name is repeated
/// and the second arg is set not set to `false`.
/// see [`tests::decodes_query_string`]
fn decode_query_string(This(s): This<Arc<String>>) -> ResolveResult {
fn decode_query_string(This(s): This<Arc<String>>, Arguments(args): Arguments) -> ResolveResult {
let allow_repeats = if args.len() == 2 {
match &args[1] {
Value::Bool(b) => *b,
_ => true,
}
} else {
true
};
let mut map: HashMap<Key, Value> = HashMap::default();
for part in s.split('&') {
let mut kv = part.split('=');
if let (Some(key), Some(value)) = (kv.next(), kv.next().or(Some(""))) {
let new_v: Value = decode(value).unwrap().into_owned().into();
match map.entry(decode(key).unwrap().into_owned().into()) {
Entry::Occupied(mut e) => {
if let Value::List(ref mut list) = e.get_mut() {
Arc::get_mut(list)
.expect("This isn't ever shared!")
.push(new_v);
} else {
let v = e.get().clone();
let list = Value::List([v, new_v].to_vec().into());
e.insert(list);
if allow_repeats {
if let Value::List(ref mut list) = e.get_mut() {
Arc::get_mut(list)
.expect("This isn't ever shared!")
.push(new_v);
} else {
let v = e.get().clone();
let list = Value::List([v, new_v].to_vec().into());
e.insert(list);
}
}
}
Entry::Vacant(e) => {
Expand Down Expand Up @@ -652,6 +663,20 @@ mod tests {
.expect("This is valid!");
assert!(predicate.test());

property::test::TEST_PROPERTY_VALUE.set(Some((
"request.query".into(),
"param1=%F0%9F%91%BE%20&param2=Exterminate%21&%F0%9F%91%BE=123&%F0%9F%91%BE=456&%F0%9F%91%BE"
.bytes()
.collect(),
)));
let predicate = Predicate::route_rule(
"decodeQueryString(request.query, false)['param2'] == 'Exterminate!' && \
decodeQueryString(request.query, false)['👾'] == '123' \
",
)
.expect("This is valid!");
assert!(predicate.test());

property::test::TEST_PROPERTY_VALUE.set(Some((
"request.query".into(),
"%F0%9F%91%BE".bytes().collect(),
Expand Down

0 comments on commit a8632ce

Please sign in to comment.