platelet/
for_loop_runner.rs

1use serde_json::Value;
2
3use crate::{
4    expression_eval::{eval, EvalError},
5    for_loop_parser::ForLoop,
6    types::{type_of, Type},
7};
8
9#[derive(Debug, PartialEq)]
10pub enum Error {
11    TypeMismatch { expected: Vec<Type>, found: Type },
12    Eval(EvalError),
13}
14
15pub(crate) fn for_loop_runner(
16    for_loop: &ForLoop,
17    base_context: &Value,
18) -> Result<Vec<Value>, Error> {
19    match for_loop {
20        ForLoop::Simple(id, exp) => {
21            let val = eval(exp, base_context).map_err(Error::Eval)?;
22            match val {
23                Value::Array(vec) => Ok(vec
24                    .iter()
25                    .map(|v| {
26                        let mut obj = base_context.as_object().unwrap().clone();
27                        obj.insert(id.clone(), v.clone());
28                        Value::Object(obj)
29                    })
30                    .collect()),
31                _ => Err(Error::TypeMismatch {
32                    expected: vec![Type::Array],
33                    found: type_of(&val),
34                }),
35            }
36        }
37        ForLoop::IndexedObjectOrKeyValue(ids, exp) => {
38            let val = eval(exp, base_context).map_err(Error::Eval)?;
39            match val {
40                Value::Array(vec) => {
41                    let (id, indexer) = ids;
42                    Ok(vec
43                        .iter()
44                        .enumerate()
45                        .map(|(index, v)| {
46                            let mut obj = base_context.as_object().unwrap().clone();
47                            obj.insert(id.clone(), v.clone());
48                            obj.insert(indexer.clone(), index.clone().into());
49                            Value::Object(obj)
50                        })
51                        .collect())
52                }
53                Value::Object(vec) => {
54                    let (key_id, value_id) = ids;
55                    Ok(vec
56                        .iter()
57                        .map(|(k, v)| {
58                            let mut obj = base_context.as_object().unwrap().clone();
59                            obj.insert(key_id.clone(), k.clone().into());
60                            obj.insert(value_id.clone(), v.clone());
61                            Value::Object(obj)
62                        })
63                        .collect())
64                }
65                _ => Err(Error::TypeMismatch {
66                    expected: vec![Type::Array, Type::Object],
67                    found: type_of(&val),
68                }),
69            }
70        }
71        ForLoop::IndexedKeyValue(ids, exp) => {
72            let val = eval(exp, base_context).map_err(Error::Eval)?;
73            match val {
74                Value::Object(vec) => {
75                    let (key_id, value_id, indexer) = ids;
76                    Ok(vec
77                        .iter()
78                        .enumerate()
79                        .map(|(index, (k, v))| {
80                            let mut obj = base_context.as_object().unwrap().clone();
81                            obj.insert(key_id.clone(), k.clone().into());
82                            obj.insert(value_id.clone(), v.clone());
83                            obj.insert(indexer.clone(), index.clone().into());
84                            Value::Object(obj)
85                        })
86                        .collect())
87                }
88                _ => Err(Error::TypeMismatch {
89                    expected: vec![Type::Object],
90                    found: type_of(&val),
91                }),
92            }
93        }
94    }
95}