--- a/crates/jsonnet-evaluator/src/ctx.rs +++ b/crates/jsonnet-evaluator/src/ctx.rs @@ -1,4 +1,4 @@ -use crate::{future_wrapper, rc_fn_helper, LazyBinding, ObjValue, LazyVal, Val}; +use crate::{future_wrapper, rc_fn_helper, LazyBinding, LazyVal, ObjValue}; use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc}; rc_fn_helper!( @@ -51,13 +51,9 @@ } pub fn binding(&self, name: &str) -> LazyVal { - self.0 - .bindings - .get(name) - .cloned() - .unwrap_or_else(|| { - panic!("can't find {} in {:?}", name, self); - }) + self.0.bindings.get(name).cloned().unwrap_or_else(|| { + panic!("can't find {} in {:?}", name, self); + }) } pub fn into_future(self, ctx: FutureContext) -> Context { { --- a/crates/jsonnet-evaluator/src/evaluate.rs +++ b/crates/jsonnet-evaluator/src/evaluate.rs @@ -1,7 +1,7 @@ use crate::{ binding, bool_val, context_creator, function_default, function_rhs, future_wrapper, - lazy_binding, lazy_val, Binding, Context, ContextCreator, FuncDesc, LazyBinding, ObjMember, - ObjValue, Val, + lazy_binding, lazy_val, Context, ContextCreator, FuncDesc, LazyBinding, ObjMember, ObjValue, + Val, }; use closure::closure; use jsonnet_parser::{ @@ -284,8 +284,7 @@ .unwrap_or_else(|| panic!("out of bounds")) .clone(), (Val::Str(s), Val::Num(n)) => { - // FIXME: Only works for ASCII - Val::Str(String::from_utf8(vec![s.as_bytes()[n as usize]]).unwrap()) + Val::Str(s.chars().skip(n as usize - 1).take(1).collect()) } (v, i) => todo!("not implemented: {:?}[{:?}]", v, i.unwrap_if_lazy()), } @@ -320,7 +319,7 @@ assert_eq!(args.len(), 1); let expr = &args.get(0).unwrap().1; match evaluate(context, expr) { - Val::Str(n) => Val::Num(n.len() as f64), + Val::Str(n) => Val::Num(n.chars().count() as f64), Val::Arr(i) => Val::Num(i.len() as f64), v => panic!("can't get length of {:?}", v), } @@ -349,8 +348,11 @@ ("std", "codepoint") => { assert_eq!(args.len(), 1); if let Val::Str(s) = evaluate(context.clone(), &args[0].1) { - // FIXME: this is not a codepoint - Val::Num(s.as_bytes()[0] as f64) + assert!( + s.chars().count() == 1, + "std.codepoint should receive single char string" + ); + Val::Num(s.chars().take(1).next().unwrap() as u32 as f64) } else { panic!("bad codepoint call"); } --- a/crates/jsonnet-evaluator/src/lib.rs +++ b/crates/jsonnet-evaluator/src/lib.rs @@ -68,10 +68,7 @@ } macro_rules! assert_json_stdlib { ($str: expr, $out: expr) => { - assert_eq!( - format!("{}", eval_stdlib!($str)), - $out - ) + assert_eq!(format!("{}", eval_stdlib!($str)), $out) }; } macro_rules! assert_eval_neg { @@ -237,4 +234,12 @@ fn base64_works() { assert_json_stdlib!(r#"std.base64("test")"#, r#""dGVzdA==""#); } + + #[test] + fn utf8_chars() { + assert_json_stdlib!( + r#"local c="😎";{c:std.codepoint(c),l:std.length(c)}"#, + r#"{"c":128526,"l":1}"# + ) + } }