Skip to content

Commit 21bcb6f

Browse files
committed
Add slice extension
1 parent 5b8d3e3 commit 21bcb6f

4 files changed

Lines changed: 69 additions & 0 deletions

File tree

src/input_handler.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::io::{self};
1515
use crate::InputParameters;
1616
use crate::cel_value_to_json_value;
1717
use crate::json_to_cel_variables;
18+
use crate::slice_extension;
1819

1920
/// Process input from stdin and execute the CEL program
2021
///
@@ -174,6 +175,7 @@ fn handle_json(
174175
) -> Result<(String, bool)> {
175176
// Create context with default values
176177
let mut context = Context::default();
178+
context.add_function("slice", slice_extension::slice);
177179

178180
// Add argument variables to context
179181
for (name, value) in arg_variables {

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod cel2json;
1313
mod cli;
1414
mod input_handler;
1515
mod json2cel;
16+
pub mod slice_extension;
1617

1718
use args2cel::args_to_cel_variables;
1819
pub use cel2json::cel_value_to_json_value;

src/slice_extension.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use cel::Value;
2+
use cel::extractors::This;
3+
use std::sync::Arc;
4+
5+
/// Returns a slice of a list, Python-style. We support negative indices and indices
6+
/// that are beyond the end of the list.
7+
pub fn slice(This(this): This<Arc<Vec<Value>>>, start: i64, end: i64) -> Arc<Vec<Value>> {
8+
let len = this.len() as i64;
9+
10+
// Normalize negative indices
11+
let norm_start = if start < 0 {
12+
(len + start).max(0)
13+
} else {
14+
start.min(len)
15+
} as usize;
16+
17+
let norm_end = if end < 0 {
18+
(len + end).max(0)
19+
} else {
20+
end.min(len)
21+
} as usize;
22+
23+
// Handle case where start >= end
24+
if norm_start >= norm_end {
25+
return Arc::new(Vec::new());
26+
}
27+
28+
// Extract the slice
29+
Arc::new(this[norm_start..norm_end].to_vec())
30+
}

tests/golden.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,42 @@ json.a.b.c.d[0].e = "deep";
857857
r#"{"a":{"b":{"c":{"d":[{"e":"deep"}]}}}}"#
858858
);
859859

860+
// Slice extension tests
861+
test!(
862+
slice_basic,
863+
&["this.items.slice(1, 3)"],
864+
r#"{"items":[1,2,3,4,5]}"#,
865+
"[2,3]"
866+
);
867+
868+
test!(
869+
slice_negative_indices,
870+
&["this.items.slice(-3, -1)"],
871+
r#"{"items":[10,20,30,40,50]}"#,
872+
"[30,40]"
873+
);
874+
875+
test!(
876+
slice_from_start,
877+
&["this.items.slice(0, 2)"],
878+
r#"{"items":["a","b","c","d"]}"#,
879+
r#"["a","b"]"#
880+
);
881+
882+
test!(
883+
slice_beyond_bounds,
884+
&["this.items.slice(2, 100)"],
885+
r#"{"items":[1,2,3]}"#,
886+
"[3]"
887+
);
888+
889+
test!(
890+
slice_negative_to_positive,
891+
&["this.items.slice(-5, 4)"],
892+
r#"{"items":[5,10,15,20,25,30]}"#,
893+
"[10,15,20]"
894+
);
895+
860896
#[test]
861897
fn test_boolean_false_exit_code() -> io::Result<()> {
862898
let mut child = process::Command::new(env!("CARGO_BIN_EXE_celq"))

0 commit comments

Comments
 (0)