git.delta.rocks / jrsonnet / refs/commits / 773438d8aef3

difftreelog

source

crates/jrsonnet-stdlib/src/sets.rs2.9 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}73#[builtin]74#[allow(non_snake_case, clippy::redundant_closure)]75pub fn builtin_set_diff(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {76	let mut a = a.iter_lazy();77	let mut b = b.iter_lazy();7879	let keyF = keyF80		.unwrap_or(FuncVal::identity())81		.into_native::<((Thunk<Val>,), Val)>();82	let keyF = |v| keyF(v);8384	let mut av = a.next();85	let mut bv = b.next();86	let mut ak = av.clone().map(keyF).transpose()?;87	let mut bk = bv.map(keyF).transpose()?;8889	let mut out = Vec::new();90	while let (Some(ac), Some(bc)) = (&ak, &bk) {91		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {92			Ordering::Less => {93				// In a, but not in b94				out.push(av.clone().expect("ak != None"));95				av = a.next();96				ak = av.clone().map(keyF).transpose()?;97			}98			Ordering::Greater => {99				bv = b.next();100				bk = bv.map(keyF).transpose()?;101			}102			Ordering::Equal => {103				av = a.next();104				ak = av.clone().map(keyF).transpose()?;105				bv = b.next();106				bk = bv.map(keyF).transpose()?;107			}108		};109	}110	while let Some(_ac) = &ak {111		// In a, but not in b112		out.push(av.clone().expect("ak != None"));113		av = a.next();114		ak = av.clone().map(keyF).transpose()?;115	}116	Ok(ArrValue::lazy(out))117}