git.delta.rocks / jrsonnet / refs/commits / 7b01ecbd8fbc

difftreelog

source

crates/jrsonnet-stdlib/src/arrays.rs4.6 KiBsourcehistory
1use jrsonnet_evaluator::{2	error::Result,3	function::{builtin, FuncVal},4	throw,5	typed::{Any, BoundedUsize, Either2, NativeFn, Typed, VecVal},6	val::{equals, ArrValue, IndexableVal},7	Either, IStr, Val,8};9use jrsonnet_gcmodule::Cc;1011#[builtin]12pub fn builtin_make_array(sz: usize, func: NativeFn<((f64,), Any)>) -> Result<VecVal> {13	let mut out = Vec::with_capacity(sz);14	for i in 0..sz {15		out.push(func(i as f64)?.0);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(func: NativeFn<((Any,), Any)>, arr: ArrValue) -> Result<ArrValue> {32	arr.map(|val| Ok(func(Any(val))?.0))33}3435#[builtin]36pub fn builtin_flatmap(37	func: NativeFn<((Either![String, Any],), Any)>,38	arr: IndexableVal,39) -> Result<IndexableVal> {40	match arr {41		IndexableVal::Str(str) => {42			let mut out = String::new();43			for c in str.chars() {44				match func(Either2::A(c.to_string()))?.0 {45					Val::Str(o) => out.push_str(&o),46					Val::Null => continue,47					_ => throw!("in std.join all items should be strings"),48				};49			}50			Ok(IndexableVal::Str(out.into()))51		}52		IndexableVal::Arr(a) => {53			let mut out = Vec::new();54			for el in a.iter() {55				let el = el?;56				match func(Either2::B(Any(el)))?.0 {57					Val::Arr(o) => {58						for oe in o.iter() {59							out.push(oe?);60						}61					}62					Val::Null => continue,63					_ => throw!("in std.join all items should be arrays"),64				};65			}66			Ok(IndexableVal::Arr(out.into()))67		}68	}69}7071#[builtin]72pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {73	arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(Any(val.clone()),))?))74}7576#[builtin]77pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {78	let mut acc = init.0;79	for i in arr.iter() {80		acc = func.evaluate_simple(&(Any(acc), Any(i?)))?;81	}82	Ok(Any(acc))83}8485#[builtin]86pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {87	let mut acc = init.0;88	for i in arr.iter().rev() {89		acc = func.evaluate_simple(&(Any(i?), Any(acc)))?;90	}91	Ok(Any(acc))92}9394#[builtin]95pub fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {96	if to < from {97		return Ok(ArrValue::new_eager());98	}99	Ok(ArrValue::new_range(from, to))100}101102#[builtin]103pub fn builtin_join(sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {104	Ok(match sep {105		IndexableVal::Arr(joiner_items) => {106			let mut out = Vec::new();107108			let mut first = true;109			for item in arr.iter() {110				let item = item?.clone();111				if let Val::Arr(items) = item {112					if !first {113						out.reserve(joiner_items.len());114						// TODO: extend115						for item in joiner_items.iter() {116							out.push(item?);117						}118					}119					first = false;120					out.reserve(items.len());121					for item in items.iter() {122						out.push(item?);123					}124				} else if matches!(item, Val::Null) {125					continue;126				} else {127					throw!("in std.join all items should be arrays");128				}129			}130131			IndexableVal::Arr(out.into())132		}133		IndexableVal::Str(sep) => {134			let mut out = String::new();135136			let mut first = true;137			for item in arr.iter() {138				let item = item?.clone();139				if let Val::Str(item) = item {140					if !first {141						out += &sep;142					}143					first = false;144					out += &item;145				} else if matches!(item, Val::Null) {146					continue;147				} else {148					throw!("in std.join all items should be strings");149				}150			}151152			IndexableVal::Str(out.into())153		}154	})155}156157#[builtin]158pub fn builtin_reverse(value: ArrValue) -> Result<ArrValue> {159	Ok(value.reversed())160}161162#[builtin]163pub fn builtin_any(arr: ArrValue) -> Result<bool> {164	for v in arr.iter() {165		let v = bool::from_untyped(v?)?;166		if v {167			return Ok(true);168		}169	}170	Ok(false)171}172173#[builtin]174pub fn builtin_all(arr: ArrValue) -> Result<bool> {175	for v in arr.iter() {176		let v = bool::from_untyped(v?)?;177		if !v {178			return Ok(false);179		}180	}181	Ok(true)182}183184#[builtin]185pub fn builtin_member(arr: IndexableVal, x: Any) -> Result<bool> {186	match arr {187		IndexableVal::Str(str) => {188			let x: IStr = IStr::from_untyped(x.0)?;189			Ok(!x.is_empty() && str.contains(&*x))190		}191		IndexableVal::Arr(a) => {192			for item in a.iter() {193				let item = item?;194				if equals(&item, &x.0)? {195					return Ok(true);196				}197			}198			Ok(false)199		}200	}201}202203#[builtin]204pub fn builtin_count(arr: Vec<Any>, v: Any) -> Result<usize> {205	let mut count = 0;206	for item in &arr {207		if equals(&item.0, &v.0)? {208			count += 1;209		}210	}211	Ok(count)212}