Struct regorust::Interpreter
source · pub struct Interpreter { /* private fields */ }
Expand description
Interface for the Rego interpreter.
This wraps the Rego C API, and handles passing calls to the C API and converting the results to Rust types.
§Examples
let rego = Interpreter::new();
match rego.query("x=5;y=x + (2 - 4 * 0.25) * -3 + 7.4") {
Ok(result) => {
let x = result.binding("x").expect("cannot get x");
let y = result.binding("y").expect("cannot get y");
println!("x = {}", x.json().unwrap());
println!("y = {}", y.json().unwrap());
}
Err(e) => {
panic!("error: {}", e);
}
}
let input = r#"
{
"a": 10,
"b": "20",
"c": 30.0,
"d": true
}
"#;
let data0 = r#"
{
"one": {
"bar": "Foo",
"baz": 5,
"be": true,
"bop": 23.4
},
"two": {
"bar": "Bar",
"baz": 12.3,
"be": false,
"bop": 42
}
}
"#;
let data1 = r#"
{
"three": {
"bar": "Baz",
"baz": 15,
"be": true,
"bop": 4.23
}
}
"#;
let module = r#"
package objects
rect := {`width`: 2, "height": 4}
cube := {"width": 3, `height`: 4, "depth": 5}
a := 42
b := false
c := null
d := {"a": a, "x": [b, c]}
index := 1
shapes := [rect, cube]
names := ["prod", `smoke1`, "dev"]
sites := [{"name": "prod"}, {"name": names[index]}, {"name": "dev"}]
e := {
a: "foo",
"three": c,
names[2]: b,
"four": d,
}
f := e["dev"]
"#;
let rego = Interpreter::new();
rego.set_input_json(input);
rego.add_data_json(data0);
rego.add_data_json(data1);
rego.add_module("objects", module);
match rego.query("x=[data.one, input.b, data.objects.sites[1]]") {
Ok(result) => {
println!("{}", result.to_str().unwrap());
let x = result.binding("x").expect("cannot get x");
let data_one = x.index(0).unwrap();
if let NodeValue::String(bar) = data_one
.lookup("bar")
.unwrap()
.value()
.unwrap()
{
println!("data.one.bar = {}", bar);
}
}
Err(e) => {
panic!("error: {}", e);
}
}
Implementations§
source§impl Interpreter
impl Interpreter
pub fn new_v1() -> Self
sourcepub fn add_module_file(&self, path: &Path) -> Result<(), &str>
pub fn add_module_file(&self, path: &Path) -> Result<(), &str>
Adds a Rego module from a file.
The file must be valid Rego, and is equivalent to adding
the module as a string using add_module
.
§Example module file
package scalars
greeting := "Hello"
max_height := 42
pi := 3.14159
allowed := true
location := null
sourcepub fn add_module(&self, name: &str, source: &str) -> Result<(), &str>
pub fn add_module(&self, name: &str, source: &str) -> Result<(), &str>
Adds a Rego module from a string.
§Example
let module = r#"
package scalars
greeting := "Hello"
max_height := 42
pi := 3.14159
allowed := true
location := null
"#;
let rego = Interpreter::new();
rego.add_module("scalars", module);
let result = rego.query("data.scalars.greeting").unwrap();
println!("{}", result.to_str().unwrap());
sourcepub fn add_data_json_file(&self, path: &Path) -> Result<(), &str>
pub fn add_data_json_file(&self, path: &Path) -> Result<(), &str>
Adds a base document from a file.
The file must be a valid JSON object, and is equivalent to adding
the document as a string using add_data_json
.
§Example document file
{
"one": {
"bar": "Foo",
"baz": 5,
"be": true,
"bop": 23.4
},
"two": {
"bar": "Bar",
"baz": 12.3,
"be": false,
"bop": 42
}
}
sourcepub fn add_data_json(&self, data: &str) -> Result<(), &str>
pub fn add_data_json(&self, data: &str) -> Result<(), &str>
Adds a base document from a string.
The string must contain a valid JSON object.
§Example
let data = r#"
{
"one": {
"bar": "Foo",
"baz": 5,
"be": true,
"bop": 23.4
},
"two": {
"bar": "Bar",
"baz": 12.3,
"be": false,
"bop": 42
}
}
"#;
let rego = Interpreter::new();
rego.add_data_json(data);
let result = rego.query("data.one.bar").unwrap();
println!("{}", result.to_str().unwrap());
sourcepub fn set_input_json_file(&self, path: &Path) -> Result<(), &str>
pub fn set_input_json_file(&self, path: &Path) -> Result<(), &str>
Sets the input JSON expression from a file.
The input must be a single valid JSON value. It is equivalent to adding
the input file as a string using add_input_json
.
§Example input files
"Hello, rego"
42
[1, 2, 3]
{"a": 1, "b": 2}
sourcepub fn set_input_json(&self, input: &str) -> Result<(), &str>
pub fn set_input_json(&self, input: &str) -> Result<(), &str>
Sets the input JSON expression from a string.
The input must be a single valid JSON value.
§Example input files
"Hello, rego"
42
[1, 2, 3]
{"a": 1, "b": 2}
§Example
let input = r#"
{
"a": 10,
"b": "20",
"c": 30.0,
"d": true
}
"#;
let rego = Interpreter::new();
rego.set_input_json(input);
let result = rego.query("input.a").unwrap();
println!("{}", result.to_str().unwrap());
sourcepub fn set_debug_enabled(&self, enabled: bool)
pub fn set_debug_enabled(&self, enabled: bool)
Sets whether the Rego interpreter is in debug mode.
When debug mode is enabled, the Rego interpreter will output extensive debugging information about the compliation process, including intermediary ASTs and the generated bytecode. This is mostly useful for debugging the Rego compiler itself, and is not useful for debugging Rego policies.
sourcepub fn get_debug_enabled(&self) -> bool
pub fn get_debug_enabled(&self) -> bool
Returns whether the Rego interpreter is in debug mode.
sourcepub fn set_debug_path(&self, path: &Path) -> Result<(), &str>
pub fn set_debug_path(&self, path: &Path) -> Result<(), &str>
Sets the path to the directory where the Rego interpreter will write debug AST files.
This is only useful when debug mode is enabled.
sourcepub fn set_well_formed_checks_enabled(&self, enabled: bool)
pub fn set_well_formed_checks_enabled(&self, enabled: bool)
Sets whether the Rego interpreter will perform well-formedness checks.
When enabled, the Rego interpreter will perform well-formedness checks on the AST during each pass of the compiler.
sourcepub fn get_well_formed_checks_enabled(&self) -> bool
pub fn get_well_formed_checks_enabled(&self) -> bool
Returns whether the Rego interpreter will perform well-formedness checks.
sourcepub fn set_strict_built_in_errors(&self, enabled: bool)
pub fn set_strict_built_in_errors(&self, enabled: bool)
Sets whether the interpreter will forward errors thrown by the built-ins.
By default, the Rego interpreter will catch errors thrown by the built-ins and return them as an Undefined result. When this is enabled, the interpreter will instead forward the error to the caller.
sourcepub fn get_strict_built_in_errors(&self) -> bool
pub fn get_strict_built_in_errors(&self) -> bool
Returns whether the interpreter will forward errors thrown by the built-ins.
sourcepub fn query(&self, query: &str) -> Result<Output, &str>
pub fn query(&self, query: &str) -> Result<Output, &str>
This method performs a query against the current set of base and virtual documents.
While the Rego interpreter can be used to perform simple queries, in most cases
users will want to load one or more base documents (using Self::add_data_json()
or
Self::add_data_json_file()
) and one or more Rego modules (using Self::add_module()
or
Self::add_module_file()
). Then, multiple queries can be performed by providing an input
(using Self::set_input_json()
or Self::set_input_json_file()
) and then calling this
method.
§Example
let input0 = r#"{"a": 10}"#;
let input1 = r#"{"a": 4}"#;
let input2 = r#"{"a": 7}"#;
let multi = r#"
package multi
default a := 0
a := val {
input.a > 0
input.a < 10
input.a % 2 == 1
val := input.a * 10
} {
input.a > 0
input.a < 10
input.a % 2 == 0
val := input.a * 10 + 1
}
a := input.a / 10 {
input.a >= 10
}
"#;
let rego = Interpreter::new();
rego.add_module("multi", multi);
rego.set_input_json(input0);
let result = rego.query("data.multi.a").unwrap();
println!("{}", result.to_str().unwrap());
rego.set_input_json(input1);
let result = rego.query("data.multi.a").unwrap();
println!("{}", result.to_str().unwrap());
rego.set_input_json(input2);
let result = rego.query("data.multi.a").unwrap();
println!("{}", result.to_str().unwrap());