1use std::cmp::Ordering;23use jrsonnet_evaluator::{4 error::Result,5 function::{builtin, FuncVal},6 operator::evaluate_compare_op,7 val::ArrValue,8 Thunk, Val,9};10use jrsonnet_parser::BinaryOpType;1112#[builtin]13#[allow(non_snake_case)]14pub fn builtin_set_member(x: Thunk<Val>, arr: ArrValue, keyF: Option<FuncVal>) -> Result<bool> {15 let mut low = 0;16 let mut high = arr.len();1718 let keyF = keyF19 .unwrap_or(FuncVal::Id)20 .into_native::<((Thunk<Val>,), Val)>();2122 let x = keyF(x)?;2324 while low < high {25 let middle = (high + low) / 2;26 let comp = keyF(arr.get_lazy(middle).expect("in bounds"))?;27 match evaluate_compare_op(&comp, &x, BinaryOpType::Lt)? {28 Ordering::Less => low = middle + 1,29 Ordering::Equal => return Ok(true),30 Ordering::Greater => high = middle,31 }32 }33 Ok(false)34}3536#[builtin]37#[allow(non_snake_case, clippy::redundant_closure)]38pub fn builtin_set_inter(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {39 let mut a = a.iter_lazy();40 let mut b = b.iter_lazy();4142 let keyF = keyF43 .unwrap_or(FuncVal::identity())44 .into_native::<((Thunk<Val>,), Val)>();45 let keyF = |v| keyF(v);4647 let mut av = a.next();48 let mut bv = b.next();49 let mut ak = av.clone().map(keyF).transpose()?;50 let mut bk = bv.map(keyF).transpose()?;5152 let mut out = Vec::new();53 while let (Some(ac), Some(bc)) = (&ak, &bk) {54 match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {55 Ordering::Less => {56 av = a.next();57 ak = av.clone().map(keyF).transpose()?;58 }59 Ordering::Greater => {60 bv = b.next();61 bk = bv.map(keyF).transpose()?;62 }63 Ordering::Equal => {64 out.push(av.clone().expect("ak != None => av != None"));65 av = a.next();66 ak = av.clone().map(keyF).transpose()?;67 bv = b.next();68 bk = bv.map(keyF).transpose()?;69 }70 };71 }72 Ok(ArrValue::lazy(out))73}