rs_json_filter_cel/
lib.rs1use std::io;
2
3use io::BufRead;
4
5use serde_json::Value;
6
7use cel::{Context, Program};
8
9pub struct CelValue(pub cel::Value);
10
11impl CelValue {
12 pub fn to_bool(&self) -> Option<bool> {
13 match self.0 {
14 cel::Value::Bool(b) => Some(b),
15 _ => None,
16 }
17 }
18}
19
20pub struct CelProgram(pub Program);
21
22impl CelProgram {
23 pub fn execute(&self, ctx: &Context) -> Result<CelValue, io::Error> {
24 self.0.execute(ctx).map(CelValue).map_err(io::Error::other)
25 }
26
27 pub fn execute_with_value(
28 &self,
29 ctx: &Context,
30 vname: &str,
31 val: Value,
32 ) -> Result<CelValue, io::Error> {
33 let mut child: Context = ctx.new_inner_scope();
34 child.add_variable(vname, val).map_err(io::Error::other)?;
35 self.execute(&child)
36 }
37
38 pub fn filter_value(&self, ctx: &Context, vname: &str, val: &Value) -> Result<bool, io::Error> {
39 let cv: CelValue = self.execute_with_value(ctx, vname, val.clone())?;
40 let ob: Option<bool> = cv.to_bool();
41 ob.ok_or(io::Error::other("bool expected"))
42 }
43}
44
45impl CelProgram {
46 pub fn jsons2filtered<I>(
47 self,
48 jsons: I,
49 ctx: Context,
50 vname: String,
51 ) -> impl Iterator<Item = Result<Value, io::Error>>
52 where
53 I: Iterator<Item = Result<Value, io::Error>>,
54 {
55 jsons.filter(move |rv| match rv {
56 Ok(v) => {
57 let rflt = self.filter_value(&ctx, &vname, v);
58 rflt.unwrap_or(false)
59 }
60 Err(_e) => true,
61 })
62 }
63}
64
65pub fn compile(expr: &str) -> Result<CelProgram, io::Error> {
66 Program::compile(expr)
67 .map(CelProgram)
68 .map_err(io::Error::other)
69}
70
71pub fn rdr2jsons<R>(rdr: R) -> impl Iterator<Item = Result<Value, io::Error>>
72where
73 R: BufRead,
74{
75 rdr.lines()
76 .map(|rline| rline.and_then(|line| serde_json::from_str(&line).map_err(io::Error::other)))
77}
78
79pub fn stdin2jsons() -> impl Iterator<Item = Result<Value, io::Error>> {
80 rdr2jsons(io::stdin().lock())
81}