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

source

pub fn new() -> Self

Creates a new Rego interpreter.

source

pub fn new_v1() -> Self

source

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
source

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());
source

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
   }
}
source

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());
source

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}
source

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());
source

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.

source

pub fn get_debug_enabled(&self) -> bool

Returns whether the Rego interpreter is in debug mode.

source

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.

source

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.

source

pub fn get_well_formed_checks_enabled(&self) -> bool

Returns whether the Rego interpreter will perform well-formedness checks.

source

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.

source

pub fn get_strict_built_in_errors(&self) -> bool

Returns whether the interpreter will forward errors thrown by the built-ins.

source

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());

Trait Implementations§

source§

impl Debug for Interpreter

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Drop for Interpreter

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl PartialEq for Interpreter

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more