1use jrsonnet_gcmodule::{Cc, Trace};2use jrsonnet_interner::IBytes;3use jrsonnet_parser::LocExpr;45use crate::{function::FuncVal, Context, Result, Thunk, Val};67mod spec;8use spec::*;91011#[derive(Debug, Clone, Trace)]1213#[trace(tracking(force))]14pub enum ArrValue {15 16 Bytes(BytesArray),17 18 Lazy(LazyArray),19 20 Expr(ExprArray),21 22 Eager(EagerArray),23 24 Extended(Cc<ExtendedArray>),25 26 27 Range(RangeArray),28 29 Slice(Box<SliceArray>),30 31 32 Reverse(Box<ReverseArray>),33 34 Mapped(MappedArray),35}3637impl ArrValue {38 pub fn empty() -> Self {39 Self::Range(RangeArray::empty())40 }4142 pub fn expr(ctx: Context, exprs: impl IntoIterator<Item = LocExpr>) -> Self {43 Self::Expr(ExprArray::new(ctx, exprs))44 }4546 pub fn lazy(thunks: Cc<Vec<Thunk<Val>>>) -> Self {47 Self::Lazy(LazyArray(thunks))48 }4950 pub fn eager(values: Cc<Vec<Val>>) -> Self {51 Self::Eager(EagerArray(values))52 }5354 pub fn bytes(bytes: IBytes) -> Self {55 Self::Bytes(BytesArray(bytes))56 }5758 #[must_use]59 pub fn map(self, mapper: FuncVal) -> Self {60 Self::Mapped(MappedArray::new(self, mapper))61 }6263 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {64 65 let mut out = Vec::new();66 for i in self.iter() {67 let i = i?;68 if filter(&i)? {69 out.push(i);70 };71 }72 Ok(Self::eager(Cc::new(out)))73 }7475 pub fn extended(a: ArrValue, b: ArrValue) -> Self {76 77 const ARR_EXTEND_THRESHOLD: usize = 100;7879 if a.len() + b.len() > ARR_EXTEND_THRESHOLD {80 Self::Extended(Cc::new(ExtendedArray::new(a, b)))81 } else if let (Some(a), Some(b)) = (a.iter_cheap(), b.iter_cheap()) {82 let mut out = Vec::with_capacity(a.len() + b.len());83 out.extend(a);84 out.extend(b);85 Self::eager(Cc::new(out))86 } else {87 let mut out = Vec::with_capacity(a.len() + b.len());88 out.extend(a.iter_lazy());89 out.extend(b.iter_lazy());90 Self::lazy(Cc::new(out))91 }92 }9394 pub fn range_exclusive(a: i32, b: i32) -> Self {95 Self::Range(RangeArray::new_exclusive(a, b))96 }97 pub fn range_inclusive(a: i32, b: i32) -> Self {98 Self::Range(RangeArray::new_inclusive(a, b))99 }100101 #[must_use]102 pub fn slice(103 self,104 from: Option<usize>,105 to: Option<usize>,106 step: Option<usize>,107 ) -> Option<Self> {108 let len = self.len();109 let from = from.unwrap_or(0);110 let to = to.unwrap_or(len).min(len);111 let step = step.unwrap_or(1);112 if from >= to || step == 0 {113 return None;114 }115116 Some(Self::Slice(Box::new(SliceArray {117 inner: self,118 from: from as u32,119 to: to as u32,120 step: step as u32,121 })))122 }123124 125 pub fn len(&self) -> usize {126 pass!(self.len())127 }128129 130 pub fn is_empty(&self) -> bool {131 pass!(self.is_empty())132 }133134 135 136 137 pub fn get(&self, index: usize) -> Result<Option<Val>> {138 pass!(self.get(index))139 }140141 142 fn get_cheap(&self, index: usize) -> Option<Val> {143 pass!(self.get_cheap(index))144 }145146 147 148 149 pub fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {150 pass!(self.get_lazy(index))151 }152153 154 pub fn evaluatedcc(&self) -> Result<Cc<Vec<Val>>> {155 self.evaluated().map(Cc::new)156 }157 pub fn evaluated(&self) -> Result<Vec<Val>> {158 pass!(self.evaluated())159 }160161 162 pub fn iter(&self) -> UnknownArrayIter<'_> {163 pass_iter_call!(self.iter => UnknownArrayIter)164 }165166 167 pub fn iter_lazy(&self) -> UnknownArrayIterLazy<'_> {168 pass_iter_call!(self.iter_lazy => UnknownArrayIterLazy)169 }170171 pub fn iter_cheap(&self) -> Option<UnknownArrayIterCheap<'_>> {172 macro_rules! question {173 ($v:expr) => {174 $v?175 };176 }177 Some(pass_iter_call!(self.iter_cheap in question => UnknownArrayIterCheap))178 }179180 181 #[must_use]182 pub fn reversed(self) -> Self {183 Self::Reverse(Box::new(ReverseArray(self)))184 }185186 pub fn ptr_eq(a: &Self, b: &Self) -> bool {187 match (a, b) {188 (ArrValue::Bytes(a), ArrValue::Bytes(b)) => a.0 == b.0,189 (ArrValue::Lazy(a), ArrValue::Lazy(b)) => Cc::ptr_eq(&a.0, &b.0),190 (ArrValue::Expr(a), ArrValue::Expr(b)) => Cc::ptr_eq(&a.0, &b.0),191 (ArrValue::Eager(a), ArrValue::Eager(b)) => Cc::ptr_eq(&a.0, &b.0),192 (ArrValue::Extended(a), ArrValue::Extended(b)) => Cc::ptr_eq(&a, &b),193 (ArrValue::Range(a), ArrValue::Range(b)) => a == b,194 (ArrValue::Slice(_), ArrValue::Slice(_)) => false,195 (ArrValue::Reverse(_), ArrValue::Reverse(_)) => false,196 _ => false,197 }198 }199200 pub fn is_cheap(&self) -> bool {201 match self {202 ArrValue::Eager(_) | ArrValue::Range(..) | ArrValue::Bytes(_) => true,203 ArrValue::Extended(v) => v.a.is_cheap() && v.b.is_cheap(),204 ArrValue::Slice(r) => r.inner.is_cheap(),205 ArrValue::Reverse(i) => i.0.is_cheap(),206 ArrValue::Expr(_) | ArrValue::Lazy(_) | ArrValue::Mapped(_) => false,207 }208 }209}210impl From<Vec<Val>> for ArrValue {211 fn from(value: Vec<Val>) -> Self {212 Self::eager(Cc::new(value))213 }214}215impl From<Vec<Thunk<Val>>> for ArrValue {216 fn from(value: Vec<Thunk<Val>>) -> Self {217 Self::lazy(Cc::new(value))218 }219}220221#[cfg(target_pointer_width = "64")]222static_assertions::assert_eq_size!(ArrValue, [u8; 16]);