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}7374#[builtin]75#[allow(non_snake_case, clippy::redundant_closure)]76pub fn builtin_set_diff(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {77 let mut a = a.iter_lazy();78 let mut b = b.iter_lazy();7980 let keyF = keyF81 .unwrap_or(FuncVal::identity())82 .into_native::<((Thunk<Val>,), Val)>();83 let keyF = |v| keyF(v);8485 let mut av = a.next();86 let mut bv = b.next();87 let mut ak = av.clone().map(keyF).transpose()?;88 let mut bk = bv.map(keyF).transpose()?;8990 let mut out = Vec::new();91 while let (Some(ac), Some(bc)) = (&ak, &bk) {92 match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {93 Ordering::Less => {94 95 out.push(av.clone().expect("ak != None"));96 av = a.next();97 ak = av.clone().map(keyF).transpose()?;98 }99 Ordering::Greater => {100 bv = b.next();101 bk = bv.map(keyF).transpose()?;102 }103 Ordering::Equal => {104 av = a.next();105 ak = av.clone().map(keyF).transpose()?;106 bv = b.next();107 bk = bv.map(keyF).transpose()?;108 }109 };110 }111 while let Some(_ac) = &ak {112 113 out.push(av.clone().expect("ak != None"));114 av = a.next();115 ak = av.clone().map(keyF).transpose()?;116 }117 Ok(ArrValue::lazy(out))118}119120#[builtin]121#[allow(non_snake_case, clippy::redundant_closure)]122pub fn builtin_set_union(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {123 let mut a = a.iter_lazy();124 let mut b = b.iter_lazy();125126 let keyF = keyF127 .unwrap_or(FuncVal::identity())128 .into_native::<((Thunk<Val>,), Val)>();129 let keyF = |v| keyF(v);130131 let mut av = a.next();132 let mut bv = b.next();133 let mut ak = av.clone().map(keyF).transpose()?;134 let mut bk = bv.clone().map(keyF).transpose()?;135136 let mut out = Vec::new();137 while let (Some(ac), Some(bc)) = (&ak, &bk) {138 match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {139 Ordering::Less => {140 out.push(av.clone().expect("ak != None"));141 av = a.next();142 ak = av.clone().map(keyF).transpose()?;143 }144 Ordering::Greater => {145 out.push(bv.clone().expect("bk != None"));146 bv = b.next();147 bk = bv.clone().map(keyF).transpose()?;148 }149 Ordering::Equal => {150 151 out.push(av.clone().expect("ak != None"));152 av = a.next();153 ak = av.clone().map(keyF).transpose()?;154 bv = b.next();155 bk = bv.clone().map(keyF).transpose()?;156 }157 };158 }159 160 while let Some(_ac) = &ak {161 out.push(av.clone().expect("ak != None"));162 av = a.next();163 ak = av.clone().map(keyF).transpose()?;164 }165 166 while let Some(_bc) = &bk {167 out.push(bv.clone().expect("ak != None"));168 bv = b.next();169 bk = bv.clone().map(keyF).transpose()?;170 }171 Ok(ArrValue::lazy(out))172}