rs_json_map_cel/
lib.rs

1use std::io;
2use std::io::BufRead;
3
4use serde_json::{Map, Value, json};
5
6use cel::{Context, Program};
7
8pub struct CelValue(pub cel::Value);
9
10impl From<CelValue> for serde_json::Value {
11    fn from(wrapper_cel_value: CelValue) -> Self {
12        let cel_value = wrapper_cel_value.0;
13        match cel_value {
14            cel::Value::Null => serde_json::Value::Null,
15            cel::Value::Bool(b) => serde_json::Value::Bool(b),
16            cel::Value::Int(i) => json!(i),
17            cel::Value::UInt(u) => json!(u),
18            cel::Value::Float(f) => json!(f),
19            cel::Value::String(s) => serde_json::Value::String(s.to_string()),
20            cel::Value::List(list) => {
21                let values: &[cel::Value] = &list;
22                serde_json::Value::Array(
23                    values.iter().map(|v| CelValue(v.clone()).into()).collect(),
24                )
25            }
26            cel::Value::Map(map_obj) => {
27                let mut json_map = Map::new();
28                for (key, val) in map_obj.map.iter() {
29                    // Convert &Key to cel::Value
30                    let cel_key_value: cel::Value = key.into(); // Use the From<&Key> for Value impl
31
32                    let key_str = match cel_key_value {
33                        cel::Value::String(s) => s.to_string(),
34                        _ => format!("{:?}", cel_key_value), // Fallback for non-string keys
35                    };
36                    json_map.insert(key_str, CelValue(val.clone()).into());
37                }
38                serde_json::Value::Object(json_map)
39            }
40            _ => serde_json::Value::String(format!("{:?}", cel_value)),
41        }
42    }
43}
44
45pub struct CelProgram(pub Program);
46
47impl CelProgram {
48    pub fn execute(&self, ctx: &Context) -> Result<cel::Value, io::Error> {
49        self.0.execute(ctx).map_err(io::Error::other)
50    }
51
52    pub fn execute_with_value(
53        &self,
54        ctx: &Context,
55        vname: &str,
56        val: Value,
57    ) -> Result<cel::Value, io::Error> {
58        let mut child: Context = ctx.new_inner_scope();
59        child.add_variable(vname, val).map_err(io::Error::other)?;
60        self.execute(&child)
61    }
62
63    pub fn jsons2mapped<I>(
64        self,
65        jsons: I,
66        ctx: Context,
67        vname: String,
68    ) -> impl Iterator<Item = Result<Value, io::Error>>
69    where
70        I: Iterator<Item = Result<Value, io::Error>>,
71    {
72        jsons.map(move |rv| match rv {
73            Ok(v) => {
74                let mapped_cel_value = self.execute_with_value(&ctx, &vname, v)?;
75                Ok(CelValue(mapped_cel_value).into())
76            }
77            Err(e) => Err(e),
78        })
79    }
80}
81
82pub fn compile(expr: &str) -> Result<CelProgram, io::Error> {
83    Program::compile(expr)
84        .map(CelProgram)
85        .map_err(io::Error::other)
86}
87
88pub fn rdr2jsons<R>(rdr: R) -> impl Iterator<Item = Result<Value, io::Error>>
89where
90    R: BufRead,
91{
92    rdr.lines()
93        .map(|rline| rline.and_then(|line| serde_json::from_str(&line).map_err(io::Error::other)))
94}
95
96pub fn stdin2jsons() -> impl Iterator<Item = Result<Value, io::Error>> {
97    rdr2jsons(io::stdin().lock())
98}