Constructing rust types in cel
From the cle doc it seems like it's possible to construct strongly typed types inside cel and pass them back. Does cel-rust support this? Couldn't find documentation about this.
Example:
use cel_interpreter::{Context, Program};
use serde::Serialize;
// An example struct that derives Serialize
#[derive(Serialize)]
struct MyStruct {
a: i32,
b: i32,
}
fn main() {
let program = Program::compile("MyStruct { a: 0, b: 0}").unwrap();
let context = Context::default();
let value = program.execute(&context).unwrap();
assert_eq!(value, true.into());
println!("{value:?}");
}
This is not supported today. I believe the cel-go project supports this via protobufs. It's definitely something that we need to support to be spec-compliant.
Is there a easy way to hack this so that in addition to Json, we also support Ron ? That might be a solution to this.
Context: I am currently using Ron for my config files -- but I find what I really want is not merely Ron, but EXPRESSIONS over Ron -- which led me to finding Cel. And I'm now wondering if there is a easy hack to make Cel-rust also support Ron in addition to Json for the data notation.
@zeroexcuses any type that implements Serialize (which a Rust ron rust would) can be added as a variable to the context. Not every rust data type is supported (tuples for example), so those wouldn't be available in your expressions, but the CEL-supported types should work fine.
Are you having issues doing the following? Or is your question about deserializing from CEL to Ron?
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
struct MyStruct {
boolean: bool,
float: f32,
}
let x: MyStruct = ron::from_str("(boolean: true, float: 1.23)").unwrap();
let mut context = Context::default();
context.add_variable("x", x).unwrap();
Is there a easy way to hack this so that in addition to Json, we also support Ron ? That might be a solution to this.
Context: I am currently using Ron for my config files -- but I find what I really want is not merely Ron, but EXPRESSIONS over Ron -- which led me to finding Cel. And I'm now wondering if there is a easy hack to make Cel-rust also support Ron in addition to Json for the data notation.
This is also what i want/need. I started hacking expressions into my rust types, which kinda works but also is hacky. I think fusing cel and the ron syntax for enums/structs would be quite neat. I could imagine that one could return strings from cel and then deserialize them on the rust side to get rust types. Maybe that's the hack you are looking for?
Can you help me understand the idea behind coupling Ron and cel? Cel is format-agnostic. Anything that implements serialize can be referenced in a CEL expression already.
Can you help me understand the idea behind coupling Ron and cel? Cel is format-agnostic. Anything that implements serialize can be referenced in a CEL expression already.
I'm more talking about deserializing. Being able to construct rust structs/enums from cel would be amazing and leveraging the ron syntax for this.
There's an important disambiguation to be made here. Ron is a config file format, while it looks like Rust, it doesn't actually define a schema.
A schema would allow you to define:
MyStruct {
example: Either<String, f32>
}
while Ron operates on values so it can only do:
MyStruct {
example: "I must be a discrete value, even though Either implements Serialize and Deserialize for both types"
}
So Ron support isn't the solution, and it's already supported for the most part as input for cel-rust, the only lacking part here is that Value has no Value::ron() function like it does for Value::json(), but you can serialize Value into Ron directly just fine.
Building types at runtime requires protobufs, and they will never be visible to the complier. Crates like prost can load a .proto file at build-time and generate structs that way, but not while the program is running.
rust-protobuf supports dynamic types, but check the linked example to see how you'd have to interact with those objects.
@Caellian for me it's not about dynamic types. I think defining the schema in rust is the way to go, but allowing the cel side to construct those types. Personally I don't care if protobuf or serde or anything else is used under the hood.
Oh, I get it now.
For now you can get very close by using functions, but I see what you mean.
This suggestion then requires extending both the parser and interpreter. The parser is straightforward enough, the interpreter would need a new ConstructorFunction concept to handle this properly.