git.delta.rocks / jrsonnet / refs/commits / a05afd32cebc

difftreelog

source

crates/jrsonnet-stdlib/src/misc.rs2.6 KiBsourcehistory
1use std::{cell::RefCell, rc::Rc};23use jrsonnet_evaluator::{4	error::{ErrorKind::*, Result},5	function::{builtin, ArgLike, CallLocation, FuncVal},6	throw,7	typed::{Either2, Either4},8	val::{equals, ArrValue},9	Context, Either, IStr, ObjValue, Thunk, Val,10};1112use crate::{extvar_source, Settings};1314#[builtin]15pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> usize {16	use Either4::*;17	match x {18		A(x) => x.chars().count(),19		B(x) => x.len(),20		C(x) => x.len(),21		D(f) => f.params_len(),22	}23}2425#[builtin(fields(26	settings: Rc<RefCell<Settings>>,27))]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, ""));30	this.settings31		.borrow()32		.ext_vars33		.get(&x)34		.cloned()35		.ok_or_else(|| UndefinedExternalVariable(x))?36		.evaluate_arg(ctx, true)?37		.evaluate()38}3940#[builtin(fields(41	settings: Rc<RefCell<Settings>>,42))]43pub fn builtin_native(this: &builtin_native, x: IStr) -> Val {44	this.settings45		.borrow()46		.ext_natives47		.get(&x)48		.cloned()49		.map_or(Val::Null, |v| Val::Func(FuncVal::Builtin(v)))50}5152#[builtin(fields(53	settings: Rc<RefCell<Settings>>,54))]55pub fn builtin_trace(56	this: &builtin_trace,57	loc: CallLocation,58	str: IStr,59	rest: Thunk<Val>,60) -> Result<Val> {61	this.settings.borrow().trace_printer.print_trace(loc, str);62	rest.evaluate()63}6465#[allow(clippy::comparison_chain)]66#[builtin]67pub fn builtin_starts_with(a: Either![IStr, ArrValue], b: Either![IStr, ArrValue]) -> Result<bool> {68	Ok(match (a, b) {69		(Either2::A(a), Either2::A(b)) => a.starts_with(b.as_str()),70		(Either2::B(a), Either2::B(b)) => {71			if b.len() > a.len() {72				return Ok(false);73			} else if b.len() == a.len() {74				return equals(&Val::Arr(a), &Val::Arr(b));75			} else {76				for (a, b) in a.iter().take(b.len()).zip(b.iter()) {77					let a = a?;78					let b = b?;79					if !equals(&a, &b)? {80						return Ok(false);81					}82				}83				true84			}85		}86		_ => throw!("both arguments should be of the same type"),87	})88}8990#[allow(clippy::comparison_chain)]91#[builtin]92pub fn builtin_ends_with(a: Either![IStr, ArrValue], b: Either![IStr, ArrValue]) -> Result<bool> {93	Ok(match (a, b) {94		(Either2::A(a), Either2::A(b)) => a.ends_with(b.as_str()),95		(Either2::B(a), Either2::B(b)) => {96			if b.len() > a.len() {97				return Ok(false);98			} else if b.len() == a.len() {99				return equals(&Val::Arr(a), &Val::Arr(b));100			} else {101				let a_len = a.len();102				for (a, b) in a.iter().skip(a_len - b.len()).zip(b.iter()) {103					let a = a?;104					let b = b?;105					if !equals(&a, &b)? {106						return Ok(false);107					}108				}109				true110			}111		}112		_ => throw!("both arguments should be of the same type"),113	})114}