1use std::cmp::Ordering;23use jrsonnet_evaluator::{4 Result, Thunk, Val, function::builtin, operator::evaluate_compare_op, val::ArrValue,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(33 a: ArrValue,34 b: ArrValue,35 #[default] keyF: KeyF,36) -> Result<Vec<Thunk<Val>>> {37 let mut a = a.iter_lazy();38 let mut b = b.iter_lazy();3940 let keyF = |v| keyF.eval(v);4142 let mut av = a.next();43 let mut bv = b.next();44 let mut ak = av.clone().map(keyF).transpose()?;45 let mut bk = bv.map(keyF).transpose()?;4647 let mut out = Vec::new();48 while let (Some(ac), Some(bc)) = (&ak, &bk) {49 match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {50 Ordering::Less => {51 av = a.next();52 ak = av.clone().map(keyF).transpose()?;53 }54 Ordering::Greater => {55 bv = b.next();56 bk = bv.map(keyF).transpose()?;57 }58 Ordering::Equal => {59 out.push(av.clone().expect("ak != None => av != None"));60 av = a.next();61 ak = av.clone().map(keyF).transpose()?;62 bv = b.next();63 bk = bv.map(keyF).transpose()?;64 }65 }66 }67 Ok(out)68}6970#[builtin]71#[allow(non_snake_case, clippy::redundant_closure)]72pub fn builtin_set_diff(73 a: ArrValue,74 b: ArrValue,75 #[default] keyF: KeyF,76) -> Result<Vec<Thunk<Val>>> {77 let mut a = a.iter_lazy();78 let mut b = b.iter_lazy();7980 let keyF = |v| keyF.eval(v);8182 let mut av = a.next();83 let mut bv = b.next();84 let mut ak = av.clone().map(keyF).transpose()?;85 let mut bk = bv.map(keyF).transpose()?;8687 let mut out = Vec::new();88 while let (Some(ac), Some(bc)) = (&ak, &bk) {89 match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {90 Ordering::Less => {91 92 out.push(av.clone().expect("ak != None"));93 av = a.next();94 ak = av.clone().map(keyF).transpose()?;95 }96 Ordering::Greater => {97 bv = b.next();98 bk = bv.map(keyF).transpose()?;99 }100 Ordering::Equal => {101 av = a.next();102 ak = av.clone().map(keyF).transpose()?;103 bv = b.next();104 bk = bv.map(keyF).transpose()?;105 }106 }107 }108 while let Some(_ac) = &ak {109 110 out.push(av.clone().expect("ak != None"));111 av = a.next();112 ak = av.clone().map(keyF).transpose()?;113 }114 Ok(out)115}116117#[builtin]118#[allow(non_snake_case, clippy::redundant_closure)]119pub fn builtin_set_union(120 a: ArrValue,121 b: ArrValue,122 #[default] keyF: KeyF,123) -> Result<Vec<Thunk<Val>>> {124 let mut a = a.iter_lazy();125 let mut b = b.iter_lazy();126127 let keyF = |v| keyF.eval(v);128129 let mut av = a.next();130 let mut bv = b.next();131 let mut ak = av.clone().map(keyF).transpose()?;132 let mut bk = bv.clone().map(keyF).transpose()?;133134 let mut out = Vec::new();135 while let (Some(ac), Some(bc)) = (&ak, &bk) {136 match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {137 Ordering::Less => {138 out.push(av.clone().expect("ak != None"));139 av = a.next();140 ak = av.clone().map(keyF).transpose()?;141 }142 Ordering::Greater => {143 out.push(bv.clone().expect("bk != None"));144 bv = b.next();145 bk = bv.clone().map(keyF).transpose()?;146 }147 Ordering::Equal => {148 149 out.push(av.clone().expect("ak != None"));150 av = a.next();151 ak = av.clone().map(keyF).transpose()?;152 bv = b.next();153 bk = bv.clone().map(keyF).transpose()?;154 }155 }156 }157 158 while let Some(_ac) = &ak {159 out.push(av.clone().expect("ak != None"));160 av = a.next();161 ak = av.clone().map(keyF).transpose()?;162 }163 164 while let Some(_bc) = &bk {165 out.push(bv.clone().expect("ak != None"));166 bv = b.next();167 bk = bv.clone().map(keyF).transpose()?;168 }169 Ok(out)170}