git.delta.rocks / jrsonnet / refs/commits / 78d45eb4e76f

difftreelog

source

crates/jrsonnet-stdlib/src/misc.rs2.9 KiBsourcehistory
1use std::{cell::RefCell, rc::Rc};23use jrsonnet_evaluator::{4	error::{Error::*, Result},5	function::{builtin, ArgLike, CallLocation, FuncVal},6	throw,7	typed::{Any, Either2, Either4},8	val::{equals, ArrValue},9	Either, IStr, ObjValue, State, 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, s: State, x: IStr) -> Result<Any> {29	let ctx = s.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(s.clone(), ctx, true)?38		.evaluate(s)?))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	s: State,62	loc: CallLocation,63	str: IStr,64	rest: Thunk<Val>,65) -> Result<Any> {66	this.settings67		.borrow()68		.trace_printer69		.print_trace(s.clone(), loc, str);70	Ok(Any(rest.evaluate(s)?))71}7273#[allow(clippy::comparison_chain)]74#[builtin]75pub fn builtin_starts_with(76	s: State,77	a: Either![IStr, ArrValue],78	b: Either![IStr, ArrValue],79) -> Result<bool> {80	Ok(match (a, b) {81		(Either2::A(a), Either2::A(b)) => a.starts_with(b.as_str()),82		(Either2::B(a), Either2::B(b)) => {83			if b.len() > a.len() {84				return Ok(false);85			} else if b.len() == a.len() {86				return equals(s, &Val::Arr(a), &Val::Arr(b));87			} else {88				for (a, b) in a89					.slice(None, Some(b.len()), None)90					.iter(s.clone())91					.zip(b.iter(s.clone()))92				{93					let a = a?;94					let b = b?;95					if !equals(s.clone(), &a, &b)? {96						return Ok(false);97					}98				}99				true100			}101		}102		_ => throw!("both arguments should be of the same type"),103	})104}105106#[allow(clippy::comparison_chain)]107#[builtin]108pub fn builtin_ends_with(109	s: State,110	a: Either![IStr, ArrValue],111	b: Either![IStr, ArrValue],112) -> Result<bool> {113	Ok(match (a, b) {114		(Either2::A(a), Either2::A(b)) => a.ends_with(b.as_str()),115		(Either2::B(a), Either2::B(b)) => {116			if b.len() > a.len() {117				return Ok(false);118			} else if b.len() == a.len() {119				return equals(s, &Val::Arr(a), &Val::Arr(b));120			} else {121				let a_len = a.len();122				for (a, b) in a123					.slice(Some(a_len - b.len()), None, None)124					.iter(s.clone())125					.zip(b.iter(s.clone()))126				{127					let a = a?;128					let b = b?;129					if !equals(s.clone(), &a, &b)? {130						return Ok(false);131					}132				}133				true134			}135		}136		_ => throw!("both arguments should be of the same type"),137	})138}