difftreelog
perf(evaluator) use hashmap for object body
in: master
4 files changed
bindings/jsonnet/src/lib.rsdiffbeforeafterboth1use jrsonnet_evaluator::{2 create_error, create_error_result, Error, EvaluationState, ImportResolver, LazyBinding,3 LazyVal, ObjMember, ObjValue, Result, Val,4};5use jrsonnet_parser::Visibility;6use libc::{c_char, c_double, c_int, c_uint};7use std::{8 alloc::Layout,9 any::Any,10 cell::RefCell,11 collections::BTreeMap,12 ffi::{CStr, CString},13 fs::File,14 io::Read,15 path::PathBuf,16 rc::Rc,17};1819#[no_mangle]20#[cfg(target = "wasm32-wasi")]21pub extern "C" fn _start() {}2223#[no_mangle]24pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {25 b"v0.16.0\0"26}2728#[derive(Default)]29struct NativeImportResolver {30 library_paths: RefCell<Vec<PathBuf>>,31}32impl NativeImportResolver {33 fn add_jpath(&self, path: PathBuf) {34 self.library_paths.borrow_mut().push(path);35 }36}37impl ImportResolver for NativeImportResolver {38 fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {39 let mut new_path = from.clone();40 new_path.push(path);41 if new_path.exists() {42 Ok(Rc::new(new_path))43 } else {44 for library_path in self.library_paths.borrow().iter() {45 let mut cloned = library_path.clone();46 cloned.push(path);47 if cloned.exists() {48 return Ok(Rc::new(cloned));49 }50 }51 create_error_result(Error::ImportFileNotFound(from.clone(), path.clone()))52 }53 }54 fn load_file_contents(&self, id: &PathBuf) -> Result<Rc<str>> {55 let mut file =56 File::open(id).map_err(|_e| create_error(Error::ResolvedFileNotFound(id.clone())))?;57 let mut out = String::new();58 file.read_to_string(&mut out)59 .map_err(|_e| create_error(Error::ImportBadFileUtf8(id.clone())))?;60 Ok(out.into())61 }62 unsafe fn as_any(&self) -> &dyn Any {63 self64 }65}6667#[no_mangle]68pub extern "C" fn jsonnet_make() -> Box<EvaluationState> {69 let state = EvaluationState::default();70 state.with_stdlib();71 state.set_import_resolver(Box::new(NativeImportResolver::default()));72 Box::new(state)73}7475#[no_mangle]76pub extern "C" fn jsonnet_max_stack(vm: &EvaluationState, v: c_uint) {77 vm.set_max_stack(v as usize);78}7980// jrsonnet currently have no GC, so these functions is no-op81#[no_mangle]82pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}83#[no_mangle]84pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}8586// TODO87#[no_mangle]88pub extern "C" fn jsonnet_string_output(_vm: &EvaluationState, _v: c_int) {89 todo!()90}9192#[no_mangle]93pub extern "C" fn jsonnet_json_extract_string(_vm: &EvaluationState, v: &Val) -> *mut c_char {94 match v.unwrap_if_lazy().unwrap() {95 Val::Str(s) => CString::new(&*s as &str).unwrap().into_raw(),96 _ => std::ptr::null_mut(),97 }98}99#[no_mangle]100pub extern "C" fn jsonnet_json_extract_number(101 _vm: &EvaluationState,102 v: &Val,103 out: &mut c_double,104) -> c_int {105 match v.unwrap_if_lazy().unwrap() {106 Val::Num(n) => {107 *out = n;108 1109 }110 _ => 0,111 }112}113#[no_mangle]114pub extern "C" fn jsonnet_json_extract_bool(_vm: &EvaluationState, v: &Val) -> c_int {115 match v.unwrap_if_lazy().unwrap() {116 Val::Bool(false) => 0,117 Val::Bool(true) => 1,118 _ => 2,119 }120}121#[no_mangle]122pub extern "C" fn jsonnet_json_extract_null(_vm: &EvaluationState, v: &Val) -> c_int {123 match v.unwrap_if_lazy().unwrap() {124 Val::Null => 1,125 _ => 0,126 }127}128129/// # Safety130///131/// This function is safe, if received v is a pointer to normal C string132#[no_mangle]133pub unsafe extern "C" fn jsonnet_json_make_string(134 _vm: &EvaluationState,135 v: *const c_char,136) -> Box<Val> {137 let cstr = CStr::from_ptr(v);138 let str = cstr.to_str().unwrap();139 Box::new(Val::Str(str.into()))140}141142#[no_mangle]143pub extern "C" fn jsonnet_json_make_number(_vm: &EvaluationState, v: c_double) -> Box<Val> {144 Box::new(Val::Num(v))145}146147#[no_mangle]148pub extern "C" fn jsonnet_json_make_bool(_vm: &EvaluationState, v: c_int) -> Box<Val> {149 assert!(v == 0 || v == 1);150 Box::new(Val::Bool(v == 1))151}152153#[no_mangle]154pub extern "C" fn jsonnet_json_make_null(_vm: &EvaluationState) -> Box<Val> {155 Box::new(Val::Null)156}157158#[no_mangle]159pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> Box<Val> {160 Box::new(Val::Arr(Rc::new(Vec::new())))161}162163#[no_mangle]164pub extern "C" fn jsonnet_json_array_append(_vm: &EvaluationState, arr: &mut Val, val: &Val) {165 match arr {166 Val::Arr(old) => {167 // TODO: Mutate array, instead of recreating them168 let mut new = Vec::new();169 new.extend(old.iter().cloned());170 new.push(val.clone());171 *arr = Val::Arr(Rc::new(new));172 }173 _ => panic!("should receive array"),174 }175}176177#[no_mangle]178pub extern "C" fn jsonnet_json_make_object(_vm: &EvaluationState) -> Box<Val> {179 Box::new(Val::Obj(ObjValue::new_empty()))180}181182/// # Safety183///184/// This function is safe if passed name is ok185#[no_mangle]186pub unsafe extern "C" fn jsonnet_json_object_append(187 _vm: &EvaluationState,188 obj: &mut Val,189 name: *const c_char,190 val: &Val,191) {192 match obj {193 Val::Obj(old) => {194 let mut new = BTreeMap::new();195 new.insert(196 CStr::from_ptr(name).to_str().unwrap().into(),197 ObjMember {198 add: false,199 visibility: Visibility::Normal,200 invoke: LazyBinding::Bound(LazyVal::new_resolved(val.clone())),201 },202 );203 let new_obj = ObjValue::new(Some(old.clone()), Rc::new(new));204 *obj = Val::Obj(new_obj);205 }206 _ => panic!("should receive array"),207 }208}209210/// # Safety211///212/// This function is most definitely broken, but it works somehow, see TODO inside213#[no_mangle]214pub unsafe extern "C" fn jsonnet_realloc(215 _vm: &EvaluationState,216 buf: *mut u8,217 sz: usize,218) -> *mut u8 {219 if buf.is_null() {220 assert!(sz != 0);221 return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());222 }223 // TODO: Somehow store size of allocation, because its real size is probally not 16 :D224 // OR (Alternative way of fixing this TODO)225 // TODO: Standard allocator uses malloc, and it doesn't uses allocation size,226 // TODO: so it should work in normal cases. Maybe force allocator for this library?227 let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();228 if sz == 0 {229 std::alloc::dealloc(buf, old_layout);230 return std::ptr::null_mut();231 }232 std::alloc::realloc(buf, old_layout, sz)233}234235#[no_mangle]236#[allow(clippy::boxed_local)]237pub extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, _v: Box<Val>) {}238239#[no_mangle]240pub extern "C" fn jsonnet_import_callback() {241 todo!()242}243#[no_mangle]244pub extern "C" fn jsonnet_native_callback() {245 todo!()246}247#[no_mangle]248pub extern "C" fn jsonnet_ext_var() {249 todo!()250}251#[no_mangle]252pub extern "C" fn jsonnet_ext_code() {253 todo!()254}255#[no_mangle]256pub extern "C" fn jsonnet_tla_var() {257 todo!()258}259#[no_mangle]260pub extern "C" fn jsonnet_tla_code() {261 todo!()262}263#[no_mangle]264pub extern "C" fn jsonnet_max_trace() {265 todo!()266}267268/// # Safety269///270/// This function is safe, if received v is a pointer to normal C string271#[no_mangle]272pub unsafe extern "C" fn jsonnet_jpath_add(vm: &EvaluationState, v: *const c_char) {273 let cstr = CStr::from_ptr(v);274 let path = PathBuf::from(cstr.to_str().unwrap());275 let any_resolver = vm.import_resolver();276 let resolver = any_resolver277 .as_any()278 .downcast_ref::<NativeImportResolver>()279 .unwrap();280 resolver.add_jpath(path);281}282283/// # Safety284///285/// This function is safe, if received v is a pointer to normal C string286#[no_mangle]287pub unsafe extern "C" fn jsonnet_evaluate_file(288 vm: &EvaluationState,289 filename: *const c_char,290 error: &mut c_int,291) -> *const c_char {292 vm.run_in_state(|| {293 use std::fmt::Write;294 let filename = CStr::from_ptr(filename);295 match vm.evaluate_file_to_json(&PathBuf::from(filename.to_str().unwrap())) {296 Ok(v) => {297 *error = 0;298 CString::new(&*v as &str).unwrap().into_raw()299 }300 Err(e) => {301 *error = 1;302 let mut out = String::new();303 writeln!(out, "{:?}", e.0).unwrap();304 for i in (e.1).0.iter() {305 writeln!(out, "{:?}", i.0).unwrap();306 }307 CString::new(&out as &str).unwrap().into_raw()308 }309 }310 })311}312313/// # Safety314///315/// This function is safe, if received v is a pointer to normal C string316#[no_mangle]317pub unsafe extern "C" fn jsonnet_evaluate_snippet(318 vm: &EvaluationState,319 filename: *const c_char,320 snippet: *const c_char,321 error: &mut c_int,322) -> *const c_char {323 vm.run_in_state(|| {324 use std::fmt::Write;325 let filename = CStr::from_ptr(filename);326 let snippet = CStr::from_ptr(snippet);327 match vm.evaluate_snippet_to_json(328 &PathBuf::from(filename.to_str().unwrap()),329 &snippet.to_str().unwrap(),330 ) {331 Ok(v) => {332 *error = 0;333 CString::new(&*v as &str).unwrap().into_raw()334 }335 Err(e) => {336 *error = 1;337 let mut out = String::new();338 writeln!(out, "{:?}", e.0).unwrap();339 for i in (e.1).0.iter() {340 writeln!(out, "{:?} ---- {}", i.0, i.1).unwrap();341 }342 CString::new(&out as &str).unwrap().into_raw()343 }344 }345 })346}347348#[no_mangle]349pub extern "C" fn jsonnet_evaluate_file_multi() {350 todo!()351}352#[no_mangle]353pub extern "C" fn jsonnet_evaluate_snippet_multi() {354 todo!()355}356#[no_mangle]357pub extern "C" fn jsonnet_evaluate_file_stream() {358 todo!()359}360#[no_mangle]361pub extern "C" fn jsonnet_evaluate_snippet_stream() {362 todo!()363}364365#[no_mangle]366#[allow(clippy::boxed_local)]367pub extern "C" fn jsonnet_destroy(_vm: Box<EvaluationState>) {}1use jrsonnet_evaluator::{2 create_error, create_error_result, Error, EvaluationState, ImportResolver, LazyBinding,3 LazyVal, ObjMember, ObjValue, Result, Val,4};5use jrsonnet_parser::Visibility;6use libc::{c_char, c_double, c_int, c_uint};7use std::{8 alloc::Layout,9 any::Any,10 cell::RefCell,11 collections::HashMap,12 ffi::{CStr, CString},13 fs::File,14 io::Read,15 path::PathBuf,16 rc::Rc,17};1819#[no_mangle]20#[cfg(target = "wasm32-wasi")]21pub extern "C" fn _start() {}2223#[no_mangle]24pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {25 b"v0.16.0\0"26}2728#[derive(Default)]29struct NativeImportResolver {30 library_paths: RefCell<Vec<PathBuf>>,31}32impl NativeImportResolver {33 fn add_jpath(&self, path: PathBuf) {34 self.library_paths.borrow_mut().push(path);35 }36}37impl ImportResolver for NativeImportResolver {38 fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {39 let mut new_path = from.clone();40 new_path.push(path);41 if new_path.exists() {42 Ok(Rc::new(new_path))43 } else {44 for library_path in self.library_paths.borrow().iter() {45 let mut cloned = library_path.clone();46 cloned.push(path);47 if cloned.exists() {48 return Ok(Rc::new(cloned));49 }50 }51 create_error_result(Error::ImportFileNotFound(from.clone(), path.clone()))52 }53 }54 fn load_file_contents(&self, id: &PathBuf) -> Result<Rc<str>> {55 let mut file =56 File::open(id).map_err(|_e| create_error(Error::ResolvedFileNotFound(id.clone())))?;57 let mut out = String::new();58 file.read_to_string(&mut out)59 .map_err(|_e| create_error(Error::ImportBadFileUtf8(id.clone())))?;60 Ok(out.into())61 }62 unsafe fn as_any(&self) -> &dyn Any {63 self64 }65}6667#[no_mangle]68pub extern "C" fn jsonnet_make() -> Box<EvaluationState> {69 let state = EvaluationState::default();70 state.with_stdlib();71 state.set_import_resolver(Box::new(NativeImportResolver::default()));72 Box::new(state)73}7475#[no_mangle]76pub extern "C" fn jsonnet_max_stack(vm: &EvaluationState, v: c_uint) {77 vm.set_max_stack(v as usize);78}7980// jrsonnet currently have no GC, so these functions is no-op81#[no_mangle]82pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}83#[no_mangle]84pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}8586// TODO87#[no_mangle]88pub extern "C" fn jsonnet_string_output(_vm: &EvaluationState, _v: c_int) {89 todo!()90}9192#[no_mangle]93pub extern "C" fn jsonnet_json_extract_string(_vm: &EvaluationState, v: &Val) -> *mut c_char {94 match v.unwrap_if_lazy().unwrap() {95 Val::Str(s) => CString::new(&*s as &str).unwrap().into_raw(),96 _ => std::ptr::null_mut(),97 }98}99#[no_mangle]100pub extern "C" fn jsonnet_json_extract_number(101 _vm: &EvaluationState,102 v: &Val,103 out: &mut c_double,104) -> c_int {105 match v.unwrap_if_lazy().unwrap() {106 Val::Num(n) => {107 *out = n;108 1109 }110 _ => 0,111 }112}113#[no_mangle]114pub extern "C" fn jsonnet_json_extract_bool(_vm: &EvaluationState, v: &Val) -> c_int {115 match v.unwrap_if_lazy().unwrap() {116 Val::Bool(false) => 0,117 Val::Bool(true) => 1,118 _ => 2,119 }120}121#[no_mangle]122pub extern "C" fn jsonnet_json_extract_null(_vm: &EvaluationState, v: &Val) -> c_int {123 match v.unwrap_if_lazy().unwrap() {124 Val::Null => 1,125 _ => 0,126 }127}128129/// # Safety130///131/// This function is safe, if received v is a pointer to normal C string132#[no_mangle]133pub unsafe extern "C" fn jsonnet_json_make_string(134 _vm: &EvaluationState,135 v: *const c_char,136) -> Box<Val> {137 let cstr = CStr::from_ptr(v);138 let str = cstr.to_str().unwrap();139 Box::new(Val::Str(str.into()))140}141142#[no_mangle]143pub extern "C" fn jsonnet_json_make_number(_vm: &EvaluationState, v: c_double) -> Box<Val> {144 Box::new(Val::Num(v))145}146147#[no_mangle]148pub extern "C" fn jsonnet_json_make_bool(_vm: &EvaluationState, v: c_int) -> Box<Val> {149 assert!(v == 0 || v == 1);150 Box::new(Val::Bool(v == 1))151}152153#[no_mangle]154pub extern "C" fn jsonnet_json_make_null(_vm: &EvaluationState) -> Box<Val> {155 Box::new(Val::Null)156}157158#[no_mangle]159pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> Box<Val> {160 Box::new(Val::Arr(Rc::new(Vec::new())))161}162163#[no_mangle]164pub extern "C" fn jsonnet_json_array_append(_vm: &EvaluationState, arr: &mut Val, val: &Val) {165 match arr {166 Val::Arr(old) => {167 // TODO: Mutate array, instead of recreating them168 let mut new = Vec::new();169 new.extend(old.iter().cloned());170 new.push(val.clone());171 *arr = Val::Arr(Rc::new(new));172 }173 _ => panic!("should receive array"),174 }175}176177#[no_mangle]178pub extern "C" fn jsonnet_json_make_object(_vm: &EvaluationState) -> Box<Val> {179 Box::new(Val::Obj(ObjValue::new_empty()))180}181182/// # Safety183///184/// This function is safe if passed name is ok185#[no_mangle]186pub unsafe extern "C" fn jsonnet_json_object_append(187 _vm: &EvaluationState,188 obj: &mut Val,189 name: *const c_char,190 val: &Val,191) {192 match obj {193 Val::Obj(old) => {194 let mut new = HashMap::new();195 new.insert(196 CStr::from_ptr(name).to_str().unwrap().into(),197 ObjMember {198 add: false,199 visibility: Visibility::Normal,200 invoke: LazyBinding::Bound(LazyVal::new_resolved(val.clone())),201 },202 );203 let new_obj = ObjValue::new(Some(old.clone()), Rc::new(new));204 *obj = Val::Obj(new_obj);205 }206 _ => panic!("should receive array"),207 }208}209210/// # Safety211///212/// This function is most definitely broken, but it works somehow, see TODO inside213#[no_mangle]214pub unsafe extern "C" fn jsonnet_realloc(215 _vm: &EvaluationState,216 buf: *mut u8,217 sz: usize,218) -> *mut u8 {219 if buf.is_null() {220 assert!(sz != 0);221 return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());222 }223 // TODO: Somehow store size of allocation, because its real size is probally not 16 :D224 // OR (Alternative way of fixing this TODO)225 // TODO: Standard allocator uses malloc, and it doesn't uses allocation size,226 // TODO: so it should work in normal cases. Maybe force allocator for this library?227 let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();228 if sz == 0 {229 std::alloc::dealloc(buf, old_layout);230 return std::ptr::null_mut();231 }232 std::alloc::realloc(buf, old_layout, sz)233}234235#[no_mangle]236#[allow(clippy::boxed_local)]237pub extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, _v: Box<Val>) {}238239#[no_mangle]240pub extern "C" fn jsonnet_import_callback() {241 todo!()242}243#[no_mangle]244pub extern "C" fn jsonnet_native_callback() {245 todo!()246}247#[no_mangle]248pub extern "C" fn jsonnet_ext_var() {249 todo!()250}251#[no_mangle]252pub extern "C" fn jsonnet_ext_code() {253 todo!()254}255#[no_mangle]256pub extern "C" fn jsonnet_tla_var() {257 todo!()258}259#[no_mangle]260pub extern "C" fn jsonnet_tla_code() {261 todo!()262}263#[no_mangle]264pub extern "C" fn jsonnet_max_trace() {265 todo!()266}267268/// # Safety269///270/// This function is safe, if received v is a pointer to normal C string271#[no_mangle]272pub unsafe extern "C" fn jsonnet_jpath_add(vm: &EvaluationState, v: *const c_char) {273 let cstr = CStr::from_ptr(v);274 let path = PathBuf::from(cstr.to_str().unwrap());275 let any_resolver = vm.import_resolver();276 let resolver = any_resolver277 .as_any()278 .downcast_ref::<NativeImportResolver>()279 .unwrap();280 resolver.add_jpath(path);281}282283/// # Safety284///285/// This function is safe, if received v is a pointer to normal C string286#[no_mangle]287pub unsafe extern "C" fn jsonnet_evaluate_file(288 vm: &EvaluationState,289 filename: *const c_char,290 error: &mut c_int,291) -> *const c_char {292 vm.run_in_state(|| {293 use std::fmt::Write;294 let filename = CStr::from_ptr(filename);295 match vm.evaluate_file_to_json(&PathBuf::from(filename.to_str().unwrap())) {296 Ok(v) => {297 *error = 0;298 CString::new(&*v as &str).unwrap().into_raw()299 }300 Err(e) => {301 *error = 1;302 let mut out = String::new();303 writeln!(out, "{:?}", e.0).unwrap();304 for i in (e.1).0.iter() {305 writeln!(out, "{:?}", i.0).unwrap();306 }307 CString::new(&out as &str).unwrap().into_raw()308 }309 }310 })311}312313/// # Safety314///315/// This function is safe, if received v is a pointer to normal C string316#[no_mangle]317pub unsafe extern "C" fn jsonnet_evaluate_snippet(318 vm: &EvaluationState,319 filename: *const c_char,320 snippet: *const c_char,321 error: &mut c_int,322) -> *const c_char {323 vm.run_in_state(|| {324 use std::fmt::Write;325 let filename = CStr::from_ptr(filename);326 let snippet = CStr::from_ptr(snippet);327 match vm.evaluate_snippet_to_json(328 &PathBuf::from(filename.to_str().unwrap()),329 &snippet.to_str().unwrap(),330 ) {331 Ok(v) => {332 *error = 0;333 CString::new(&*v as &str).unwrap().into_raw()334 }335 Err(e) => {336 *error = 1;337 let mut out = String::new();338 writeln!(out, "{:?}", e.0).unwrap();339 for i in (e.1).0.iter() {340 writeln!(out, "{:?} ---- {}", i.0, i.1).unwrap();341 }342 CString::new(&out as &str).unwrap().into_raw()343 }344 }345 })346}347348#[no_mangle]349pub extern "C" fn jsonnet_evaluate_file_multi() {350 todo!()351}352#[no_mangle]353pub extern "C" fn jsonnet_evaluate_snippet_multi() {354 todo!()355}356#[no_mangle]357pub extern "C" fn jsonnet_evaluate_file_stream() {358 todo!()359}360#[no_mangle]361pub extern "C" fn jsonnet_evaluate_snippet_stream() {362 todo!()363}364365#[no_mangle]366#[allow(clippy::boxed_local)]367pub extern "C" fn jsonnet_destroy(_vm: Box<EvaluationState>) {}crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate.rs
@@ -9,10 +9,7 @@
ForSpecData, IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, UnaryOpType,
Visibility,
};
-use std::{
- collections::{BTreeMap, HashMap},
- rc::Rc,
-};
+use std::{collections::HashMap, rc::Rc};
pub fn evaluate_binding(b: &BindSpec, context_creator: ContextCreator) -> (Rc<str>, LazyBinding) {
let b = b.clone();
@@ -242,7 +239,7 @@
new_bindings.fill(bindings);
}
- let mut new_members = BTreeMap::new();
+ let mut new_members = HashMap::new();
for member in members.iter() {
match member {
Member::Field(FieldMember {
@@ -317,7 +314,7 @@
ObjBody::MemberList(members) => evaluate_member_list_object(context, &members)?,
ObjBody::ObjComp(obj) => {
let future_this = FutureObjValue::new();
- let mut new_members = BTreeMap::new();
+ let mut new_members = HashMap::new();
for (k, v) in evaluate_comp(
context.clone(),
&|ctx| {
@@ -450,13 +447,13 @@
0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
1, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
], {
- Ok(Val::Arr(Rc::new(
- obj.fields_visibility()
- .into_iter()
- .filter(|(_k, v)| *v || inc_hidden)
- .map(|(k, _v)| Val::Str(k))
- .collect(),
- )))
+ let mut out = obj.fields_visibility()
+ .into_iter()
+ .filter(|(_k, v)| *v || inc_hidden)
+ .map(|(k, _v)|k)
+ .collect::<Vec<_>>();
+ out.sort();
+ Ok(Val::Arr(Rc::new(out.into_iter().map(Val::Str).collect())))
}))?
}
// object, field, includeHidden
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -1,12 +1,7 @@
use crate::{evaluate_add_op, LazyBinding, Result, Val};
use indexmap::IndexMap;
-use jrsonnet_parser::Visibility;
-use std::{
- cell::RefCell,
- collections::{BTreeMap, HashMap},
- fmt::Debug,
- rc::Rc,
-};
+use jrsonnet_parser::{ExprLocation, Visibility};
+use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
#[derive(Debug)]
pub struct ObjMember {
@@ -18,7 +13,7 @@
#[derive(Debug)]
pub struct ObjValueInternals {
super_obj: Option<ObjValue>,
- this_entries: Rc<BTreeMap<Rc<str>, ObjMember>>,
+ this_entries: Rc<HashMap<Rc<str>, ObjMember>>,
value_cache: RefCell<HashMap<Rc<str>, Val>>,
}
#[derive(Clone)]
@@ -44,7 +39,7 @@
impl ObjValue {
pub fn new(
super_obj: Option<ObjValue>,
- this_entries: Rc<BTreeMap<Rc<str>, ObjMember>>,
+ this_entries: Rc<HashMap<Rc<str>, ObjMember>>,
) -> ObjValue {
ObjValue(Rc::new(ObjValueInternals {
super_obj,
@@ -53,7 +48,7 @@
}))
}
pub fn new_empty() -> ObjValue {
- Self::new(None, Rc::new(BTreeMap::new()))
+ Self::new(None, Rc::new(HashMap::new()))
}
pub fn with_super(&self, super_obj: ObjValue) -> ObjValue {
match &self.0.super_obj {
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -246,7 +246,8 @@
}
Val::Obj(obj) => {
buf.push_str("{\n");
- let fields = obj.visible_fields();
+ let mut fields = obj.visible_fields();
+ fields.sort();
if !fields.is_empty() {
let old_len = cur_padding.len();
cur_padding.push_str(padding);