--- a/crates/jrsonnet-stdlib/src/arrays.rs +++ b/crates/jrsonnet-stdlib/src/arrays.rs @@ -204,10 +204,31 @@ pub fn builtin_lines(arr: ArrValue) -> Result { builtin_join( IndexableVal::Str("\n".into()), - ArrValue::extended(arr, ArrValue::eager(vec![Val::string("")])).into(), + ArrValue::extended(arr, ArrValue::eager(vec![Val::string("")])), ) } +pub fn deep_join_inner(out: &mut String, arr: IndexableVal) -> Result<()> { + use std::fmt::Write; + match arr { + IndexableVal::Str(s) => write!(out, "{s}").expect("no error"), + IndexableVal::Arr(arr) => { + for ele in arr.iter() { + let indexable = IndexableVal::from_untyped(ele?)?; + deep_join_inner(out, indexable)?; + } + } + } + Ok(()) +} + +#[builtin] +pub fn builtin_deep_join(arr: IndexableVal) -> Result { + let mut out = String::new(); + deep_join_inner(&mut out, arr)?; + Ok(out) +} + #[builtin] pub fn builtin_reverse(arr: ArrValue) -> ArrValue { arr.reversed() --- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -86,6 +86,7 @@ ("range", builtin_range::INST), ("join", builtin_join::INST), ("lines", builtin_lines::INST), + ("deepJoin", builtin_deep_join::INST), ("reverse", builtin_reverse::INST), ("any", builtin_any::INST), ("all", builtin_all::INST), --- a/crates/jrsonnet-stdlib/src/std.jsonnet +++ b/crates/jrsonnet-stdlib/src/std.jsonnet @@ -11,14 +11,6 @@ else { [k]: func(k, obj[k]) for k in std.objectFields(obj) }, - deepJoin(arr):: - if std.isString(arr) then - arr - else if std.isArray(arr) then - std.join('', [std.deepJoin(x) for x in arr]) - else - error 'Expected string or array, got %s' % std.type(arr), - assertEqual(a, b):: if a == b then true