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

difftreelog

source

crates/jrsonnet-stdlib/src/sets.rs4.4 KiBsourcehistory
1use std::cmp::Ordering;23use jrsonnet_evaluator::{4	function::{builtin, FuncVal},5	operator::evaluate_compare_op,6	val::ArrValue,7	Result, Thunk, Val,8};9use jrsonnet_parser::BinaryOpType;1011#[builtin]12#[allow(non_snake_case)]13pub fn builtin_set_member(x: Thunk<Val>, arr: ArrValue, keyF: Option<FuncVal>) -> Result<bool> {14	let mut low = 0;15	let mut high = arr.len();1617	let keyF = keyF18		.unwrap_or(FuncVal::Id)19		.into_native::<((Thunk<Val>,), Val)>();2021	let x = keyF(x)?;2223	while low < high {24		let middle = (high + low) / 2;25		let comp = keyF(arr.get_lazy(middle).expect("in bounds"))?;26		match evaluate_compare_op(&comp, &x, BinaryOpType::Lt)? {27			Ordering::Less => low = middle + 1,28			Ordering::Equal => return Ok(true),29			Ordering::Greater => high = middle,30		}31	}32	Ok(false)33}3435#[builtin]36#[allow(non_snake_case, clippy::redundant_closure)]37pub fn builtin_set_inter(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {38	let mut a = a.iter_lazy();39	let mut b = b.iter_lazy();4041	let keyF = keyF42		.unwrap_or(FuncVal::identity())43		.into_native::<((Thunk<Val>,), Val)>();44	let keyF = |v| keyF(v);4546	let mut av = a.next();47	let mut bv = b.next();48	let mut ak = av.clone().map(keyF).transpose()?;49	let mut bk = bv.map(keyF).transpose()?;5051	let mut out = Vec::new();52	while let (Some(ac), Some(bc)) = (&ak, &bk) {53		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {54			Ordering::Less => {55				av = a.next();56				ak = av.clone().map(keyF).transpose()?;57			}58			Ordering::Greater => {59				bv = b.next();60				bk = bv.map(keyF).transpose()?;61			}62			Ordering::Equal => {63				out.push(av.clone().expect("ak != None => av != None"));64				av = a.next();65				ak = av.clone().map(keyF).transpose()?;66				bv = b.next();67				bk = bv.map(keyF).transpose()?;68			}69		};70	}71	Ok(ArrValue::lazy(out))72}7374#[builtin]75#[allow(non_snake_case, clippy::redundant_closure)]76pub fn builtin_set_diff(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {77	let mut a = a.iter_lazy();78	let mut b = b.iter_lazy();7980	let keyF = keyF81		.unwrap_or(FuncVal::identity())82		.into_native::<((Thunk<Val>,), Val)>();83	let keyF = |v| keyF(v);8485	let mut av = a.next();86	let mut bv = b.next();87	let mut ak = av.clone().map(keyF).transpose()?;88	let mut bk = bv.map(keyF).transpose()?;8990	let mut out = Vec::new();91	while let (Some(ac), Some(bc)) = (&ak, &bk) {92		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {93			Ordering::Less => {94				// In a, but not in b95				out.push(av.clone().expect("ak != None"));96				av = a.next();97				ak = av.clone().map(keyF).transpose()?;98			}99			Ordering::Greater => {100				bv = b.next();101				bk = bv.map(keyF).transpose()?;102			}103			Ordering::Equal => {104				av = a.next();105				ak = av.clone().map(keyF).transpose()?;106				bv = b.next();107				bk = bv.map(keyF).transpose()?;108			}109		};110	}111	while let Some(_ac) = &ak {112		// In a, but not in b113		out.push(av.clone().expect("ak != None"));114		av = a.next();115		ak = av.clone().map(keyF).transpose()?;116	}117	Ok(ArrValue::lazy(out))118}119120#[builtin]121#[allow(non_snake_case, clippy::redundant_closure)]122pub fn builtin_set_union(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {123	let mut a = a.iter_lazy();124	let mut b = b.iter_lazy();125126	let keyF = keyF127		.unwrap_or(FuncVal::identity())128		.into_native::<((Thunk<Val>,), Val)>();129	let keyF = |v| keyF(v);130131	let mut av = a.next();132	let mut bv = b.next();133	let mut ak = av.clone().map(keyF).transpose()?;134	let mut bk = bv.clone().map(keyF).transpose()?;135136	let mut out = Vec::new();137	while let (Some(ac), Some(bc)) = (&ak, &bk) {138		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {139			Ordering::Less => {140				out.push(av.clone().expect("ak != None"));141				av = a.next();142				ak = av.clone().map(keyF).transpose()?;143			}144			Ordering::Greater => {145				out.push(bv.clone().expect("bk != None"));146				bv = b.next();147				bk = bv.clone().map(keyF).transpose()?;148			}149			Ordering::Equal => {150				// NOTE: order matters, values in `a` win151				out.push(av.clone().expect("ak != None"));152				av = a.next();153				ak = av.clone().map(keyF).transpose()?;154				bv = b.next();155				bk = bv.clone().map(keyF).transpose()?;156			}157		};158	}159	// a.len() > b.len()160	while let Some(_ac) = &ak {161		out.push(av.clone().expect("ak != None"));162		av = a.next();163		ak = av.clone().map(keyF).transpose()?;164	}165	// b.len() > a.len()166	while let Some(_bc) = &bk {167		out.push(bv.clone().expect("ak != None"));168		bv = b.next();169		bk = bv.clone().map(keyF).transpose()?;170	}171	Ok(ArrValue::lazy(out))172}