--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs +++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs @@ -114,6 +114,8 @@ ("encodeUTF8".into(), builtin_encode_utf8), ("md5".into(), builtin_md5), ("base64".into(), builtin_base64), + ("base64DecodeBytes".into(), builtin_base64_decode_bytes), + ("base64Decode".into(), builtin_base64_decode), ("trace".into(), builtin_trace), ("join".into(), builtin_join), ("escapeStringJson".into(), builtin_escape_string_json), @@ -626,6 +628,39 @@ }) } +fn builtin_base64_decode_bytes( + context: Context, + _loc: Option<&ExprLocation>, + args: &ArgsDesc, +) -> Result { + parse_args!(context, "base64DecodeBytes", args, 1, [ + 0, input: ty!(string) => Val::Str; + ], { + Ok(Val::Arr( + base64::decode(&input.as_bytes()) + .map_err(|_| RuntimeError("bad base64".into()))? + .iter() + .map(|v| Val::Num(*v as f64)).collect::>().into() + )) + }) +} + +fn builtin_base64_decode( + context: Context, + _loc: Option<&ExprLocation>, + args: &ArgsDesc, +) -> Result { + parse_args!(context, "base64Decode", args, 1, [ + 0, input: ty!(string) => Val::Str; + ], { + Ok(Val::Str( + String::from_utf8(base64::decode(&input.as_bytes()) + .map_err(|_| RuntimeError("bad base64".into()))?) + .map_err(|_| RuntimeError("bad utf8".into()))?.into() + )) + }) +} + fn builtin_join(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result { parse_args!(context, "join", args, 2, [ 0, sep: ty!((string | array)); --- a/crates/jrsonnet-stdlib/src/std.jsonnet +++ b/crates/jrsonnet-stdlib/src/std.jsonnet @@ -531,30 +531,9 @@ base64:: $intrinsic(base64), - base64DecodeBytes(str):: - if std.length(str) % 4 != 0 then - error 'Not a base64 encoded string "%s"' % str - else - local aux(str, i, r) = - if i >= std.length(str) then - r - else - // all 6 bits of i, 2 MSB of i+1 - local n1 = [base64_inv[str[i]] << 2 | (base64_inv[str[i + 1]] >> 4)]; - // 4 LSB of i+1, 4MSB of i+2 - local n2 = - if str[i + 2] == '=' then [] - else [(base64_inv[str[i + 1]] & 15) << 4 | (base64_inv[str[i + 2]] >> 2)]; - // 2 LSB of i+2, all 6 bits of i+3 - local n3 = - if str[i + 3] == '=' then [] - else [(base64_inv[str[i + 2]] & 3) << 6 | base64_inv[str[i + 3]]]; - aux(str, i + 4, r + n1 + n2 + n3) tailstrict; - aux(str, 0, []), + base64DecodeBytes:: $intrinsic(base64DecodeBytes), - base64Decode(str):: - local bytes = std.base64DecodeBytes(str); - std.join('', std.map(function(b) std.char(b), bytes)), + base64Decode:: $intrinsic(base64Decode), reverse:: $intrinsic(reverse),