git.delta.rocks / jrsonnet / refs/commits / 0afd46183b60

difftreelog

source

crates/jrsonnet-stdlib/src/sets.rs4.1 KiBsourcehistory
1use std::cmp::Ordering;23use jrsonnet_evaluator::{4	function::builtin, operator::evaluate_compare_op, val::ArrValue, Result, Thunk, Val,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(a: ArrValue, b: ArrValue, #[default] keyF: KeyF) -> Result<ArrValue> {33	let mut a = a.iter_lazy();34	let mut b = b.iter_lazy();3536	let keyF = |v| keyF.eval(v);3738	let mut av = a.next();39	let mut bv = b.next();40	let mut ak = av.clone().map(keyF).transpose()?;41	let mut bk = bv.map(keyF).transpose()?;4243	let mut out = Vec::new();44	while let (Some(ac), Some(bc)) = (&ak, &bk) {45		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {46			Ordering::Less => {47				av = a.next();48				ak = av.clone().map(keyF).transpose()?;49			}50			Ordering::Greater => {51				bv = b.next();52				bk = bv.map(keyF).transpose()?;53			}54			Ordering::Equal => {55				out.push(av.clone().expect("ak != None => av != None"));56				av = a.next();57				ak = av.clone().map(keyF).transpose()?;58				bv = b.next();59				bk = bv.map(keyF).transpose()?;60			}61		}62	}63	Ok(ArrValue::lazy(out))64}6566#[builtin]67#[allow(non_snake_case, clippy::redundant_closure)]68pub fn builtin_set_diff(a: ArrValue, b: ArrValue, #[default] keyF: KeyF) -> Result<ArrValue> {69	let mut a = a.iter_lazy();70	let mut b = b.iter_lazy();7172	let keyF = |v| keyF.eval(v);7374	let mut av = a.next();75	let mut bv = b.next();76	let mut ak = av.clone().map(keyF).transpose()?;77	let mut bk = bv.map(keyF).transpose()?;7879	let mut out = Vec::new();80	while let (Some(ac), Some(bc)) = (&ak, &bk) {81		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {82			Ordering::Less => {83				// In a, but not in b84				out.push(av.clone().expect("ak != None"));85				av = a.next();86				ak = av.clone().map(keyF).transpose()?;87			}88			Ordering::Greater => {89				bv = b.next();90				bk = bv.map(keyF).transpose()?;91			}92			Ordering::Equal => {93				av = a.next();94				ak = av.clone().map(keyF).transpose()?;95				bv = b.next();96				bk = bv.map(keyF).transpose()?;97			}98		}99	}100	while let Some(_ac) = &ak {101		// In a, but not in b102		out.push(av.clone().expect("ak != None"));103		av = a.next();104		ak = av.clone().map(keyF).transpose()?;105	}106	Ok(ArrValue::lazy(out))107}108109#[builtin]110#[allow(non_snake_case, clippy::redundant_closure)]111pub fn builtin_set_union(a: ArrValue, b: ArrValue, #[default] keyF: KeyF) -> Result<ArrValue> {112	let mut a = a.iter_lazy();113	let mut b = b.iter_lazy();114115	let keyF = |v| keyF.eval(v);116117	let mut av = a.next();118	let mut bv = b.next();119	let mut ak = av.clone().map(keyF).transpose()?;120	let mut bk = bv.clone().map(keyF).transpose()?;121122	let mut out = Vec::new();123	while let (Some(ac), Some(bc)) = (&ak, &bk) {124		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {125			Ordering::Less => {126				out.push(av.clone().expect("ak != None"));127				av = a.next();128				ak = av.clone().map(keyF).transpose()?;129			}130			Ordering::Greater => {131				out.push(bv.clone().expect("bk != None"));132				bv = b.next();133				bk = bv.clone().map(keyF).transpose()?;134			}135			Ordering::Equal => {136				// NOTE: order matters, values in `a` win137				out.push(av.clone().expect("ak != None"));138				av = a.next();139				ak = av.clone().map(keyF).transpose()?;140				bv = b.next();141				bk = bv.clone().map(keyF).transpose()?;142			}143		}144	}145	// a.len() > b.len()146	while let Some(_ac) = &ak {147		out.push(av.clone().expect("ak != None"));148		av = a.next();149		ak = av.clone().map(keyF).transpose()?;150	}151	// b.len() > a.len()152	while let Some(_bc) = &bk {153		out.push(bv.clone().expect("ak != None"));154		bv = b.next();155		bk = bv.clone().map(keyF).transpose()?;156	}157	Ok(ArrValue::lazy(out))158}