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

difftreelog

source

crates/jrsonnet-stdlib/src/arrays.rs4.9 KiBsourcehistory
1use jrsonnet_evaluator::{2	error::Result,3	function::{builtin, FuncVal},4	throw_runtime,5	typed::{Any, BoundedUsize, Typed, VecVal},6	val::{equals, ArrValue, IndexableVal},7	IStr, State, Val,8};9use jrsonnet_gcmodule::Cc;1011#[builtin]12pub fn builtin_make_array(s: State, sz: usize, func: FuncVal) -> Result<VecVal> {13	let mut out = Vec::with_capacity(sz);14	for i in 0..sz {15		out.push(func.evaluate_simple(s.clone(), &(i as f64,))?);16	}17	Ok(VecVal(Cc::new(out)))18}1920#[builtin]21pub fn builtin_slice(22	indexable: IndexableVal,23	index: Option<BoundedUsize<0, { i32::MAX as usize }>>,24	end: Option<BoundedUsize<0, { i32::MAX as usize }>>,25	step: Option<BoundedUsize<1, { i32::MAX as usize }>>,26) -> Result<Any> {27	indexable.slice(index, end, step).map(Val::from).map(Any)28}2930#[builtin]31pub fn builtin_map(s: State, func: FuncVal, arr: ArrValue) -> Result<ArrValue> {32	arr.map(s.clone(), |val| {33		func.evaluate_simple(s.clone(), &(Any(val),))34	})35}3637#[builtin]38pub fn builtin_flatmap(s: State, func: FuncVal, arr: IndexableVal) -> Result<IndexableVal> {39	match arr {40		IndexableVal::Str(str) => {41			let mut out = String::new();42			for c in str.chars() {43				match func.evaluate_simple(s.clone(), &(c.to_string(),))? {44					Val::Str(o) => out.push_str(&o),45					Val::Null => continue,46					_ => throw_runtime!("in std.join all items should be strings"),47				};48			}49			Ok(IndexableVal::Str(out.into()))50		}51		IndexableVal::Arr(a) => {52			let mut out = Vec::new();53			for el in a.iter(s.clone()) {54				let el = el?;55				match func.evaluate_simple(s.clone(), &(Any(el),))? {56					Val::Arr(o) => {57						for oe in o.iter(s.clone()) {58							out.push(oe?);59						}60					}61					Val::Null => continue,62					_ => throw_runtime!("in std.join all items should be arrays"),63				};64			}65			Ok(IndexableVal::Arr(out.into()))66		}67	}68}6970#[builtin]71pub fn builtin_filter(s: State, func: FuncVal, arr: ArrValue) -> Result<ArrValue> {72	arr.filter(s.clone(), |val| {73		bool::from_untyped(74			func.evaluate_simple(s.clone(), &(Any(val.clone()),))?,75			s.clone(),76		)77	})78}7980#[builtin]81pub fn builtin_foldl(s: State, func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {82	let mut acc = init.0;83	for i in arr.iter(s.clone()) {84		acc = func.evaluate_simple(s.clone(), &(Any(acc), Any(i?)))?;85	}86	Ok(Any(acc))87}8889#[builtin]90pub fn builtin_foldr(s: State, func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {91	let mut acc = init.0;92	for i in arr.iter(s.clone()).rev() {93		acc = func.evaluate_simple(s.clone(), &(Any(i?), Any(acc)))?;94	}95	Ok(Any(acc))96}9798#[builtin]99pub fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {100	if to < from {101		return Ok(ArrValue::new_eager());102	}103	Ok(ArrValue::new_range(from, to))104}105106#[builtin]107pub fn builtin_join(s: State, sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {108	Ok(match sep {109		IndexableVal::Arr(joiner_items) => {110			let mut out = Vec::new();111112			let mut first = true;113			for item in arr.iter(s.clone()) {114				let item = item?.clone();115				if let Val::Arr(items) = item {116					if !first {117						out.reserve(joiner_items.len());118						// TODO: extend119						for item in joiner_items.iter(s.clone()) {120							out.push(item?);121						}122					}123					first = false;124					out.reserve(items.len());125					for item in items.iter(s.clone()) {126						out.push(item?);127					}128				} else if matches!(item, Val::Null) {129					continue;130				} else {131					throw_runtime!("in std.join all items should be arrays");132				}133			}134135			IndexableVal::Arr(out.into())136		}137		IndexableVal::Str(sep) => {138			let mut out = String::new();139140			let mut first = true;141			for item in arr.iter(s) {142				let item = item?.clone();143				if let Val::Str(item) = item {144					if !first {145						out += &sep;146					}147					first = false;148					out += &item;149				} else if matches!(item, Val::Null) {150					continue;151				} else {152					throw_runtime!("in std.join all items should be strings");153				}154			}155156			IndexableVal::Str(out.into())157		}158	})159}160161#[builtin]162pub fn builtin_reverse(value: ArrValue) -> Result<ArrValue> {163	Ok(value.reversed())164}165166#[builtin]167pub fn builtin_any(s: State, arr: ArrValue) -> Result<bool> {168	for v in arr.iter(s.clone()) {169		let v = bool::from_untyped(v?, s.clone())?;170		if v {171			return Ok(true);172		}173	}174	Ok(false)175}176177#[builtin]178pub fn builtin_all(s: State, arr: ArrValue) -> Result<bool> {179	for v in arr.iter(s.clone()) {180		let v = bool::from_untyped(v?, s.clone())?;181		if !v {182			return Ok(false);183		}184	}185	Ok(true)186}187188#[builtin]189pub fn builtin_member(s: State, arr: IndexableVal, x: Any) -> Result<bool> {190	match arr {191		IndexableVal::Str(str) => {192			let x: IStr = IStr::from_untyped(x.0, s)?;193			Ok(!x.is_empty() && str.contains(&*x))194		}195		IndexableVal::Arr(a) => {196			for item in a.iter(s.clone()) {197				let item = item?;198				if equals(s.clone(), &item, &x.0)? {199					return Ok(true);200				}201			}202			Ok(false)203		}204	}205}206207#[builtin]208pub fn builtin_count(s: State, arr: Vec<Any>, v: Any) -> Result<usize> {209	let mut count = 0;210	for item in &arr {211		if equals(s.clone(), &item.0, &v.0)? {212			count += 1;213		}214	}215	Ok(count)216}