difftreelog
refactor reduce callsite boilerplate
in: master
38 files changed
bindings/jsonnet/src/import.rsdiffbeforeafterboth117 ctx: *mut c_void,117 ctx: *mut c_void,118) {118) {119 vm.state119 vm.state.set_import_resolver(CallbackImportResolver {120 .set_import_resolver(Box::new(CallbackImportResolver {121 cb,120 cb,122 ctx,121 ctx,123 out: RefCell::new(HashMap::new()),122 out: RefCell::new(HashMap::new()),124 }))123 })125}124}126125127/// # Safety126/// # Safetybindings/jsonnet/src/native.rsdiffbeforeafterboth7use jrsonnet_evaluator::{7use jrsonnet_evaluator::{8 error::{Error, ErrorKind},8 error::{Error, ErrorKind},9 function::builtin::{NativeCallback, NativeCallbackHandler},9 function::builtin::{NativeCallback, NativeCallbackHandler},10 tb,11 typed::Typed,10 typed::Typed,12 IStr, Val,11 IStr, Val,13};12};14use jrsonnet_gcmodule::Cc;151316use crate::VM;14use crate::VM;1715102 .add_native(100 .add_native(103 name,101 name,104 #[allow(deprecated)]102 #[allow(deprecated)]105 Cc::new(tb!(NativeCallback::new(103 NativeCallback::new(params, JsonnetNativeCallbackHandler { ctx, cb }),106 params,107 tb!(JsonnetNativeCallbackHandler { ctx, cb }),108 ))),109 )104 )110}105}111106bindings/jsonnet/src/val_extract.rsdiffbeforeafterboth13#[no_mangle]13#[no_mangle]14pub extern "C" fn jsonnet_json_extract_string(_vm: &VM, v: &Val) -> *mut c_char {14pub extern "C" fn jsonnet_json_extract_string(_vm: &VM, v: &Val) -> *mut c_char {15 match v {15 match v {16 Val::Str(s) => CString::new(s as &str).unwrap().into_raw(),16 Val::Str(s) => {17 let s = s.clone().into_flat();18 CString::new(s.as_str()).unwrap().into_raw()19 }17 _ => std::ptr::null_mut(),20 _ => std::ptr::null_mut(),18 }21 }19}22}bindings/jsonnet/src/val_make.rsdiffbeforeafterboth6};6};778use jrsonnet_evaluator::{val::ArrValue, ObjValue, Val};8use jrsonnet_evaluator::{9use jrsonnet_gcmodule::Cc;9 val::{ArrValue, StrValue},10 ObjValue, Val,11};101211use crate::VM;13use crate::VM;19pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &VM, val: *const c_char) -> *mut Val {21pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &VM, val: *const c_char) -> *mut Val {20 let val = CStr::from_ptr(val);22 let val = CStr::from_ptr(val);21 let val = val.to_str().expect("string is not utf-8");23 let val = val.to_str().expect("string is not utf-8");22 Box::into_raw(Box::new(Val::Str(val.into())))24 Box::into_raw(Box::new(Val::Str(StrValue::Flat(val.into()))))23}25}242625/// Convert the given double to a `JsonnetJsonValue`.27/// Convert the given double to a `JsonnetJsonValue`.46/// Assign elements with [`jsonnet_json_array_append`].48/// Assign elements with [`jsonnet_json_array_append`].47#[no_mangle]49#[no_mangle]48pub extern "C" fn jsonnet_json_make_array(_vm: &VM) -> *mut Val {50pub extern "C" fn jsonnet_json_make_array(_vm: &VM) -> *mut Val {49 Box::into_raw(Box::new(Val::Arr(ArrValue::eager(Cc::new(Vec::new())))))51 Box::into_raw(Box::new(Val::Arr(ArrValue::eager(Vec::new()))))50}52}515352/// Make a `JsonnetJsonValue` representing an object.54/// Make a `JsonnetJsonValue` representing an object.crates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth54 library_paths.extend(env::split_paths(path.as_os_str()));54 library_paths.extend(env::split_paths(path.as_os_str()));55 }55 }565657 s.set_import_resolver(Box::new(FileImportResolver::new(library_paths)));57 s.set_import_resolver(FileImportResolver::new(library_paths));585859 set_stack_depth_limit(self.max_stack);59 set_stack_depth_limit(self.max_stack);60 Ok(())60 Ok(())crates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth55 Self::Lazy(LazyArray(thunks))55 Self::Lazy(LazyArray(thunks))56 }56 }575758 pub fn eager(values: Cc<Vec<Val>>) -> Self {58 pub fn eager(values: Vec<Val>) -> Self {59 Self::Eager(EagerArray(values))59 Self::Eager(EagerArray(Cc::new(values)))60 }60 }616162 pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {62 pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {81 out.push(i);81 out.push(i);82 };82 };83 }83 }84 Ok(Self::eager(Cc::new(out)))84 Ok(Self::eager(out))85 }85 }868687 pub fn extended(a: ArrValue, b: ArrValue) -> Self {87 pub fn extended(a: ArrValue, b: ArrValue) -> Self {98 let mut out = Vec::with_capacity(a.len() + b.len());98 let mut out = Vec::with_capacity(a.len() + b.len());99 out.extend(a);99 out.extend(a);100 out.extend(b);100 out.extend(b);101 Self::eager(Cc::new(out))101 Self::eager(out)102 } else {102 } else {103 let mut out = Vec::with_capacity(a.len() + b.len());103 let mut out = Vec::with_capacity(a.len() + b.len());104 out.extend(a.iter_lazy());104 out.extend(a.iter_lazy());235}235}236impl From<Vec<Val>> for ArrValue {236impl From<Vec<Val>> for ArrValue {237 fn from(value: Vec<Val>) -> Self {237 fn from(value: Vec<Val>) -> Self {238 Self::eager(Cc::new(value))238 Self::eager(value)239 }239 }240}240}241impl From<Vec<Thunk<Val>>> for ArrValue {241impl From<Vec<Thunk<Val>>> for ArrValue {242 fn from(value: Vec<Thunk<Val>>) -> Self {242 fn from(value: Vec<Thunk<Val>>) -> Self {243 Self::lazy(Cc::new(value))243 Self::lazy(Cc::new(value))244 }244 }245}245}246impl FromIterator<Val> for ArrValue {247 fn from_iter<T: IntoIterator<Item = Val>>(iter: T) -> Self {248 Self::eager(iter.into_iter().collect())249 }250}246251247#[cfg(target_pointer_width = "64")]252#[cfg(target_pointer_width = "64")]248static_assertions::assert_eq_size!(ArrValue, [u8; 16]);253static_assertions::assert_eq_size!(ArrValue, [u8; 16]);crates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth7use jrsonnet_interner::IBytes;7use jrsonnet_interner::IBytes;8use jrsonnet_parser::LocExpr;8use jrsonnet_parser::LocExpr;9910use super::{ArrValue, ArrayLikeIter};10use super::ArrValue;11use crate::{11use crate::{12 error::ErrorKind::InfiniteRecursionDetected, evaluate, function::FuncVal, tb, typed::Any,12 error::ErrorKind::InfiniteRecursionDetected, evaluate, function::FuncVal, val::ThunkValue,13 val::ThunkValue, Context, Error, Result, Thunk, Val,13 Context, Error, Result, Thunk, Val,14};14};151575 }75 }767677 #[cfg(not(feature = "nightly"))]77 #[cfg(not(feature = "nightly"))]78 fn iter_cheap(&self) -> Option<impl ArrayLikeIter<Val> + '_> {78 fn iter_cheap(&self) -> Option<impl crate::arr::ArrayLikeIter<Val> + '_> {79 Some(79 Some(80 self.inner80 self.inner81 .iter_cheap()?81 .iter_cheap()?300 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}300 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}301 };301 };302302303 Some(Thunk::new(tb!(ArrayElement {303 Some(Thunk::new(ArrayElement {304 arr_thunk: self.clone(),304 arr_thunk: self.clone(),305 index,305 index,306 })))306 }))307 }307 }308 fn get_cheap(&self, _index: usize) -> Option<Val> {308 fn get_cheap(&self, _index: usize) -> Option<Val> {309 None309 None748 .get(index)748 .get(index)749 .transpose()749 .transpose()750 .expect("index checked")750 .expect("index checked")751 .and_then(|r| self.0.mapper.evaluate_simple(&(Any(r),)));751 .and_then(|r| self.0.mapper.evaluate_simple(&(r,)));752752753 let new_value = match val {753 let new_value = match val {754 Ok(v) => v,754 Ok(v) => v,787 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}787 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}788 };788 };789789790 Some(Thunk::new(tb!(ArrayElement {790 Some(Thunk::new(ArrayElement {791 arr_thunk: self.clone(),791 arr_thunk: self.clone(),792 index,792 index,793 })))793 }))794 }794 }795795796 fn get_cheap(&self, _index: usize) -> Option<Val> {796 fn get_cheap(&self, _index: usize) -> Option<Val> {crates/jrsonnet-evaluator/src/async_import.rsdiffbeforeafterboth294 path: handler.resolve(path.as_ref()).await?,294 path: handler.resolve(path.as_ref()).await?,295 parse: true,295 parse: true,296 }];296 }];297 // let mut resolved = HashMap::<(SourcePath, IStr), (SourcePath, bool)>::new();298 while let Some(job) = queue.pop() {297 while let Some(job) = queue.pop() {299 match job {298 match job {300 Job::LoadFile { path, parse } => {299 Job::LoadFile { path, parse } => {349 }348 }350 }349 }351 }350 }352 s.set_import_resolver(Box::new(ResolvedImportResolver {351 s.set_import_resolver(ResolvedImportResolver {353 resolved: RefCell::new(resolved),352 resolved: RefCell::new(resolved),354 }));353 });355 Ok(())354 Ok(())356}355}357356crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth39 .expect("used state from dummy context")39 .expect("used state from dummy context")40 }40 }414142 pub fn dollar(&self) -> &Option<ObjValue> {42 pub fn dollar(&self) -> Option<&ObjValue> {43 &self.0.dollar43 self.0.dollar.as_ref()44 }44 }454546 pub fn this(&self) -> &Option<ObjValue> {46 pub fn this(&self) -> Option<&ObjValue> {47 &self.0.this47 self.0.this.as_ref()48 }48 }494950 pub fn super_obj(&self) -> &Option<ObjValue> {50 pub fn super_obj(&self) -> Option<&ObjValue> {51 &self.0.sup51 self.0.sup.as_ref()52 }52 }535354 #[cfg(not(feature = "friendly-errors"))]54 #[cfg(not(feature = "friendly-errors"))]131 }131 }132}132}133134// impl Default for Context {135// fn default() -> Self {136// Self::new()137// }138// }139133140impl PartialEq for Context {134impl PartialEq for Context {141 fn eq(&self, other: &Self) -> bool {135 fn eq(&self, other: &Self) -> bool {crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth6 error::{ErrorKind::*, Result},6 error::{ErrorKind::*, Result},7 evaluate, evaluate_method, evaluate_named,7 evaluate, evaluate_method, evaluate_named,8 gc::GcHashMap,8 gc::GcHashMap,9 tb, throw,9 throw,10 val::ThunkValue,10 val::ThunkValue,11 Context, Pending, Thunk, Val,11 Context, Pending, Thunk, Val,12};12};63 }63 }64 }64 }656566 let full = Thunk::new(tb!(DataThunk {66 let full = Thunk::new(DataThunk {67 min_len: start.len() + end.len(),67 min_len: start.len() + end.len(),68 has_rest: rest.is_some(),68 has_rest: rest.is_some(),69 parent,69 parent,70 }));70 });717172 {72 {73 #[derive(Trace)]73 #[derive(Trace)]86 for (i, d) in start.iter().enumerate() {86 for (i, d) in start.iter().enumerate() {87 destruct(87 destruct(88 d,88 d,89 Thunk::new(tb!(BaseThunk {89 Thunk::new(BaseThunk {90 full: full.clone(),90 full: full.clone(),91 index: i,91 index: i,92 })),92 }),93 fctx.clone(),93 fctx.clone(),94 new_bindings,94 new_bindings,95 )?;95 )?;119119120 destruct(120 destruct(121 &Destruct::Full(v.clone()),121 &Destruct::Full(v.clone()),122 Thunk::new(tb!(RestThunk {122 Thunk::new(RestThunk {123 full: full.clone(),123 full: full.clone(),124 start: start.len(),124 start: start.len(),125 end: end.len(),125 end: end.len(),126 })),126 }),127 fctx.clone(),127 fctx.clone(),128 new_bindings,128 new_bindings,129 )?;129 )?;151 for (i, d) in end.iter().enumerate() {151 for (i, d) in end.iter().enumerate() {152 destruct(152 destruct(153 d,153 d,154 Thunk::new(tb!(EndThunk {154 Thunk::new(EndThunk {155 full: full.clone(),155 full: full.clone(),156 index: i,156 index: i,157 end: end.len(),157 end: end.len(),158 })),158 }),159 fctx.clone(),159 fctx.clone(),160 new_bindings,160 new_bindings,161 )?;161 )?;199 .filter(|f| f.2.is_none())199 .filter(|f| f.2.is_none())200 .map(|f| f.0.clone())200 .map(|f| f.0.clone())201 .collect();201 .collect();202 let full = Thunk::new(tb!(DataThunk {202 let full = Thunk::new(DataThunk {203 parent,203 parent,204 field_names,204 field_names,205 has_rest: rest.is_some()205 has_rest: rest.is_some(),206 }));206 });207207208 for (field, d, default) in fields {208 for (field, d, default) in fields {209 #[derive(Trace)]209 #[derive(Trace)]225 }225 }226 }226 }227 }227 }228 let value = Thunk::new(tb!(FieldThunk {228 let value = Thunk::new(FieldThunk {229 full: full.clone(),229 full: full.clone(),230 field: field.clone(),230 field: field.clone(),231 default: default.clone().map(|e| (fctx.clone(), e)),231 default: default.clone().map(|e| (fctx.clone(), e)),232 }));232 });233 if let Some(d) = d {233 if let Some(d) = d {234 destruct(d, value, fctx.clone(), new_bindings)?;234 destruct(d, value, fctx.clone(), new_bindings)?;235 } else {235 } else {268 )268 )269 }269 }270 }270 }271 let data = Thunk::new(tb!(EvaluateThunkValue {271 let data = Thunk::new(EvaluateThunkValue {272 name: into.name(),272 name: into.name(),273 fctx: fctx.clone(),273 fctx: fctx.clone(),274 expr: value.clone(),274 expr: value.clone(),275 }));275 });276 destruct(into, data, fctx, new_bindings)?;276 destruct(into, data, fctx, new_bindings)?;277 }277 }278 BindSpec::Function {278 BindSpec::Function {302302303 let old = new_bindings.insert(303 let old = new_bindings.insert(304 name.clone(),304 name.clone(),305 Thunk::new(tb!(MethodThunk {305 Thunk::new(MethodThunk {306 fctx,306 fctx,307 name: name.clone(),307 name: name.clone(),308 params: params.clone(),308 params: params.clone(),309 value: value.clone()309 value: value.clone(),310 })),310 }),311 );311 );312 if old.is_some() {312 if old.is_some() {313 throw!(DuplicateLocalVar(name.clone()))313 throw!(DuplicateLocalVar(name.clone()))crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth15 error::ErrorKind::*,15 error::ErrorKind::*,16 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},16 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},17 function::{CallLocation, FuncDesc, FuncVal},17 function::{CallLocation, FuncDesc, FuncVal},18 tb, throw,18 throw,19 typed::Typed,19 typed::Typed,20 val::{CachedUnbound, IndexableVal, StrValue, Thunk, ThunkValue},20 val::{CachedUnbound, IndexableVal, StrValue, Thunk, ThunkValue},21 Context, GcHashMap, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result, State,21 Context, GcHashMap, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result, State,45 if n.iter().any(|e| !is_trivial(e)) {45 if n.iter().any(|e| !is_trivial(e)) {46 return None;46 return None;47 }47 }48 Val::Arr(ArrValue::eager(Cc::new(48 Val::Arr(ArrValue::eager(49 n.iter()49 n.iter()50 .map(evaluate_trivial)50 .map(evaluate_trivial)51 .map(|e| e.expect("checked trivial"))51 .map(|e| e.expect("checked trivial"))52 .collect(),52 .collect(),53 )))53 ))54 }54 }55 Expr::Parened(e) => evaluate_trivial(e)?,55 Expr::Parened(e) => evaluate_trivial(e)?,56 _ => return None,56 _ => return None,136 let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());136 let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());137 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(Cc::new(vec![137 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(Cc::new(vec![138 Thunk::evaluated(Val::Str(StrValue::Flat(field.clone()))),138 Thunk::evaluated(Val::Str(StrValue::Flat(field.clone()))),139 Thunk::new(tb!(ObjectFieldThunk {139 Thunk::new(ObjectFieldThunk {140 field: field.clone(),140 field: field.clone(),141 obj: obj.clone(),141 obj: obj.clone(),142 })),142 }),143 ]))));143 ]))));144 destruct(var, value, fctx.clone(), &mut new_bindings)?;144 destruct(var, value, fctx.clone(), &mut new_bindings)?;145 let ctx = ctx145 let ctx = ctx180 }180 }181181182 let ctx = self.fctx.unwrap();182 let ctx = self.fctx.unwrap();183 let new_dollar = ctx.dollar().clone().or_else(|| this.clone());183 let new_dollar = ctx.dollar().cloned().or_else(|| this.clone());184184185 let ctx = ctx185 let ctx = ctx186 .extend(new_bindings, new_dollar, sup, this)186 .extend(new_bindings, new_dollar, sup, this)230 .with_add(*plus)230 .with_add(*plus)231 .with_visibility(*visibility)231 .with_visibility(*visibility)232 .with_location(value.1.clone())232 .with_location(value.1.clone())233 .bindable(tb!(UnboundValue {233 .bindable(UnboundValue {234 uctx,234 uctx,235 value: value.clone(),235 value: value.clone(),236 name,236 name,237 }))?;237 })?;238 }238 }239 FieldMember {239 FieldMember {240 params: Some(params),240 params: Some(params),265 .member(name.clone())265 .member(name.clone())266 .with_visibility(*visibility)266 .with_visibility(*visibility)267 .with_location(value.1.clone())267 .with_location(value.1.clone())268 .bindable(tb!(UnboundMethod {268 .bindable(UnboundMethod {269 uctx,269 uctx,270 value: value.clone(),270 value: value.clone(),271 params: params.clone(),271 params: params.clone(),272 name,272 name,273 }))?;273 })?;274 }274 }275 }275 }276 Ok(())276 Ok(())311 evaluate_assert(ctx, &self.assert)311 evaluate_assert(ctx, &self.assert)312 }312 }313 }313 }314 builder.assert(tb!(ObjectAssert {314 builder.assert(ObjectAssert {315 uctx: uctx.clone(),315 uctx: uctx.clone(),316 assert: stmt.clone(),316 assert: stmt.clone(),317 }));317 });318 }318 }319 Member::BindStmt(_) => {319 Member::BindStmt(_) => {320 // Already handled320 // Already handled420 let LocExpr(expr, loc) = expr;420 let LocExpr(expr, loc) = expr;421 Ok(match &**expr {421 Ok(match &**expr {422 Literal(LiteralType::This) => {422 Literal(LiteralType::This) => {423 Val::Obj(ctx.this().clone().ok_or(CantUseSelfOutsideOfObject)?)423 Val::Obj(ctx.this().ok_or(CantUseSelfOutsideOfObject)?.clone())424 }424 }425 Literal(LiteralType::Super) => Val::Obj(425 Literal(LiteralType::Super) => Val::Obj(426 ctx.super_obj().clone().ok_or(NoSuperFound)?.with_this(426 ctx.super_obj().ok_or(NoSuperFound)?.with_this(427 ctx.this()427 ctx.this()428 .clone()428 .expect("if super exists - then this should too")429 .expect("if super exists - then this should too"),429 .clone(),430 ),430 ),431 ),431 ),432 Literal(LiteralType::Dollar) => {432 Literal(LiteralType::Dollar) => {433 Val::Obj(ctx.dollar().clone().ok_or(NoTopLevelObjectFound)?)433 Val::Obj(ctx.dollar().ok_or(NoTopLevelObjectFound)?.clone())434 }434 }435 Literal(LiteralType::True) => Val::Bool(true),435 Literal(LiteralType::True) => Val::Bool(true),436 Literal(LiteralType::False) => Val::Bool(false),436 Literal(LiteralType::False) => Val::Bool(false),455 ))455 ))456 };456 };457 ctx.super_obj()457 ctx.super_obj()458 .clone()459 .expect("no super found")458 .expect("no super found")460 .get_for(name.into_flat(), ctx.this().clone().expect("no this found"))?459 .get_for(name.into_flat(), ctx.this().expect("no this found").clone())?461 .expect("value not found")460 .expect("value not found")462 }461 }463 Index(value, index) => match (evaluate(ctx.clone(), value)?, evaluate(ctx, index)?) {462 Index(value, index) => match (evaluate(ctx.clone(), value)?, evaluate(ctx, index)?) {563 evaluate(self.ctx, &self.item)562 evaluate(self.ctx, &self.item)564 }563 }565 }564 }566 Val::Arr(ArrValue::lazy(Cc::new(vec![Thunk::new(tb!(565 Val::Arr(ArrValue::lazy(Cc::new(vec![Thunk::new(ArrayElement {567 ArrayElement {568 ctx,566 ctx,569 item: items[0].clone(),567 item: items[0].clone(),570 }568 })])))571 ))])))572 } else {569 } else {573 Val::Arr(ArrValue::expr(ctx, items.iter().cloned()))570 Val::Arr(ArrValue::expr(ctx, items.iter().cloned()))574 }571 }579 out.push(evaluate(ctx, expr)?);576 out.push(evaluate(ctx, expr)?);580 Ok(())577 Ok(())581 })?;578 })?;582 Val::Arr(ArrValue::eager(Cc::new(out)))579 Val::Arr(ArrValue::eager(out))583 }580 }584 Obj(body) => Val::Obj(evaluate_object(ctx, body)?),581 Obj(body) => Val::Obj(evaluate_object(ctx, body)?),585 ObjExtend(a, b) => evaluate_add_op(582 ObjExtend(a, b) => evaluate_add_op(623 fn parse_idx<T: Typed>(620 fn parse_idx<T: Typed>(624 loc: CallLocation<'_>,621 loc: CallLocation<'_>,625 ctx: &Context,622 ctx: &Context,626 expr: &Option<LocExpr>,623 expr: Option<&LocExpr>,627 desc: &'static str,624 desc: &'static str,628 ) -> Result<Option<T>> {625 ) -> Result<Option<T>> {629 if let Some(value) = expr {626 if let Some(value) = expr {640 let indexable = evaluate(ctx.clone(), value)?;637 let indexable = evaluate(ctx.clone(), value)?;641 let loc = CallLocation::new(loc);638 let loc = CallLocation::new(loc);642639643 let start = parse_idx(loc, &ctx, &desc.start, "start")?;640 let start = parse_idx(loc, &ctx, desc.start.as_ref(), "start")?;644 let end = parse_idx(loc, &ctx, &desc.end, "end")?;641 let end = parse_idx(loc, &ctx, desc.end.as_ref(), "end")?;645 let step = parse_idx(loc, &ctx, &desc.step, "step")?;642 let step = parse_idx(loc, &ctx, desc.step.as_ref(), "step")?;646643647 IndexableVal::into_untyped(indexable.into_indexable()?.slice(start, end, step)?)?644 IndexableVal::into_untyped(indexable.into_indexable()?.slice(start, end, step)?)?648 }645 }crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth7 error::Result,7 error::Result,8 evaluate,8 evaluate,9 gc::GcHashMap,9 gc::GcHashMap,10 tb,11 typed::Typed,10 typed::Typed,12 val::{StrValue, ThunkValue},11 val::{StrValue, ThunkValue},13 Context, Thunk, Val,12 Context, Thunk, Val,37 Ok(if tailstrict {36 Ok(if tailstrict {38 Thunk::evaluated(evaluate(ctx, self)?)37 Thunk::evaluated(evaluate(ctx, self)?)39 } else {38 } else {40 Thunk::new(tb!(EvaluateThunk {39 Thunk::new(EvaluateThunk {41 ctx,40 ctx,42 expr: (*self).clone(),41 expr: (*self).clone(),43 }))42 })44 })43 })45 }44 }46}45}69 TlaArg::Code(code) => Ok(if tailstrict {68 TlaArg::Code(code) => Ok(if tailstrict {70 Thunk::evaluated(evaluate(ctx, code)?)69 Thunk::evaluated(evaluate(ctx, code)?)71 } else {70 } else {72 Thunk::new(tb!(EvaluateThunk {71 Thunk::new(EvaluateThunk {73 ctx,72 ctx,74 expr: code.clone(),73 expr: code.clone(),75 }))74 })76 }),75 }),77 TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),76 TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),78 }77 }128 }127 }129 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}128 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}130}129}131impl OptionalContext for Vec<Val> {}132130133impl ArgsLike for ArgsDesc {131impl ArgsLike for ArgsDesc {134 fn unnamed_len(&self) -> usize {132 fn unnamed_len(&self) -> usize {147 if tailstrict {145 if tailstrict {148 Thunk::evaluated(evaluate(ctx.clone(), arg)?)146 Thunk::evaluated(evaluate(ctx.clone(), arg)?)149 } else {147 } else {150 Thunk::new(tb!(EvaluateThunk {148 Thunk::new(EvaluateThunk {151 ctx: ctx.clone(),149 ctx: ctx.clone(),152 expr: arg.clone(),150 expr: arg.clone(),153 }))151 })154 },152 },155 )?;153 )?;156 }154 }169 if tailstrict {167 if tailstrict {170 Thunk::evaluated(evaluate(ctx.clone(), arg)?)168 Thunk::evaluated(evaluate(ctx.clone(), arg)?)171 } else {169 } else {172 Thunk::new(tb!(EvaluateThunk {170 Thunk::new(EvaluateThunk {173 ctx: ctx.clone(),171 ctx: ctx.clone(),174 expr: arg.clone(),172 expr: arg.clone(),175 }))173 })176 },174 },177 )?;175 )?;178 }176 }crates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth3use jrsonnet_gcmodule::Trace;3use jrsonnet_gcmodule::Trace;445use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};5use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};6use crate::{error::Result, gc::TraceBox, Context, Val};6use crate::{error::Result, gc::TraceBox, tb, Context, Val};778pub type BuiltinParamName = Cow<'static, str>;8pub type BuiltinParamName = Cow<'static, str>;9942}42}43impl NativeCallback {43impl NativeCallback {44 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]44 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]45 pub fn new(45 pub fn new(params: Vec<Cow<'static, str>>, handler: impl NativeCallbackHandler) -> Self {46 params: Vec<Cow<'static, str>>,47 handler: TraceBox<dyn NativeCallbackHandler>,48 ) -> Self {49 Self {46 Self {50 params: params47 params: params54 has_default: false,51 has_default: false,55 })52 })56 .collect(),53 .collect(),57 handler,54 handler: tb!(handler),58 }55 }59 }56 }60}57}crates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth12 native::NativeDesc,12 native::NativeDesc,13 parse::{parse_default_function_call, parse_function_call},13 parse::{parse_default_function_call, parse_function_call},14};14};15use crate::{15use crate::{evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result, Val};16 evaluate, evaluate_trivial, gc::TraceBox, typed::Any, Context, ContextBuilder, Result, Val,17};181619pub mod arglike;17pub mod arglike;116}114}117115118impl FuncVal {116impl FuncVal {117 pub fn builtin(builtin: impl Builtin) -> Self {118 Self::Builtin(Cc::new(tb!(builtin)))119 }119 /// Amount of non-default required arguments120 /// Amount of non-default required arguments120 pub fn params_len(&self) -> usize {121 pub fn params_len(&self) -> usize {121 match self {122 match self {148 Self::Id => {149 Self::Id => {149 #[allow(clippy::unnecessary_wraps)]150 #[allow(clippy::unnecessary_wraps)]150 #[builtin]151 #[builtin]151 const fn builtin_id(v: Any) -> Result<Any> {152 const fn builtin_id(x: Val) -> Val {152 Ok(v)153 x153 }154 }154 static ID: &builtin_id = &builtin_id {};155 static ID: &builtin_id = &builtin_id {};155156crates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth10 error::{ErrorKind::*, Result},10 error::{ErrorKind::*, Result},11 evaluate_named,11 evaluate_named,12 gc::GcHashMap,12 gc::GcHashMap,13 tb, throw,13 throw,14 val::ThunkValue,14 val::ThunkValue,15 Context, Pending, Thunk, Val,15 Context, Pending, Thunk, Val,16};16};100100101 destruct(101 destruct(102 ¶m.0,102 ¶m.0,103 Thunk::new(tb!(EvaluateNamedThunk {103 Thunk::new(EvaluateNamedThunk {104 ctx: fctx.clone(),104 ctx: fctx.clone(),105 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),105 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),106 value: param.1.clone().expect("default exists"),106 value: param.1.clone().expect("default exists"),107 })),107 }),108 fctx.clone(),108 fctx.clone(),109 &mut defaults,109 &mut defaults,110 )?;110 )?;250 if let Some(v) = ¶m.1 {250 if let Some(v) = ¶m.1 {251 destruct(251 destruct(252 ¶m.0.clone(),252 ¶m.0.clone(),253 Thunk::new(tb!(EvaluateNamedThunk {253 Thunk::new(EvaluateNamedThunk {254 ctx: fctx.clone(),254 ctx: fctx.clone(),255 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),255 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),256 value: v.clone(),256 value: v.clone(),257 })),257 }),258 fctx.clone(),258 fctx.clone(),259 &mut bindings,259 &mut bindings,260 )?;260 )?;261 } else {261 } else {262 destruct(262 destruct(263 ¶m.0,263 ¶m.0,264 Thunk::new(tb!(DependsOnUnbound(264 Thunk::new(DependsOnUnbound(265 param.0.name().unwrap_or_else(|| "<destruct>".into()),265 param.0.name().unwrap_or_else(|| "<destruct>".into()),266 params.clone()266 params.clone(),267 ))),267 )),268 fctx.clone(),268 fctx.clone(),269 &mut bindings,269 &mut bindings,270 )?;270 )?;crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth1use std::borrow::Cow;1use std::borrow::Cow;223use jrsonnet_gcmodule::Cc;4use serde::{3use serde::{5 de::Visitor,4 de::Visitor,6 ser::{Error, SerializeMap, SerializeSeq},5 ser::{Error, SerializeMap, SerializeSeq},117 out.push(val);116 out.push(val);118 }117 }119118120 Ok(Val::Arr(ArrValue::eager(Cc::new(out))))119 Ok(Val::Arr(ArrValue::eager(out)))121 }120 }122121123 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>122 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth433 pub fn import_resolver(&self) -> Ref<'_, dyn ImportResolver> {433 pub fn import_resolver(&self) -> Ref<'_, dyn ImportResolver> {434 Ref::map(self.settings(), |s| &*s.import_resolver)434 Ref::map(self.settings(), |s| &*s.import_resolver)435 }435 }436 pub fn set_import_resolver(&self, resolver: Box<dyn ImportResolver>) {436 pub fn set_import_resolver(&self, resolver: impl ImportResolver) {437 self.settings_mut().import_resolver = TraceBox(resolver);437 self.settings_mut().import_resolver = tb!(resolver);438 }438 }439 pub fn context_initializer(&self) -> Ref<'_, dyn ContextInitializer> {439 pub fn context_initializer(&self) -> Ref<'_, dyn ContextInitializer> {440 Ref::map(self.settings(), |s| &*s.context_initializer)440 Ref::map(self.settings(), |s| &*s.context_initializer)441 }441 }442 pub fn set_context_initializer(&self, initializer: impl ContextInitializer) {443 self.settings_mut().context_initializer = tb!(initializer);444 }442}445}443446crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth15 function::CallLocation,15 function::CallLocation,16 gc::{GcHashMap, GcHashSet, TraceBox},16 gc::{GcHashMap, GcHashSet, TraceBox},17 operator::evaluate_add_op,17 operator::evaluate_add_op,18 throw, MaybeUnbound, Result, State, Thunk, Unbound, Val,18 tb, throw, MaybeUnbound, Result, State, Thunk, Unbound, Val,19};19};202021#[cfg(not(feature = "exp-preserve-order"))]21#[cfg(not(feature = "exp-preserve-order"))]538 self538 self539 }539 }540540541 pub fn assert(&mut self, assertion: TraceBox<dyn ObjectAssertion>) -> &mut Self {541 pub fn assert(&mut self, assertion: impl ObjectAssertion + 'static) -> &mut Self {542 self.assertions.push(assertion);542 self.assertions.push(tb!(assertion));543 self543 self544 }544 }545 pub fn member(&mut self, name: IStr) -> ObjMemberBuilder<ValueBuilder<'_>> {545 pub fn member(&mut self, name: IStr) -> ObjMemberBuilder<ValueBuilder<'_>> {631 pub fn thunk(self, value: Thunk<Val>) -> Result<()> {631 pub fn thunk(self, value: Thunk<Val>) -> Result<()> {632 self.binding(MaybeUnbound::Bound(value))632 self.binding(MaybeUnbound::Bound(value))633 }633 }634 pub fn bindable(self, bindable: TraceBox<dyn Unbound<Bound = Val>>) -> Result<()> {634 pub fn bindable(self, bindable: impl Unbound<Bound = Val>) -> Result<()> {635 self.binding(MaybeUnbound::Unbound(Cc::new(bindable)))635 self.binding(MaybeUnbound::Unbound(Cc::new(tb!(bindable))))636 }636 }637 pub fn binding(self, binding: MaybeUnbound) -> Result<()> {637 pub fn binding(self, binding: MaybeUnbound) -> Result<()> {638 let (receiver, name, member) = self.build_member(binding);638 let (receiver, name, member) = self.build_member(binding);crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth30 fn into_untyped(typed: Self) -> Result<Val>;30 fn into_untyped(typed: Self) -> Result<Val>;31 fn from_untyped(untyped: Val) -> Result<Self>;31 fn from_untyped(untyped: Val) -> Result<Self>;3233 /// Hack to make builtins be able to return non-result values, and make macros able to convert those values to result34 /// This method returns identity in impl Typed for Result, and should not be overriden35 #[doc(hidden)]36 fn into_result(typed: Self) -> Result<Val> {37 let value = Self::into_untyped(typed)?;38 Ok(value)39 }32}40}334134const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS + 1)) - 1) as f64;42const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS + 1)) - 1) as f64;238 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);246 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);239247240 fn into_untyped(value: Self) -> Result<Val> {248 fn into_untyped(value: Self) -> Result<Val> {241 let mut o = Vec::with_capacity(value.len());242 for i in value {243 o.push(T::into_untyped(i)?);244 }245 Ok(Val::Arr(o.into()))249 Ok(Val::Arr(250 value251 .into_iter()252 .map(T::into_untyped)253 .collect::<Result<ArrValue>>()?,254 ))246 }255 }247256248 fn from_untyped(value: Val) -> Result<Self> {257 fn from_untyped(value: Val) -> Result<Self> {258 let Val::Arr(a) = value else {249 <Self as Typed>::TYPE.check(&value)?;259 <Self as Typed>::TYPE.check(&value)?;250 match value {251 Val::Arr(a) => {260 unreachable!("typecheck should fail")252 let mut o = Self::with_capacity(a.len());261 };253 for i in a.iter() {262 a.iter()254 o.push(T::from_untyped(i?)?);263 .map(|r| r.and_then(T::from_untyped))255 }256 Ok(o)257 }258 _ => unreachable!(),264 .collect::<Result<Vec<T>>>()259 }260 }265 }261}266}262263/// To be used in Vec<Any>264/// Regular Val can't be used here, because it has wrong `TryFrom::Error` type265#[derive(Clone)]266pub struct Any(pub Val);267267268impl Typed for Any {268impl Typed for Val {269 const TYPE: &'static ComplexValType = &ComplexValType::Any;269 const TYPE: &'static ComplexValType = &ComplexValType::Any;270270271 fn into_untyped(value: Self) -> Result<Val> {271 fn into_untyped(typed: Self) -> Result<Val> {272 Ok(value.0)272 Ok(typed)273 }273 }274275 fn from_untyped(value: Val) -> Result<Self> {274 fn from_untyped(untyped: Val) -> Result<Self> {276 Ok(Self(value))275 Ok(untyped)277 }276 }278}277}279278280/// Specialization, provides faster `TryFrom<VecVal>` for Val279// Hack281pub struct VecVal(pub Vec<Val>);280#[doc(hidden)]282283impl Typed for VecVal {281impl<T> Typed for Result<T>282where283 T: Typed,284{284 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);285 const TYPE: &'static ComplexValType = &ComplexValType::Any;285286286 fn into_untyped(value: Self) -> Result<Val> {287 fn into_untyped(_typed: Self) -> Result<Val> {287 Ok(Val::Arr(ArrValue::eager(Cc::new(value.0))))288 panic!("do not use this conversion")288 }289 }289290290 fn from_untyped(value: Val) -> Result<Self> {291 fn from_untyped(_untyped: Val) -> Result<Self> {291 <Self as Typed>::TYPE.check(&value)?;292 panic!("do not use this conversion")292 match value {293 }294293 Val::Arr(a) => Ok(Self(a.iter().collect::<Result<Vec<_>>>()?)),295 fn into_result(typed: Self) -> Result<Val> {294 _ => unreachable!(),296 typed.map(T::into_untyped)?295 }297 }296 }297}298}298299299/// Specialization300/// Specializationcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth15 function::FuncVal,15 function::FuncVal,16 gc::{GcHashMap, TraceBox},16 gc::{GcHashMap, TraceBox},17 manifest::{ManifestFormat, ToStringFormat},17 manifest::{ManifestFormat, ToStringFormat},18 throw,18 tb, throw,19 typed::BoundedUsize,19 typed::BoundedUsize,20 ObjValue, Result, Unbound, WeakObjValue,20 ObjValue, Result, Unbound, WeakObjValue,21};21};41 pub fn evaluated(val: T) -> Self {41 pub fn evaluated(val: T) -> Self {42 Self(Cc::new(RefCell::new(ThunkInner::Computed(val))))42 Self(Cc::new(RefCell::new(ThunkInner::Computed(val))))43 }43 }44 pub fn new(f: TraceBox<dyn ThunkValue<Output = T>>) -> Self {44 pub fn new(f: impl ThunkValue<Output = T> + 'static) -> Self {45 Self(Cc::new(RefCell::new(ThunkInner::Waiting(f))))45 Self(Cc::new(RefCell::new(ThunkInner::Waiting(tb!(f)))))46 }46 }47 pub fn errored(e: Error) -> Self {47 pub fn errored(e: Error) -> Self {48 Self(Cc::new(RefCell::new(ThunkInner::Errored(e))))48 Self(Cc::new(RefCell::new(ThunkInner::Errored(e))))crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth192 item: proc_macro::TokenStream,192 item: proc_macro::TokenStream,193) -> proc_macro::TokenStream {193) -> proc_macro::TokenStream {194 let attr = parse_macro_input!(attr as BuiltinAttrs);194 let attr = parse_macro_input!(attr as BuiltinAttrs);195 let item: ItemFn = parse_macro_input!(item);195 let item_fn = item.clone();196 let item_fn: ItemFn = parse_macro_input!(item_fn);196197197 match builtin_inner(attr, item) {198 match builtin_inner(attr, item_fn, item.into()) {198 Ok(v) => v.into(),199 Ok(v) => v.into(),199 Err(e) => e.into_compile_error().into(),200 Err(e) => e.into_compile_error().into(),200 }201 }201}202}202203203fn builtin_inner(attr: BuiltinAttrs, fun: ItemFn) -> syn::Result<TokenStream> {204fn builtin_inner(205 attr: BuiltinAttrs,206 fun: ItemFn,207 item: proc_macro2::TokenStream,208) -> syn::Result<TokenStream> {204 let ReturnType::Type(_, result) = &fun.sig.output else {209 let ReturnType::Type(_, result) = &fun.sig.output else {205 return Err(Error::new(210 return Err(Error::new(208 ))213 ))209 };214 };210211 let Some(args) = type_is_path(result, "Result") else {212 return Err(Error::new(result.span(), "return value should be result"));213214 };215 let PathArguments::AngleBracketed(params) = args else {216 return Err(Error::new(args.span(), "missing result generic"));217 };218 let generic_arg = params.args.iter().next().unwrap();219 // This argument must be a type:220 let GenericArgument::Type(result_inner) = generic_arg else {221 return Err(Error::new(222 generic_arg.span(),223 "option generic should be a type",224 ))225 };226215227 let name = fun.sig.ident.to_string();216 let name = fun.sig.ident.to_string();228 let args = fun217 let args = fun355 };344 };356345357 Ok(quote! {346 Ok(quote! {358 #fun347 #item348359 #[doc(hidden)]349 #[doc(hidden)]360 #[allow(non_camel_case_types)]350 #[allow(non_camel_case_types)]388 let parsed = parse_builtin_call(ctx.clone(), &PARAMS, args, false)?;378 let parsed = parse_builtin_call(ctx.clone(), &PARAMS, args, false)?;389379390 let result: #result = #name(#(#pass)*);380 let result: #result = #name(#(#pass)*);391 let result = result?;392 <#result_inner>::into_untyped(result)381 <_ as Typed>::into_result(result)393 }382 }394 }383 }395 };384 };crates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth2 error::{ErrorKind::RuntimeError, Result},2 error::{ErrorKind::RuntimeError, Result},3 function::{builtin, FuncVal},3 function::{builtin, FuncVal},4 throw,4 throw,5 typed::{Any, BoundedI32, BoundedUsize, Either2, NativeFn, Typed},5 typed::{BoundedI32, BoundedUsize, Either2, NativeFn, Typed},6 val::{equals, ArrValue, IndexableVal, StrValue},6 val::{equals, ArrValue, IndexableVal, StrValue},7 Either, IStr, Val,7 Either, IStr, Val,8};8};9use jrsonnet_gcmodule::Cc;10911#[builtin]10#[builtin]12pub fn builtin_make_array(sz: BoundedI32<0, { i32::MAX }>, func: FuncVal) -> Result<ArrValue> {11pub fn builtin_make_array(sz: BoundedI32<0, { i32::MAX }>, func: FuncVal) -> Result<ArrValue> {18 for _ in 0..*sz {17 for _ in 0..*sz {19 out.push(trivial.clone())18 out.push(trivial.clone())20 }19 }21 Ok(ArrValue::eager(Cc::new(out)))20 Ok(ArrValue::eager(out))22 } else {21 } else {23 Ok(ArrValue::range_exclusive(0, *sz).map(func))22 Ok(ArrValue::range_exclusive(0, *sz).map(func))24 }23 }25}24}262527#[builtin]26#[builtin]28pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Any> {27pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {29 Ok(Any(match what {28 Ok(match what {30 Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())),29 Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())),31 Either2::B(arr) => Val::Arr(30 Either2::B(arr) => Val::Arr(32 ArrValue::repeated(arr, count)31 ArrValue::repeated(arr, count)33 .ok_or_else(|| RuntimeError("repeated length overflow".into()))?,32 .ok_or_else(|| RuntimeError("repeated length overflow".into()))?,34 ),33 ),35 }))34 })36}35}373638#[builtin]37#[builtin]41 index: Option<BoundedUsize<0, { i32::MAX as usize }>>,40 index: Option<BoundedUsize<0, { i32::MAX as usize }>>,42 end: Option<BoundedUsize<0, { i32::MAX as usize }>>,41 end: Option<BoundedUsize<0, { i32::MAX as usize }>>,43 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,42 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,44) -> Result<Any> {43) -> Result<Val> {45 indexable.slice(index, end, step).map(Val::from).map(Any)44 indexable.slice(index, end, step).map(Val::from)46}45}474648#[builtin]47#[builtin]525153#[builtin]52#[builtin]54pub fn builtin_flatmap(53pub fn builtin_flatmap(55 func: NativeFn<((Either![String, Any],), Any)>,54 func: NativeFn<((Either![String, Val],), Val)>,56 arr: IndexableVal,55 arr: IndexableVal,57) -> Result<IndexableVal> {56) -> Result<IndexableVal> {58 use std::fmt::Write;57 use std::fmt::Write;59 match arr {58 match arr {60 IndexableVal::Str(str) => {59 IndexableVal::Str(str) => {61 let mut out = String::new();60 let mut out = String::new();62 for c in str.chars() {61 for c in str.chars() {63 match func(Either2::A(c.to_string()))?.0 {62 match func(Either2::A(c.to_string()))? {64 Val::Str(o) => write!(out, "{o}").unwrap(),63 Val::Str(o) => write!(out, "{o}").unwrap(),65 Val::Null => continue,64 Val::Null => continue,66 _ => throw!("in std.join all items should be strings"),65 _ => throw!("in std.join all items should be strings"),72 let mut out = Vec::new();71 let mut out = Vec::new();73 for el in a.iter() {72 for el in a.iter() {74 let el = el?;73 let el = el?;75 match func(Either2::B(Any(el)))?.0 {74 match func(Either2::B(el))? {76 Val::Arr(o) => {75 Val::Arr(o) => {77 for oe in o.iter() {76 for oe in o.iter() {78 out.push(oe?);77 out.push(oe?);898890#[builtin]89#[builtin]91pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {90pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {92 arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(Any(val.clone()),))?))91 arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(val.clone(),))?))93}92}949395#[builtin]94#[builtin]96pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {95pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {97 let mut acc = init.0;96 let mut acc = init;98 for i in arr.iter() {97 for i in arr.iter() {99 acc = func.evaluate_simple(&(Any(acc), Any(i?)))?;98 acc = func.evaluate_simple(&(acc, i?))?;100 }99 }101 Ok(Any(acc))100 Ok(acc)102}101}103102104#[builtin]103#[builtin]105pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {104pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {106 let mut acc = init.0;105 let mut acc = init;107 for i in arr.iter().rev() {106 for i in arr.iter().rev() {108 acc = func.evaluate_simple(&(Any(i?), Any(acc)))?;107 acc = func.evaluate_simple(&(i?, acc))?;109 }108 }110 Ok(Any(acc))109 Ok(acc)111}110}112111113#[builtin]112#[builtin]175}174}176175177#[builtin]176#[builtin]178pub fn builtin_reverse(value: ArrValue) -> Result<ArrValue> {177pub fn builtin_reverse(arr: ArrValue) -> ArrValue {179 Ok(value.reversed())178 arr.reversed()180}179}181180182#[builtin]181#[builtin]202}201}203202204#[builtin]203#[builtin]205pub fn builtin_member(arr: IndexableVal, x: Any) -> Result<bool> {204pub fn builtin_member(arr: IndexableVal, x: Val) -> Result<bool> {206 match arr {205 match arr {207 IndexableVal::Str(str) => {206 IndexableVal::Str(str) => {208 let x: IStr = IStr::from_untyped(x.0)?;207 let x: IStr = IStr::from_untyped(x)?;209 Ok(!x.is_empty() && str.contains(&*x))208 Ok(!x.is_empty() && str.contains(&*x))210 }209 }211 IndexableVal::Arr(a) => {210 IndexableVal::Arr(a) => {212 for item in a.iter() {211 for item in a.iter() {213 let item = item?;212 let item = item?;214 if equals(&item, &x.0)? {213 if equals(&item, &x)? {215 return Ok(true);214 return Ok(true);216 }215 }217 }216 }221}220}222221223#[builtin]222#[builtin]224pub fn builtin_count(arr: Vec<Any>, v: Any) -> Result<usize> {223pub fn builtin_count(arr: ArrValue, x: Val) -> Result<usize> {225 let mut count = 0;224 let mut count = 0;226 for item in &arr {225 for item in arr.iter() {227 if equals(&item.0, &v.0)? {226 if equals(&item?, &x)? {228 count += 1;227 count += 1;229 }228 }230 }229 }crates/jrsonnet-stdlib/src/encoding.rsdiffbeforeafterboth6};6};778#[builtin]8#[builtin]9pub fn builtin_encode_utf8(str: IStr) -> Result<IBytes> {9pub fn builtin_encode_utf8(str: IStr) -> IBytes {10 Ok(str.cast_bytes())10 str.cast_bytes()11}11}121213#[builtin]13#[builtin]18}18}191920#[builtin]20#[builtin]21pub fn builtin_base64(input: Either![IStr, IBytes]) -> Result<String> {21pub fn builtin_base64(input: Either![IStr, IBytes]) -> String {22 use Either2::*;22 use Either2::*;23 Ok(match input {23 match input {24 A(l) => base64::encode(l.as_bytes()),24 A(l) => base64::encode(l.as_bytes()),25 B(a) => base64::encode(a.as_slice()),25 B(a) => base64::encode(a.as_slice()),26 })26 }27}27}282829#[builtin]29#[builtin]30pub fn builtin_base64_decode_bytes(input: IStr) -> Result<IBytes> {30pub fn builtin_base64_decode_bytes(str: IStr) -> Result<IBytes> {31 Ok(base64::decode(input.as_bytes())31 Ok(base64::decode(str.as_bytes())32 .map_err(|_| RuntimeError("bad base64".into()))?32 .map_err(|_| RuntimeError("bad base64".into()))?33 .as_slice()33 .as_slice()34 .into())34 .into())35}35}363637#[builtin]37#[builtin]38pub fn builtin_base64_decode(input: IStr) -> Result<String> {38pub fn builtin_base64_decode(str: IStr) -> Result<String> {39 let bytes = base64::decode(input.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?;39 let bytes = base64::decode(str.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?;40 Ok(String::from_utf8(bytes).map_err(|_| RuntimeError("bad utf8".into()))?)40 Ok(String::from_utf8(bytes).map_err(|_| RuntimeError("bad utf8".into()))?)41}41}4242crates/jrsonnet-stdlib/src/hash.rsdiffbeforeafterboth1use jrsonnet_evaluator::{error::Result, function::builtin, IStr};1use jrsonnet_evaluator::{function::builtin, IStr};223#[builtin]3#[builtin]4pub fn builtin_md5(str: IStr) -> Result<String> {4pub fn builtin_md5(s: IStr) -> String {5 Ok(format!("{:x}", md5::compute(str.as_bytes())))5 format!("{:x}", md5::compute(s.as_bytes()))6}6}778#[cfg(feature = "exp-more-hashes")]8#[cfg(feature = "exp-more-hashes")]9#[builtin]9#[builtin]10pub fn builtin_sha256(str: IStr) -> Result<String> {10pub fn builtin_sha256(s: IStr) -> String {11 use sha2::digest::Digest;11 use sha2::digest::Digest;12 Ok(format!("{:?}", sha2::Sha256::digest(str.as_bytes())))12 format!("{:?}", sha2::Sha256::digest(s.as_bytes()))13}13}1414crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth155 builder155 builder156 .member("extVar".into())156 .member("extVar".into())157 .hide()157 .hide()158 .value(Val::Func(FuncVal::Builtin(Cc::new(tb!(builtin_ext_var {158 .value(Val::Func(FuncVal::builtin(builtin_ext_var {159 settings: settings.clone()159 settings: settings.clone(),160 })))))160 })))161 .expect("no conflict");161 .expect("no conflict");162 builder162 builder163 .member("native".into())163 .member("native".into())164 .hide()164 .hide()165 .value(Val::Func(FuncVal::Builtin(Cc::new(tb!(builtin_native {165 .value(Val::Func(FuncVal::builtin(builtin_native {166 settings: settings.clone()166 settings: settings.clone(),167 })))))167 })))168 .expect("no conflict");168 .expect("no conflict");169 builder169 builder170 .member("trace".into())170 .member("trace".into())171 .hide()171 .hide()172 .value(Val::Func(FuncVal::Builtin(Cc::new(tb!(builtin_trace {172 .value(Val::Func(FuncVal::builtin(builtin_trace { settings })))173 settings174 })))))175 .expect("no conflict");173 .expect("no conflict");176174177 builder175 builder301 .insert(name.into(), TlaArg::Code(parsed));299 .insert(name.into(), TlaArg::Code(parsed));302 Ok(())300 Ok(())303 }301 }304 pub fn add_native(&self, name: IStr, cb: Cc<TraceBox<dyn Builtin>>) {302 pub fn add_native(&self, name: IStr, cb: impl Builtin) {305 self.settings_mut().ext_natives.insert(name, cb);303 self.settings_mut()304 .ext_natives305 .insert(name, Cc::new(tb!(cb)));306 }306 }307}307}308impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {308impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {crates/jrsonnet-stdlib/src/manifest/mod.rsdiffbeforeafterboth5 error::Result,5 error::Result,6 function::builtin,6 function::builtin,7 manifest::{escape_string_json, JsonFormat},7 manifest::{escape_string_json, JsonFormat},8 typed::Any,9 IStr, ObjValue, Val,8 IStr, ObjValue, Val,10};9};11pub use toml::TomlFormat;10pub use toml::TomlFormat;181719#[builtin]18#[builtin]20pub fn builtin_manifest_json_ex(19pub fn builtin_manifest_json_ex(21 value: Any,20 value: Val,22 indent: IStr,21 indent: IStr,23 newline: Option<IStr>,22 newline: Option<IStr>,24 key_val_sep: Option<IStr>,23 key_val_sep: Option<IStr>,25 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,24 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,26) -> Result<String> {25) -> Result<String> {27 let newline = newline.as_deref().unwrap_or("\n");26 let newline = newline.as_deref().unwrap_or("\n");28 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");27 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");29 value.0.manifest(JsonFormat::std_to_json(28 value.manifest(JsonFormat::std_to_json(30 indent.to_string(),29 indent.to_string(),31 newline,30 newline,32 key_val_sep,31 key_val_sep,373638#[builtin]37#[builtin]39pub fn builtin_manifest_yaml_doc(38pub fn builtin_manifest_yaml_doc(40 value: Any,39 value: Val,41 indent_array_in_object: Option<bool>,40 indent_array_in_object: Option<bool>,42 quote_keys: Option<bool>,41 quote_keys: Option<bool>,43 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,42 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,44) -> Result<String> {43) -> Result<String> {45 value.0.manifest(YamlFormat::std_to_yaml(44 value.manifest(YamlFormat::std_to_yaml(46 indent_array_in_object.unwrap_or(false),45 indent_array_in_object.unwrap_or(false),47 quote_keys.unwrap_or(true),46 quote_keys.unwrap_or(true),48 #[cfg(feature = "exp-preserve-order")]47 #[cfg(feature = "exp-preserve-order")]crates/jrsonnet-stdlib/src/math.rsdiffbeforeafterboth1use jrsonnet_evaluator::{error::Result, function::builtin, typed::PositiveF64};1use jrsonnet_evaluator::{function::builtin, typed::PositiveF64};223#[builtin]3#[builtin]4pub fn builtin_abs(n: f64) -> Result<f64> {4pub fn builtin_abs(n: f64) -> f64 {5 Ok(n.abs())5 n.abs()6}6}778#[builtin]8#[builtin]9pub fn builtin_sign(n: f64) -> Result<f64> {9pub fn builtin_sign(n: f64) -> f64 {10 Ok(if n == 0. { 0. } else { n.signum() })10 if n == 0. {11 0.12 } else {13 n.signum()14 }11}15}121613#[builtin]17#[builtin]14pub fn builtin_max(a: f64, b: f64) -> Result<f64> {18pub fn builtin_max(a: f64, b: f64) -> f64 {15 Ok(a.max(b))19 a.max(b)16}20}172118#[builtin]22#[builtin]19pub fn builtin_min(a: f64, b: f64) -> Result<f64> {23pub fn builtin_min(a: f64, b: f64) -> f64 {20 Ok(a.min(b))24 a.min(b)21}25}222623#[builtin]27#[builtin]24pub fn builtin_modulo(a: f64, b: f64) -> Result<f64> {28pub fn builtin_modulo(x: f64, y: f64) -> f64 {25 Ok(a % b)29 x % y26}30}273128#[builtin]32#[builtin]29pub fn builtin_floor(x: f64) -> Result<f64> {33pub fn builtin_floor(x: f64) -> f64 {30 Ok(x.floor())34 x.floor()31}35}323633#[builtin]37#[builtin]34pub fn builtin_ceil(x: f64) -> Result<f64> {38pub fn builtin_ceil(x: f64) -> f64 {35 Ok(x.ceil())39 x.ceil()36}40}374138#[builtin]42#[builtin]39pub fn builtin_log(n: f64) -> Result<f64> {43pub fn builtin_log(x: f64) -> f64 {40 Ok(n.ln())44 x.ln()41}45}424643#[builtin]47#[builtin]44pub fn builtin_pow(x: f64, n: f64) -> Result<f64> {48pub fn builtin_pow(x: f64, n: f64) -> f64 {45 Ok(x.powf(n))49 x.powf(n)46}50}475148#[builtin]52#[builtin]49pub fn builtin_sqrt(x: PositiveF64) -> Result<f64> {53pub fn builtin_sqrt(x: PositiveF64) -> f64 {50 Ok(x.0.sqrt())54 x.0.sqrt()51}55}525653#[builtin]57#[builtin]54pub fn builtin_sin(x: f64) -> Result<f64> {58pub fn builtin_sin(x: f64) -> f64 {55 Ok(x.sin())59 x.sin()56}60}576158#[builtin]62#[builtin]59pub fn builtin_cos(x: f64) -> Result<f64> {63pub fn builtin_cos(x: f64) -> f64 {60 Ok(x.cos())64 x.cos()61}65}626663#[builtin]67#[builtin]64pub fn builtin_tan(x: f64) -> Result<f64> {68pub fn builtin_tan(x: f64) -> f64 {65 Ok(x.tan())69 x.tan()66}70}677168#[builtin]72#[builtin]69pub fn builtin_asin(x: f64) -> Result<f64> {73pub fn builtin_asin(x: f64) -> f64 {70 Ok(x.asin())74 x.asin()71}75}727673#[builtin]77#[builtin]74pub fn builtin_acos(x: f64) -> Result<f64> {78pub fn builtin_acos(x: f64) -> f64 {75 Ok(x.acos())79 x.acos()76}80}778178#[builtin]82#[builtin]79pub fn builtin_atan(x: f64) -> Result<f64> {83pub fn builtin_atan(x: f64) -> f64 {80 Ok(x.atan())84 x.atan()81}85}828683#[builtin]87#[builtin]84pub fn builtin_exp(x: f64) -> Result<f64> {88pub fn builtin_exp(x: f64) -> f64 {85 Ok(x.exp())89 x.exp()86}90}879188fn frexp(s: f64) -> (f64, i16) {92fn frexp(s: f64) -> (f64, i16) {97}101}9810299#[builtin]103#[builtin]100pub fn builtin_mantissa(x: f64) -> Result<f64> {104pub fn builtin_mantissa(x: f64) -> f64 {101 Ok(frexp(x).0)105 frexp(x).0102}106}103107104#[builtin]108#[builtin]105pub fn builtin_exponent(x: f64) -> Result<i16> {109pub fn builtin_exponent(x: f64) -> i16 {106 Ok(frexp(x).1)110 frexp(x).1107}111}108112crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth4 error::{ErrorKind::*, Result},4 error::{ErrorKind::*, Result},5 function::{builtin, ArgLike, CallLocation, FuncVal},5 function::{builtin, ArgLike, CallLocation, FuncVal},6 throw,6 throw,7 typed::{Any, Either2, Either4},7 typed::{Either2, Either4},8 val::{equals, ArrValue},8 val::{equals, ArrValue},9 Context, Either, IStr, ObjValue, Thunk, Val,9 Context, Either, IStr, ObjValue, Thunk, Val,10};10};111112use crate::{extvar_source, Settings};12use crate::{extvar_source, Settings};131314#[builtin]14#[builtin]15pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> Result<usize> {15pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> usize {16 use Either4::*;16 use Either4::*;17 Ok(match x {17 match x {18 A(x) => x.chars().count(),18 A(x) => x.chars().count(),19 B(x) => x.len(),19 B(x) => x.len(),20 C(x) => x.len(),20 C(x) => x.len(),21 D(f) => f.params_len(),21 D(f) => f.params_len(),22 })22 }23}23}242425#[builtin(fields(25#[builtin(fields(26 settings: Rc<RefCell<Settings>>,26 settings: Rc<RefCell<Settings>>,27))]27))]28pub fn builtin_ext_var(this: &builtin_ext_var, ctx: Context, x: IStr) -> Result<Any> {28pub fn builtin_ext_var(this: &builtin_ext_var, ctx: Context, x: IStr) -> Result<Val> {29 let ctx = ctx.state().create_default_context(extvar_source(&x, ""));29 let ctx = ctx.state().create_default_context(extvar_source(&x, ""));30 Ok(Any(this30 this.settings31 .settings32 .borrow()31 .borrow()33 .ext_vars32 .ext_vars34 .get(&x)33 .get(&x)35 .cloned()34 .cloned()36 .ok_or_else(|| UndefinedExternalVariable(x))?35 .ok_or_else(|| UndefinedExternalVariable(x))?37 .evaluate_arg(ctx, true)?36 .evaluate_arg(ctx, true)?38 .evaluate()?))37 .evaluate()39}38}403941#[builtin(fields(40#[builtin(fields(42 settings: Rc<RefCell<Settings>>,41 settings: Rc<RefCell<Settings>>,43))]42))]44pub fn builtin_native(this: &builtin_native, name: IStr) -> Result<Any> {43pub fn builtin_native(this: &builtin_native, x: IStr) -> Val {45 Ok(Any(this44 this.settings46 .settings45 .borrow()47 .borrow()46 .ext_natives48 .ext_natives47 .get(&x)49 .get(&name)50 .cloned()48 .cloned()51 .map_or(Val::Null, |v| {49 .map_or(Val::Null, |v| Val::Func(FuncVal::Builtin(v.clone())))52 Val::Func(FuncVal::Builtin(v.clone()))53 })))54}50}555156#[builtin(fields(52#[builtin(fields(61 loc: CallLocation,57 loc: CallLocation,62 str: IStr,58 str: IStr,63 rest: Thunk<Val>,59 rest: Thunk<Val>,64) -> Result<Any> {60) -> Result<Val> {65 this.settings.borrow().trace_printer.print_trace(loc, str);61 this.settings.borrow().trace_printer.print_trace(loc, str);66 Ok(Any(rest.evaluate()?))62 rest.evaluate()67}63}686469#[allow(clippy::comparison_chain)]65#[allow(clippy::comparison_chain)]crates/jrsonnet-stdlib/src/objects.rsdiffbeforeafterboth1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{2 error::Result,3 function::builtin,2 function::builtin,4 typed::VecVal,5 val::{StrValue, Val},3 val::{StrValue, Val},6 IStr, ObjValue,4 IStr, ObjValue,7};5};869#[builtin]7#[builtin]10pub fn builtin_object_fields_ex(8pub fn builtin_object_fields_ex(11 obj: ObjValue,9 obj: ObjValue,12 inc_hidden: bool,10 hidden: bool,13 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,11 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,14) -> Result<VecVal> {12) -> Vec<Val> {15 #[cfg(feature = "exp-preserve-order")]13 #[cfg(feature = "exp-preserve-order")]16 let preserve_order = preserve_order.unwrap_or(false);14 let preserve_order = preserve_order.unwrap_or(false);17 let out = obj.fields_ex(15 let out = obj.fields_ex(18 inc_hidden,16 hidden,19 #[cfg(feature = "exp-preserve-order")]17 #[cfg(feature = "exp-preserve-order")]20 preserve_order,18 preserve_order,21 );19 );22 Ok(VecVal(23 out.into_iter()20 out.into_iter()24 .map(StrValue::Flat)21 .map(StrValue::Flat)25 .map(Val::Str)22 .map(Val::Str)26 .collect::<Vec<_>>(),23 .collect::<Vec<_>>()27 ))28}24}292530#[builtin]26#[builtin]31pub fn builtin_object_has_ex(obj: ObjValue, f: IStr, inc_hidden: bool) -> Result<bool> {27pub fn builtin_object_has_ex(obj: ObjValue, fname: IStr, hidden: bool) -> bool {32 Ok(obj.has_field_ex(f, inc_hidden))28 obj.has_field_ex(fname, hidden)33}29}3430crates/jrsonnet-stdlib/src/operator.rsdiffbeforeafterboth6 function::builtin,6 function::builtin,7 operator::evaluate_mod_op,7 operator::evaluate_mod_op,8 stdlib::std_format,8 stdlib::std_format,9 typed::{Any, Either, Either2},9 typed::{Either, Either2},10 val::{equals, primitive_equals, StrValue},10 val::{equals, primitive_equals, StrValue},11 IStr, Val,11 IStr, Val,12};12};131314#[builtin]14#[builtin]15pub fn builtin_mod(a: Either![f64, IStr], b: Any) -> Result<Any> {15pub fn builtin_mod(a: Either![f64, IStr], b: Val) -> Result<Val> {16 use Either2::*;16 use Either2::*;17 Ok(Any(evaluate_mod_op(17 evaluate_mod_op(18 &match a {18 &match a {19 A(v) => Val::Num(v),19 A(v) => Val::Num(v),20 B(s) => Val::Str(StrValue::Flat(s)),20 B(s) => Val::Str(StrValue::Flat(s)),21 },21 },22 &b.0,22 &b,23 )?))23 )24}24}252526#[builtin]26#[builtin]27pub fn builtin_primitive_equals(a: Any, b: Any) -> Result<bool> {27pub fn builtin_primitive_equals(x: Val, y: Val) -> Result<bool> {28 primitive_equals(&a.0, &b.0)28 primitive_equals(&x, &y)29}29}303031#[builtin]31#[builtin]32pub fn builtin_equals(a: Any, b: Any) -> Result<bool> {32pub fn builtin_equals(a: Val, b: Val) -> Result<bool> {33 equals(&a.0, &b.0)33 equals(&a, &b)34}34}353536#[builtin]36#[builtin]37pub fn builtin_format(str: IStr, vals: Any) -> Result<String> {37pub fn builtin_format(str: IStr, vals: Val) -> Result<String> {38 std_format(&str, vals.0)38 std_format(&str, vals)39}39}4040crates/jrsonnet-stdlib/src/parse.rsdiffbeforeafterboth1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{2 error::{ErrorKind::RuntimeError, Result},2 error::{ErrorKind::RuntimeError, Result},3 function::builtin,3 function::builtin,4 typed::Any,5 IStr, Val,4 IStr, Val,6};5};7use serde::Deserialize;6use serde::Deserialize;879#[builtin]8#[builtin]10pub fn builtin_parse_json(s: IStr) -> Result<Any> {9pub fn builtin_parse_json(str: IStr) -> Result<Val> {11 let value: Val = serde_json::from_str(&s)10 let value: Val = serde_json::from_str(&str)12 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;11 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;13 Ok(Any(value))12 Ok(value)14}13}151416#[builtin]15#[builtin]17pub fn builtin_parse_yaml(s: IStr) -> Result<Any> {16pub fn builtin_parse_yaml(str: IStr) -> Result<Val> {18 use serde_yaml_with_quirks::DeserializingQuirks;17 use serde_yaml_with_quirks::DeserializingQuirks;19 let value = serde_yaml_with_quirks::Deserializer::from_str_with_quirks(18 let value = serde_yaml_with_quirks::Deserializer::from_str_with_quirks(20 &s,19 &str,21 DeserializingQuirks { old_octals: true },20 DeserializingQuirks { old_octals: true },22 );21 );23 let mut out = vec![];22 let mut out = vec![];26 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;25 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;27 out.push(val);26 out.push(val);28 }27 }29 Ok(Any(if out.is_empty() {28 Ok(if out.is_empty() {30 Val::Null29 Val::Null31 } else if out.len() == 1 {30 } else if out.len() == 1 {32 out.into_iter().next().unwrap()31 out.into_iter().next().unwrap()33 } else {32 } else {34 Val::Arr(out.into())33 Val::Arr(out.into())35 }))34 })36}35}3736crates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth2 error::Result,2 error::Result,3 function::{builtin, CallLocation, FuncVal},3 function::{builtin, CallLocation, FuncVal},4 throw,4 throw,5 typed::Any,6 val::ArrValue,5 val::ArrValue,7 Context, Val,6 Context, Val,8};7};9use jrsonnet_gcmodule::Cc;10811#[derive(Copy, Clone)]9#[derive(Copy, Clone)]12enum SortKeyType {10enum SortKeyType {78 key_getter.evaluate(76 key_getter.evaluate(79 ctx.clone(),77 ctx.clone(),80 CallLocation::native(),78 CallLocation::native(),81 &(Any(value.clone()),),79 &(value.clone(),),82 true,80 true,83 )?,81 )?,84 ));82 ));105 if arr.len() <= 1 {103 if arr.len() <= 1 {106 return Ok(arr);104 return Ok(arr);107 }105 }108 Ok(ArrValue::eager(Cc::new(super::sort::sort(106 Ok(ArrValue::eager(super::sort::sort(109 ctx,107 ctx,110 arr.iter().collect::<Result<Vec<_>>>()?,108 arr.iter().collect::<Result<Vec<_>>>()?,111 keyF.unwrap_or_else(FuncVal::identity),109 keyF.unwrap_or_else(FuncVal::identity),112 )?)))110 )?))113}111}114112crates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth2 error::{ErrorKind::*, Result},2 error::{ErrorKind::*, Result},3 function::builtin,3 function::builtin,4 throw,4 throw,5 typed::{Either2, VecVal, M1},5 typed::{Either2, M1},6 val::{ArrValue, StrValue},6 val::{ArrValue, StrValue},7 Either, IStr, Val,7 Either, IStr, Val,8};8};9910#[builtin]10#[builtin]11pub const fn builtin_codepoint(str: char) -> Result<u32> {11pub const fn builtin_codepoint(str: char) -> u32 {12 Ok(str as u32)12 str as u3213}13}141415#[builtin]15#[builtin]16pub fn builtin_substr(str: IStr, from: usize, len: usize) -> Result<String> {16pub fn builtin_substr(str: IStr, from: usize, len: usize) -> String {17 Ok(str.chars().skip(from).take(len).collect())17 str.chars().skip(from).take(len).collect()18}18}191920#[builtin]20#[builtin]23}23}242425#[builtin]25#[builtin]26pub fn builtin_str_replace(str: String, from: IStr, to: IStr) -> Result<String> {26pub fn builtin_str_replace(str: String, from: IStr, to: IStr) -> String {27 Ok(str.replace(&from as &str, &to as &str))27 str.replace(&from as &str, &to as &str)28}28}292930#[builtin]30#[builtin]31pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> Result<VecVal> {31pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue {32 use Either2::*;32 use Either2::*;33 Ok(VecVal(match maxsplits {33 match maxsplits {34 A(n) => str34 A(n) => str35 .splitn(n + 1, &c as &str)35 .splitn(n + 1, &c as &str)36 .map(|s| Val::Str(StrValue::Flat(s.into())))36 .map(|s| Val::Str(StrValue::Flat(s.into())))39 .split(&c as &str)39 .split(&c as &str)40 .map(|s| Val::Str(StrValue::Flat(s.into())))40 .map(|s| Val::Str(StrValue::Flat(s.into())))41 .collect(),41 .collect(),42 }))42 }43}43}444445#[builtin]45#[builtin]46pub fn builtin_ascii_upper(str: IStr) -> Result<String> {46pub fn builtin_ascii_upper(str: IStr) -> String {47 Ok(str.to_ascii_uppercase())47 str.to_ascii_uppercase()48}48}494950#[builtin]50#[builtin]51pub fn builtin_ascii_lower(str: IStr) -> Result<String> {51pub fn builtin_ascii_lower(str: IStr) -> String {52 Ok(str.to_ascii_lowercase())52 str.to_ascii_lowercase()53}53}545455#[builtin]55#[builtin]56pub fn builtin_find_substr(pat: IStr, str: IStr) -> Result<ArrValue> {56pub fn builtin_find_substr(pat: IStr, str: IStr) -> ArrValue {57 if pat.is_empty() || str.is_empty() || pat.len() > str.len() {57 if pat.is_empty() || str.is_empty() || pat.len() > str.len() {58 return Ok(ArrValue::empty());58 return ArrValue::empty();59 }59 }606061 let str = str.as_str();61 let str = str.as_str();74 out.push(Val::Num(ch_idx as f64))74 out.push(Val::Num(ch_idx as f64))75 }75 }76 }76 }77 Ok(out.into())77 out.into()78}78}797980#[builtin]80#[builtin]crates/jrsonnet-stdlib/src/types.rsdiffbeforeafterboth1use jrsonnet_evaluator::{error::Result, function::builtin, typed::Any, IStr, Val};1use jrsonnet_evaluator::{function::builtin, IStr, Val};223#[builtin]3#[builtin]4pub fn builtin_type(v: Any) -> Result<IStr> {4pub fn builtin_type(x: Val) -> IStr {5 Ok(v.0.value_type().name().into())5 x.value_type().name().into()6}6}778#[builtin]8#[builtin]9pub fn builtin_is_string(v: Any) -> Result<bool> {9pub fn builtin_is_string(v: Val) -> bool {10 Ok(matches!(v.0, Val::Str(_)))10 matches!(v, Val::Str(_))11}11}12#[builtin]12#[builtin]13pub fn builtin_is_number(v: Any) -> Result<bool> {13pub fn builtin_is_number(v: Val) -> bool {14 Ok(matches!(v.0, Val::Num(_)))14 matches!(v, Val::Num(_))15}15}16#[builtin]16#[builtin]17pub fn builtin_is_boolean(v: Any) -> Result<bool> {17pub fn builtin_is_boolean(v: Val) -> bool {18 Ok(matches!(v.0, Val::Bool(_)))18 matches!(v, Val::Bool(_))19}19}20#[builtin]20#[builtin]21pub fn builtin_is_object(v: Any) -> Result<bool> {21pub fn builtin_is_object(v: Val) -> bool {22 Ok(matches!(v.0, Val::Obj(_)))22 matches!(v, Val::Obj(_))23}23}24#[builtin]24#[builtin]25pub fn builtin_is_array(v: Any) -> Result<bool> {25pub fn builtin_is_array(v: Val) -> bool {26 Ok(matches!(v.0, Val::Arr(_)))26 matches!(v, Val::Arr(_))27}27}28#[builtin]28#[builtin]29pub fn builtin_is_function(v: Any) -> Result<bool> {29pub fn builtin_is_function(v: Val) -> bool {30 Ok(matches!(v.0, Val::Func(_)))30 matches!(v, Val::Func(_))31}31}3232tests/tests/builtin.rsdiffbeforeafterboth3use jrsonnet_evaluator::{3use jrsonnet_evaluator::{4 error::Result,4 error::Result,5 function::{builtin, builtin::Builtin, CallLocation, FuncVal},5 function::{builtin, builtin::Builtin, CallLocation, FuncVal},6 tb,7 typed::Typed,6 typed::Typed,8 ContextBuilder, State, Thunk, Val,7 ContextBuilder, State, Thunk, Val,9};8};10use jrsonnet_gcmodule::Cc;11use jrsonnet_stdlib::StateExt;9use jrsonnet_stdlib::StateExt;121013#[builtin]11#[builtin]636164#[builtin]62#[builtin]65fn curry_add(a: u32) -> Result<FuncVal> {63fn curry_add(a: u32) -> Result<FuncVal> {66 Ok(FuncVal::Builtin(Cc::new(tb!(curried_add { a }))))64 Ok(FuncVal::builtin(curried_add { a }))67}65}686669#[test]67#[test]tests/tests/common.rsdiffbeforeafterboth1use std::borrow::Cow;21use jrsonnet_evaluator::{3use jrsonnet_evaluator::{2 error::Result,4 error::Result,53 Ok(true)55 Ok(true)54}56}5758#[builtin]59fn param_names(fun: FuncVal) -> Vec<String> {60 match fun {61 FuncVal::Id => vec!["x".to_string()],62 FuncVal::Normal(func) => func63 .params64 .iter()65 .map(|p| p.0.name().unwrap_or_else(|| "<unnamed>".into()).to_string())66 .collect(),67 FuncVal::StaticBuiltin(b) => b68 .params()69 .iter()70 .map(|p| {71 p.name72 .as_ref()73 .unwrap_or(&Cow::Borrowed("<unnamed>"))74 .to_string()75 })76 .collect(),77 FuncVal::Builtin(b) => b78 .params()79 .iter()80 .map(|p| {81 p.name82 .as_ref()83 .unwrap_or(&Cow::Borrowed("<unnamed>"))84 .to_string()85 })86 .collect(),87 }88}558956#[allow(dead_code)]90#[allow(dead_code)]57pub fn with_test(s: &State) {91pub fn with_test(s: &State) {58 let mut bobj = ObjValueBuilder::new();92 let mut bobj = ObjValueBuilder::new();59 bobj.member("assertThrow".into())93 bobj.member("assertThrow".into())60 .hide()94 .hide()61 .value(Val::Func(FuncVal::StaticBuiltin(assert_throw::INST)))95 .value_unchecked(Val::Func(FuncVal::StaticBuiltin(assert_throw::INST)));62 .expect("no error");96 bobj.member("paramNames".into())97 .hide()98 .value_unchecked(Val::Func(FuncVal::StaticBuiltin(param_names::INST)));639964 s.add_global("test".into(), Thunk::evaluated(Val::Obj(bobj.build())))100 s.add_global("test".into(), Thunk::evaluated(Val::Obj(bobj.build())))65}101}tests/tests/golden.rsdiffbeforeafterboth16 let s = State::default();16 let s = State::default();17 s.with_stdlib();17 s.with_stdlib();18 common::with_test(&s);18 common::with_test(&s);19 s.set_import_resolver(Box::new(FileImportResolver::default()));19 s.set_import_resolver(FileImportResolver::default());20 let trace_format = CompactFormat {20 let trace_format = CompactFormat {21 resolver: PathResolver::FileName,21 resolver: PathResolver::FileName,22 max_trace: 20,22 max_trace: 20,tests/tests/suite.rsdiffbeforeafterboth15 let s = State::default();15 let s = State::default();16 s.with_stdlib();16 s.with_stdlib();17 common::with_test(&s);17 common::with_test(&s);18 s.set_import_resolver(Box::new(FileImportResolver::default()));18 s.set_import_resolver(FileImportResolver::default());19 let trace_format = CompactFormat::default();19 let trace_format = CompactFormat::default();202021 match s.import(file) {21 match s.import(file) {