1use std::sync::Arc;
17use indexmap::IndexMap;
18
19use super::value::Val;
20use super::EvalError;
21use super::super::ast::KindType;
22
23#[inline]
26pub fn is_truthy(v: &Val) -> bool {
27 match v {
28 Val::Null => false,
29 Val::Bool(b) => *b,
30 Val::Int(n) => *n != 0,
31 Val::Float(f) => *f != 0.0,
32 Val::Str(s) => !s.is_empty(),
33 Val::StrSlice(r) => !r.is_empty(),
34 Val::Arr(a) => !a.is_empty(),
35 Val::IntVec(a) => !a.is_empty(),
36 Val::FloatVec(a) => !a.is_empty(),
37 Val::StrVec(a) => !a.is_empty(),
38 Val::StrSliceVec(a) => !a.is_empty(),
39 Val::ObjVec(d) => !d.rows.is_empty(),
40 Val::Obj(m) => !m.is_empty(),
41 Val::ObjSmall(p) => !p.is_empty(),
42 }
43}
44
45#[inline]
46pub fn kind_matches(v: &Val, ty: KindType) -> bool {
47 matches!((v, ty),
48 (Val::Null, KindType::Null) |
49 (Val::Bool(_), KindType::Bool) |
50 (Val::Int(_), KindType::Number) |
51 (Val::Float(_), KindType::Number) |
52 (Val::Str(_), KindType::Str) |
53 (Val::Arr(_), KindType::Array) |
54 (Val::IntVec(_), KindType::Array) |
55 (Val::FloatVec(_), KindType::Array) |
56 (Val::Obj(_), KindType::Object)
57 )
58}
59
60#[inline]
61pub fn vals_eq(a: &Val, b: &Val) -> bool {
62 match (a, b) {
63 (Val::Null, Val::Null) => true,
64 (Val::Bool(x), Val::Bool(y)) => x == y,
65 (Val::Str(x), Val::Str(y)) => x == y,
66 (Val::Int(x), Val::Int(y)) => x == y,
67 (Val::Float(x), Val::Float(y)) => x == y,
68 (Val::Int(x), Val::Float(y)) => (*x as f64) == *y,
69 (Val::Float(x), Val::Int(y)) => *x == (*y as f64),
70 _ => false,
71 }
72}
73
74#[inline]
75pub fn cmp_vals(a: &Val, b: &Val) -> std::cmp::Ordering {
76 match (a, b) {
77 (Val::Int(x), Val::Int(y)) => x.cmp(y),
78 (Val::Float(x), Val::Float(y)) => x.partial_cmp(y).unwrap_or(std::cmp::Ordering::Equal),
79 (Val::Int(x), Val::Float(y)) => (*x as f64).partial_cmp(y).unwrap_or(std::cmp::Ordering::Equal),
80 (Val::Float(x), Val::Int(y)) => x.partial_cmp(&(*y as f64)).unwrap_or(std::cmp::Ordering::Equal),
81 (Val::Str(x), Val::Str(y)) => x.cmp(y),
82 (Val::Bool(x), Val::Bool(y)) => x.cmp(y),
83 _ => std::cmp::Ordering::Equal,
84 }
85}
86
87#[inline]
91pub fn val_to_key(v: &Val) -> String {
92 match v {
93 Val::Str(s) => s.to_string(),
94 Val::Int(n) => n.to_string(),
95 Val::Float(f) => f.to_string(),
96 Val::Bool(b) => b.to_string(),
97 Val::Null => "null".to_string(),
98 other => val_to_string(other),
99 }
100}
101
102#[inline]
103pub fn val_to_string(v: &Val) -> String {
104 match v {
105 Val::Str(s) => s.to_string(),
106 Val::Int(n) => n.to_string(),
107 Val::Float(f) => f.to_string(),
108 Val::Bool(b) => b.to_string(),
109 Val::Null => "null".to_string(),
110 other => {
111 let sv: serde_json::Value = other.clone().into();
112 serde_json::to_string(&sv).unwrap_or_default()
113 }
114 }
115}
116
117#[inline] pub fn val_int(n: i64) -> Val { Val::Int(n) }
120#[inline] pub fn val_float(f: f64) -> Val { Val::Float(f) }
121#[inline] pub fn val_str(s: &str) -> Val { Val::Str(Arc::from(s)) }
122#[inline] pub fn val_key(s: &str) -> Arc<str> { Arc::from(s) }
123
124pub fn add_vals(a: Val, b: Val) -> Result<Val, EvalError> {
127 match (a, b) {
128 (Val::Int(x), Val::Int(y)) => Ok(Val::Int(x + y)),
129 (Val::Float(x), Val::Float(y)) => Ok(Val::Float(x + y)),
130 (Val::Int(x), Val::Float(y)) => Ok(Val::Float(x as f64 + y)),
131 (Val::Float(x), Val::Int(y)) => Ok(Val::Float(x + y as f64)),
132 (Val::Str(x), Val::Str(y)) => {
133 let mut s = String::with_capacity(x.len() + y.len());
137 s.push_str(&x);
138 s.push_str(&y);
139 Ok(Val::Str(Arc::<str>::from(s)))
140 }
141 (Val::Arr(x), Val::Arr(y)) => {
142 let mut v = Arc::try_unwrap(x).unwrap_or_else(|a| (*a).clone());
143 v.extend_from_slice(&y);
144 Ok(Val::arr(v))
145 }
146 _ => Err(EvalError("+ not supported between these types".into())),
147 }
148}
149
150pub fn num_op<Fi, Ff>(a: Val, b: Val, fi: Fi, ff: Ff) -> Result<Val, EvalError>
151where
152 Fi: Fn(i64, i64) -> i64,
153 Ff: Fn(f64, f64) -> f64,
154{
155 match (a, b) {
156 (Val::Int(x), Val::Int(y)) => Ok(Val::Int(fi(x, y))),
157 (Val::Float(x), Val::Float(y)) => Ok(Val::Float(ff(x, y))),
158 (Val::Int(x), Val::Float(y)) => Ok(Val::Float(ff(x as f64, y))),
159 (Val::Float(x), Val::Int(y)) => Ok(Val::Float(ff(x, y as f64))),
160 _ => Err(EvalError("arithmetic on non-numbers".into())),
161 }
162}
163
164pub fn flatten_val(v: Val, depth: usize) -> Val {
167 match v {
168 Val::Arr(a) if depth > 0 => {
169 let items = Arc::try_unwrap(a).unwrap_or_else(|a| (*a).clone());
170 let all_int_children = !items.is_empty() && items.iter().all(|it| matches!(it,
174 Val::IntVec(_) | Val::Int(_)
175 ));
176 if all_int_children {
177 let cap: usize = items.iter().map(|it| match it {
178 Val::IntVec(inner) => inner.len(),
179 _ => 1,
180 }).sum();
181 let mut out: Vec<i64> = Vec::with_capacity(cap);
182 for item in items {
183 match item {
184 Val::IntVec(inner) => out.extend(inner.iter().copied()),
185 Val::Int(n) => out.push(n),
186 _ => unreachable!(),
187 }
188 }
189 return Val::int_vec(out);
190 }
191 let all_float_children = !items.is_empty() && items.iter().all(|it| matches!(it,
192 Val::FloatVec(_) | Val::Float(_) | Val::Int(_)
193 ));
194 if all_float_children {
195 let cap: usize = items.iter().map(|it| match it {
196 Val::FloatVec(inner) => inner.len(),
197 _ => 1,
198 }).sum();
199 let mut out: Vec<f64> = Vec::with_capacity(cap);
200 for item in items {
201 match item {
202 Val::FloatVec(inner) => out.extend(inner.iter().copied()),
203 Val::Float(f) => out.push(f),
204 Val::Int(n) => out.push(n as f64),
205 _ => unreachable!(),
206 }
207 }
208 return Val::float_vec(out);
209 }
210 let cap: usize = items.iter().map(|it| match it {
214 Val::Arr(inner) => inner.len(),
215 Val::IntVec(inner) => inner.len(),
216 Val::FloatVec(inner) => inner.len(),
217 Val::StrVec(inner) => inner.len(),
218 _ => 1,
219 }).sum();
220 let mut out = Vec::with_capacity(cap);
221 for item in items {
222 match item {
223 Val::Arr(_) => match flatten_val(item, depth - 1) {
224 Val::Arr(inner) => {
225 out.extend(Arc::try_unwrap(inner).unwrap_or_else(|a| (*a).clone()));
226 }
227 Val::IntVec(inner) => {
228 out.extend(inner.iter().map(|n| Val::Int(*n)));
229 }
230 Val::FloatVec(inner) => {
231 out.extend(inner.iter().map(|f| Val::Float(*f)));
232 }
233 Val::StrVec(inner) => {
234 out.extend(inner.iter().map(|s| Val::Str(s.clone())));
235 }
236 _ => {}
237 },
238 Val::IntVec(inner) => {
239 out.extend(inner.iter().map(|n| Val::Int(*n)));
241 }
242 Val::FloatVec(inner) => {
243 out.extend(inner.iter().map(|f| Val::Float(*f)));
244 }
245 Val::StrVec(inner) => {
246 out.extend(inner.iter().map(|s| Val::Str(s.clone())));
247 }
248 other => out.push(other),
249 }
250 }
251 Val::arr(out)
252 }
253 Val::IntVec(_) | Val::FloatVec(_) | Val::StrVec(_) => v,
255 other => other,
256 }
257}
258
259pub fn zip_arrays(a: Val, b: Val, longest: bool, fill: Val) -> Result<Val, EvalError> {
260 let av = a.as_vals().map(|c| c.into_owned()).unwrap_or_default();
261 let bv = b.as_vals().map(|c| c.into_owned()).unwrap_or_default();
262 let len = if longest { av.len().max(bv.len()) } else { av.len().min(bv.len()) };
263 Ok(Val::arr((0..len).map(|i| Val::arr(vec![
264 av.get(i).cloned().unwrap_or_else(|| fill.clone()),
265 bv.get(i).cloned().unwrap_or_else(|| fill.clone()),
266 ])).collect()))
267}
268
269pub fn cartesian(arrays: &[Vec<Val>]) -> Vec<Vec<Val>> {
270 arrays.iter().fold(vec![vec![]], |acc, arr| {
271 acc.into_iter().flat_map(|prefix| {
272 arr.iter().map(move |item| {
273 let mut row = prefix.clone();
274 row.push(item.clone());
275 row
276 }).collect::<Vec<_>>()
277 }).collect()
278 })
279}
280
281pub fn field_exists_nested(v: &Val, path: &str) -> bool {
284 let mut parts = path.splitn(2, '.');
285 let first = parts.next().unwrap_or("");
286 match (v.get(first), parts.next()) {
287 (Some(v), _) if v.is_null() => false,
288 (Some(_), None) => true,
289 (Some(child), Some(rest)) => field_exists_nested(child, rest),
290 (None, _) => false,
291 }
292}
293
294pub fn deep_merge(base: Val, other: Val) -> Val {
297 match (base, other) {
298 (Val::Obj(bm), Val::Obj(om)) => {
299 let mut map = Arc::try_unwrap(bm).unwrap_or_else(|m| (*m).clone());
300 for (k, v) in Arc::try_unwrap(om).unwrap_or_else(|m| (*m).clone()) {
301 let existing = map.shift_remove(&k);
302 map.insert(k, match existing {
303 Some(e) => deep_merge(e, v),
304 None => v,
305 });
306 }
307 Val::obj(map)
308 }
309 (_, other) => other,
310 }
311}
312
313pub fn deep_merge_concat(base: Val, other: Val) -> Val {
316 match (base, other) {
317 (Val::Obj(bm), Val::Obj(om)) => {
318 let mut map = Arc::try_unwrap(bm).unwrap_or_else(|m| (*m).clone());
319 for (k, v) in Arc::try_unwrap(om).unwrap_or_else(|m| (*m).clone()) {
320 let existing = map.shift_remove(&k);
321 map.insert(k, match existing {
322 Some(e) => deep_merge_concat(e, v),
323 None => v,
324 });
325 }
326 Val::obj(map)
327 }
328 (Val::Arr(ba), Val::Arr(oa)) => {
329 let mut a = Arc::try_unwrap(ba).unwrap_or_else(|a| (*a).clone());
330 for v in Arc::try_unwrap(oa).unwrap_or_else(|a| (*a).clone()) { a.push(v); }
331 Val::arr(a)
332 }
333 (base, other)
334 if (base.is_array() && other.is_array())
335 && (matches!(&base, Val::StrVec(_) | Val::IntVec(_) | Val::FloatVec(_))
336 || matches!(&other, Val::StrVec(_) | Val::IntVec(_) | Val::FloatVec(_))) =>
337 {
338 let mut a = base.into_vec().unwrap_or_default();
339 if let Some(v) = other.into_vec() { a.extend(v); }
340 Val::arr(a)
341 }
342 (_, other) => other,
343 }
344}
345
346pub fn obj2(k1: &str, v1: Val, k2: &str, v2: Val) -> Val {
350 let mut m = IndexMap::with_capacity(2);
351 m.insert(val_key(k1), v1);
352 m.insert(val_key(k2), v2);
353 Val::obj(m)
354}