1use jrsonnet_evaluator::{2 error::Result,3 function::{builtin, FuncVal},4 throw,5 typed::{Any, BoundedUsize, Either2, NativeFn, Typed, VecVal},6 val::{equals, ArrValue, IndexableVal},7 Either, IStr, Val,8};9use jrsonnet_gcmodule::Cc;1011#[builtin]12pub fn builtin_make_array(sz: usize, func: NativeFn<((f64,), Any)>) -> Result<VecVal> {13 let mut out = Vec::with_capacity(sz);14 for i in 0..sz {15 out.push(func(i as f64)?.0);16 }17 Ok(VecVal(Cc::new(out)))18}1920#[builtin]21pub fn builtin_slice(22 indexable: IndexableVal,23 index: Option<BoundedUsize<0, { i32::MAX as usize }>>,24 end: Option<BoundedUsize<0, { i32::MAX as usize }>>,25 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,26) -> Result<Any> {27 indexable.slice(index, end, step).map(Val::from).map(Any)28}2930#[builtin]31pub fn builtin_map(func: NativeFn<((Any,), Any)>, arr: ArrValue) -> Result<ArrValue> {32 arr.map(|val| Ok(func(Any(val))?.0))33}3435#[builtin]36pub fn builtin_flatmap(37 func: NativeFn<((Either![String, Any],), Any)>,38 arr: IndexableVal,39) -> Result<IndexableVal> {40 match arr {41 IndexableVal::Str(str) => {42 let mut out = String::new();43 for c in str.chars() {44 match func(Either2::A(c.to_string()))?.0 {45 Val::Str(o) => out.push_str(&o),46 Val::Null => continue,47 _ => throw!("in std.join all items should be strings"),48 };49 }50 Ok(IndexableVal::Str(out.into()))51 }52 IndexableVal::Arr(a) => {53 let mut out = Vec::new();54 for el in a.iter() {55 let el = el?;56 match func(Either2::B(Any(el)))?.0 {57 Val::Arr(o) => {58 for oe in o.iter() {59 out.push(oe?);60 }61 }62 Val::Null => continue,63 _ => throw!("in std.join all items should be arrays"),64 };65 }66 Ok(IndexableVal::Arr(out.into()))67 }68 }69}7071#[builtin]72pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {73 arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(Any(val.clone()),))?))74}7576#[builtin]77pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {78 let mut acc = init.0;79 for i in arr.iter() {80 acc = func.evaluate_simple(&(Any(acc), Any(i?)))?;81 }82 Ok(Any(acc))83}8485#[builtin]86pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {87 let mut acc = init.0;88 for i in arr.iter().rev() {89 acc = func.evaluate_simple(&(Any(i?), Any(acc)))?;90 }91 Ok(Any(acc))92}9394#[builtin]95pub fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {96 if to < from {97 return Ok(ArrValue::new_eager());98 }99 Ok(ArrValue::new_range(from, to))100}101102#[builtin]103pub fn builtin_join(sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {104 Ok(match sep {105 IndexableVal::Arr(joiner_items) => {106 let mut out = Vec::new();107108 let mut first = true;109 for item in arr.iter() {110 let item = item?.clone();111 if let Val::Arr(items) = item {112 if !first {113 out.reserve(joiner_items.len());114 115 for item in joiner_items.iter() {116 out.push(item?);117 }118 }119 first = false;120 out.reserve(items.len());121 for item in items.iter() {122 out.push(item?);123 }124 } else if matches!(item, Val::Null) {125 continue;126 } else {127 throw!("in std.join all items should be arrays");128 }129 }130131 IndexableVal::Arr(out.into())132 }133 IndexableVal::Str(sep) => {134 let mut out = String::new();135136 let mut first = true;137 for item in arr.iter() {138 let item = item?.clone();139 if let Val::Str(item) = item {140 if !first {141 out += &sep;142 }143 first = false;144 out += &item;145 } else if matches!(item, Val::Null) {146 continue;147 } else {148 throw!("in std.join all items should be strings");149 }150 }151152 IndexableVal::Str(out.into())153 }154 })155}156157#[builtin]158pub fn builtin_reverse(value: ArrValue) -> Result<ArrValue> {159 Ok(value.reversed())160}161162#[builtin]163pub fn builtin_any(arr: ArrValue) -> Result<bool> {164 for v in arr.iter() {165 let v = bool::from_untyped(v?)?;166 if v {167 return Ok(true);168 }169 }170 Ok(false)171}172173#[builtin]174pub fn builtin_all(arr: ArrValue) -> Result<bool> {175 for v in arr.iter() {176 let v = bool::from_untyped(v?)?;177 if !v {178 return Ok(false);179 }180 }181 Ok(true)182}183184#[builtin]185pub fn builtin_member(arr: IndexableVal, x: Any) -> Result<bool> {186 match arr {187 IndexableVal::Str(str) => {188 let x: IStr = IStr::from_untyped(x.0)?;189 Ok(!x.is_empty() && str.contains(&*x))190 }191 IndexableVal::Arr(a) => {192 for item in a.iter() {193 let item = item?;194 if equals(&item, &x.0)? {195 return Ok(true);196 }197 }198 Ok(false)199 }200 }201}202203#[builtin]204pub fn builtin_count(arr: Vec<Any>, v: Any) -> Result<usize> {205 let mut count = 0;206 for item in &arr {207 if equals(&item.0, &v.0)? {208 count += 1;209 }210 }211 Ok(count)212}