--- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,6 @@ opt-level = 3 lto = "fat" codegen-units = 1 -# debug = 0 +debug = 0 panic = "abort" -# strip = true +strip = true --- a/crates/jrsonnet-evaluator/src/val.rs +++ b/crates/jrsonnet-evaluator/src/val.rs @@ -206,9 +206,13 @@ pub fn new_eager() -> Self { Self::Eager(Cc::new(Vec::new())) } + pub fn empty() -> Self { + Self::new_range(0, 0) + } /// # Panics /// If a > b + #[inline] pub fn new_range(a: i32, b: i32) -> Self { assert!(a <= b); Self::Range(a, b) --- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -128,6 +128,7 @@ ("splitLimit".into(), builtin_splitlimit::INST), ("asciiUpper".into(), builtin_ascii_upper::INST), ("asciiLower".into(), builtin_ascii_lower::INST), + ("findSubstr".into(), builtin_find_substr::INST), ] .iter() .cloned() @@ -420,3 +421,28 @@ fn builtin_ascii_lower(str: IStr) -> Result { Ok(str.to_ascii_lowercase()) } + +#[builtin] +fn builtin_find_substr(pat: IStr, str: IStr) -> Result { + if pat.is_empty() || str.is_empty() || pat.len() > str.len() { + return Ok(ArrValue::empty()); + } + + let str = str.as_str(); + let pat = pat.as_bytes(); + let strb = str.as_bytes(); + + let max_pos = str.len() - pat.len(); + + let mut out: Vec = Vec::new(); + for (ch_idx, (i, _)) in str + .char_indices() + .take_while(|(i, _)| i <= &max_pos) + .enumerate() + { + if &strb[i..i + pat.len()] == pat { + out.push(Val::Num(ch_idx as f64)) + } + } + Ok(out.into()) +} --- a/crates/jrsonnet-stdlib/src/std.jsonnet +++ b/crates/jrsonnet-stdlib/src/std.jsonnet @@ -477,19 +477,6 @@ } else a, - findSubstr(pat, str):: - if !std.isString(pat) then - error 'findSubstr first parameter should be a string, got ' + std.type(pat) - else if !std.isString(str) then - error 'findSubstr second parameter should be a string, got ' + std.type(str) - else - local pat_len = std.length(pat); - local str_len = std.length(str); - if pat_len == 0 || str_len == 0 || pat_len > str_len then - [] - else - std.filter(function(i) str[i:i + pat_len] == pat, std.range(0, str_len - pat_len)), - find(value, arr):: if !std.isArray(arr) then error 'find second parameter should be an array, got ' + std.type(arr)