git.delta.rocks / jrsonnet / refs/commits / 2afd5ff0dd7a

difftreelog

source

crates/jrsonnet-stdlib/src/misc.rs2.7 KiBsourcehistory
1use std::{cell::RefCell, rc::Rc};23use jrsonnet_evaluator::{4	error::{ErrorKind::*, Result},5	function::{builtin, ArgLike, CallLocation, FuncVal},6	throw,7	typed::{Any, 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]) -> Result<usize> {16	use Either4::*;17	Ok(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<Any> {29	let ctx = ctx.state().create_default_context(extvar_source(&x, ""));30	Ok(Any(this31		.settings32		.borrow()33		.ext_vars34		.get(&x)35		.cloned()36		.ok_or_else(|| UndefinedExternalVariable(x))?37		.evaluate_arg(ctx, true)?38		.evaluate()?))39}4041#[builtin(fields(42	settings: Rc<RefCell<Settings>>,43))]44pub fn builtin_native(this: &builtin_native, name: IStr) -> Result<Any> {45	Ok(Any(this46		.settings47		.borrow()48		.ext_natives49		.get(&name)50		.cloned()51		.map_or(Val::Null, |v| {52			Val::Func(FuncVal::Builtin(v.clone()))53		})))54}5556#[builtin(fields(57	settings: Rc<RefCell<Settings>>,58))]59pub fn builtin_trace(60	this: &builtin_trace,61	loc: CallLocation,62	str: IStr,63	rest: Thunk<Val>,64) -> Result<Any> {65	this.settings.borrow().trace_printer.print_trace(loc, str);66	Ok(Any(rest.evaluate()?))67}6869#[allow(clippy::comparison_chain)]70#[builtin]71pub fn builtin_starts_with(a: Either![IStr, ArrValue], b: Either![IStr, ArrValue]) -> Result<bool> {72	Ok(match (a, b) {73		(Either2::A(a), Either2::A(b)) => a.starts_with(b.as_str()),74		(Either2::B(a), Either2::B(b)) => {75			if b.len() > a.len() {76				return Ok(false);77			} else if b.len() == a.len() {78				return equals(&Val::Arr(a), &Val::Arr(b));79			} else {80				for (a, b) in a.iter().take(b.len()).zip(b.iter()) {81					let a = a?;82					let b = b?;83					if !equals(&a, &b)? {84						return Ok(false);85					}86				}87				true88			}89		}90		_ => throw!("both arguments should be of the same type"),91	})92}9394#[allow(clippy::comparison_chain)]95#[builtin]96pub fn builtin_ends_with(a: Either![IStr, ArrValue], b: Either![IStr, ArrValue]) -> Result<bool> {97	Ok(match (a, b) {98		(Either2::A(a), Either2::A(b)) => a.ends_with(b.as_str()),99		(Either2::B(a), Either2::B(b)) => {100			if b.len() > a.len() {101				return Ok(false);102			} else if b.len() == a.len() {103				return equals(&Val::Arr(a), &Val::Arr(b));104			} else {105				let a_len = a.len();106				for (a, b) in a.iter().skip(a_len - b.len()).zip(b.iter()) {107					let a = a?;108					let b = b?;109					if !equals(&a, &b)? {110						return Ok(false);111					}112				}113				true114			}115		}116		_ => throw!("both arguments should be of the same type"),117	})118}