--- a/crates/jrsonnet-stdlib/src/encoding.rs +++ b/crates/jrsonnet-stdlib/src/encoding.rs @@ -1,5 +1,6 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use jrsonnet_evaluator::{ + bail, function::builtin, runtime_error, typed::{Either, Either2}, @@ -12,8 +13,14 @@ } #[builtin] -pub fn builtin_decode_utf8(arr: IBytes) -> Result { - arr.cast_str().ok_or_else(|| runtime_error!("bad utf8")) +pub fn builtin_decode_utf8(arr: IBytes, #[default(true)] lossy: bool) -> Result { + match arr.clone().cast_str() { + Some(s) => Ok(s), + None if lossy => Ok(String::from_utf8_lossy(arr.as_slice()).into()), + None => { + bail!("bad utf8") + } + } } #[builtin] --- /dev/null +++ b/tests/golden/issue187.jsonnet @@ -0,0 +1 @@ +std.decodeUTF8(std.encodeUTF8('foo bar ') + [255] + std.encodeUTF8(' baz')) --- /dev/null +++ b/tests/golden/issue187.jsonnet.golden @@ -0,0 +1 @@ +"foo bar � baz" \ No newline at end of file --- /dev/null +++ b/tests/golden/issue187.rev.jsonnet @@ -0,0 +1 @@ +std.decodeUTF8(std.encodeUTF8('foo bar ') + [255] + std.encodeUTF8(' baz'), lossy = false) --- /dev/null +++ b/tests/golden/issue187.rev.jsonnet.golden @@ -0,0 +1,2 @@ +runtime error: bad utf8 + issue187.rev.jsonnet:1:1-92: function call \ No newline at end of file --- a/tests/suite/std_param_names.jsonnet +++ b/tests/suite/std_param_names.jsonnet @@ -129,7 +129,7 @@ parseJson: ['str'], parseYaml: ['str'], encodeUTF8: ['str'], - decodeUTF8: ['arr'], + decodeUTF8: ['arr', 'lossy'], sum: ['arr'], avg: ['arr', 'onEmpty'],