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_gcmodule::Cc;11use jrsonnet_parser::BinaryOpType;1213#[builtin]14#[allow(non_snake_case)]15pub fn builtin_set_member(x: Thunk<Val>, arr: ArrValue, keyF: Option<FuncVal>) -> Result<bool> {16 let mut low = 0;17 let mut high = arr.len();1819 let keyF = keyF20 .unwrap_or(FuncVal::Id)21 .into_native::<((Thunk<Val>,), Val)>();2223 let x = keyF(x)?;2425 while low < high {26 let middle = (high + low) / 2;27 let comp = keyF(arr.get_lazy(middle).expect("in bounds"))?;28 match evaluate_compare_op(&comp, &x, BinaryOpType::Lt)? {29 Ordering::Less => low = middle + 1,30 Ordering::Equal => return Ok(true),31 Ordering::Greater => high = middle,32 }33 }34 Ok(false)35}3637#[builtin]38#[allow(non_snake_case)]39pub fn builtin_set_inter(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {40 let mut a = a.iter_lazy();41 let mut b = b.iter_lazy();4243 let keyF = keyF44 .unwrap_or(FuncVal::identity())45 .into_native::<((Thunk<Val>,), Val)>();46 let keyF = |v| keyF(v);4748 let mut av = a.next();49 let mut bv = b.next();50 let mut ak = av.clone().map(keyF).transpose()?;51 let mut bk = bv.map(keyF).transpose()?;5253 let mut out = Vec::new();54 while let (Some(ac), Some(bc)) = (&ak, &bk) {55 match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {56 Ordering::Less => {57 av = a.next();58 ak = av.clone().map(keyF).transpose()?;59 }60 Ordering::Greater => {61 bv = b.next();62 bk = bv.map(keyF).transpose()?;63 }64 Ordering::Equal => {65 out.push(av.clone().expect("ak != None => av != None"));66 av = a.next();67 ak = av.clone().map(keyF).transpose()?;68 bv = b.next();69 bk = bv.map(keyF).transpose()?;70 }71 };72 }73 Ok(ArrValue::lazy(Cc::new(out)))74}