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

difftreelog

source

crates/jrsonnet-stdlib/src/sets.rs4.1 KiBsourcehistory
1use std::cmp::Ordering;23use jrsonnet_evaluator::{4	Result, Thunk, Val, function::builtin, operator::evaluate_compare_op, val::ArrValue,5};6use jrsonnet_ir::BinaryOpType;78use crate::keyf::KeyF;910#[builtin]11#[allow(non_snake_case)]12pub fn builtin_set_member(x: Thunk<Val>, arr: ArrValue, #[default] keyF: KeyF) -> Result<bool> {13	let mut low = 0;14	let mut high = arr.len();1516	let x = keyF.eval(x)?;1718	while low < high {19		let middle = usize::midpoint(high, low);20		let comp = keyF.eval(arr.get_lazy(middle).expect("in bounds"))?;21		match evaluate_compare_op(&comp, &x, BinaryOpType::Lt)? {22			Ordering::Less => low = middle + 1,23			Ordering::Equal => return Ok(true),24			Ordering::Greater => high = middle,25		}26	}27	Ok(false)28}2930#[builtin]31#[allow(non_snake_case, clippy::redundant_closure)]32pub fn builtin_set_inter(33	a: ArrValue,34	b: ArrValue,35	#[default] keyF: KeyF,36) -> Result<Vec<Thunk<Val>>> {37	let mut a = a.iter_lazy();38	let mut b = b.iter_lazy();3940	let keyF = |v| keyF.eval(v);4142	let mut av = a.next();43	let mut bv = b.next();44	let mut ak = av.clone().map(keyF).transpose()?;45	let mut bk = bv.map(keyF).transpose()?;4647	let mut out = Vec::new();48	while let (Some(ac), Some(bc)) = (&ak, &bk) {49		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {50			Ordering::Less => {51				av = a.next();52				ak = av.clone().map(keyF).transpose()?;53			}54			Ordering::Greater => {55				bv = b.next();56				bk = bv.map(keyF).transpose()?;57			}58			Ordering::Equal => {59				out.push(av.clone().expect("ak != None => av != None"));60				av = a.next();61				ak = av.clone().map(keyF).transpose()?;62				bv = b.next();63				bk = bv.map(keyF).transpose()?;64			}65		}66	}67	Ok(out)68}6970#[builtin]71#[allow(non_snake_case, clippy::redundant_closure)]72pub fn builtin_set_diff(73	a: ArrValue,74	b: ArrValue,75	#[default] keyF: KeyF,76) -> Result<Vec<Thunk<Val>>> {77	let mut a = a.iter_lazy();78	let mut b = b.iter_lazy();7980	let keyF = |v| keyF.eval(v);8182	let mut av = a.next();83	let mut bv = b.next();84	let mut ak = av.clone().map(keyF).transpose()?;85	let mut bk = bv.map(keyF).transpose()?;8687	let mut out = Vec::new();88	while let (Some(ac), Some(bc)) = (&ak, &bk) {89		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {90			Ordering::Less => {91				// In a, but not in b92				out.push(av.clone().expect("ak != None"));93				av = a.next();94				ak = av.clone().map(keyF).transpose()?;95			}96			Ordering::Greater => {97				bv = b.next();98				bk = bv.map(keyF).transpose()?;99			}100			Ordering::Equal => {101				av = a.next();102				ak = av.clone().map(keyF).transpose()?;103				bv = b.next();104				bk = bv.map(keyF).transpose()?;105			}106		}107	}108	while let Some(_ac) = &ak {109		// In a, but not in b110		out.push(av.clone().expect("ak != None"));111		av = a.next();112		ak = av.clone().map(keyF).transpose()?;113	}114	Ok(out)115}116117#[builtin]118#[allow(non_snake_case, clippy::redundant_closure)]119pub fn builtin_set_union(120	a: ArrValue,121	b: ArrValue,122	#[default] keyF: KeyF,123) -> Result<Vec<Thunk<Val>>> {124	let mut a = a.iter_lazy();125	let mut b = b.iter_lazy();126127	let keyF = |v| keyF.eval(v);128129	let mut av = a.next();130	let mut bv = b.next();131	let mut ak = av.clone().map(keyF).transpose()?;132	let mut bk = bv.clone().map(keyF).transpose()?;133134	let mut out = Vec::new();135	while let (Some(ac), Some(bc)) = (&ak, &bk) {136		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {137			Ordering::Less => {138				out.push(av.clone().expect("ak != None"));139				av = a.next();140				ak = av.clone().map(keyF).transpose()?;141			}142			Ordering::Greater => {143				out.push(bv.clone().expect("bk != None"));144				bv = b.next();145				bk = bv.clone().map(keyF).transpose()?;146			}147			Ordering::Equal => {148				// NOTE: order matters, values in `a` win149				out.push(av.clone().expect("ak != None"));150				av = a.next();151				ak = av.clone().map(keyF).transpose()?;152				bv = b.next();153				bk = bv.clone().map(keyF).transpose()?;154			}155		}156	}157	// a.len() > b.len()158	while let Some(_ac) = &ak {159		out.push(av.clone().expect("ak != None"));160		av = a.next();161		ak = av.clone().map(keyF).transpose()?;162	}163	// b.len() > a.len()164	while let Some(_bc) = &bk {165		out.push(bv.clone().expect("ak != None"));166		bv = b.next();167		bk = bv.clone().map(keyF).transpose()?;168	}169	Ok(out)170}