diff --git a/.github/skills/bump-version/SKILL.md b/.github/skills/bump-version/SKILL.md
index 784e18e4..5c097220 100644
--- a/.github/skills/bump-version/SKILL.md
+++ b/.github/skills/bump-version/SKILL.md
@@ -26,6 +26,9 @@ library and its wrapper packages.
| `wrappers/python/setup.py` | `VERSION = "X.Y.Z"` | `VERSION = "1.3.0"` |
| `wrappers/rust/regorust/Cargo.toml` | `version = "X.Y.Z"` | `version = "1.3.0"` |
| `wrappers/dotnet/Rego/Rego.csproj` | `X.Y.Z` | `1.3.0` |
+| `examples/rust/Cargo.toml` | `regorust = { version = "X.Y.Z" }` | `regorust = { version = "1.3.0" }` |
+| `examples/dotnet/example/example.csproj` | `Version="X.Y.Z"` | `Version="1.3.0"` |
+| `examples/dotnet/MyPolicy/MyPolicy.csproj` | `Version="X.Y.Z"` | `Version="1.3.0"` |
## Procedure
diff --git a/.github/workflows/pr_gate.yml b/.github/workflows/pr_gate.yml
index f2c9ad9d..6f644c15 100644
--- a/.github/workflows/pr_gate.yml
+++ b/.github/workflows/pr_gate.yml
@@ -197,6 +197,105 @@ jobs:
working-directory: ${{github.workspace}}/wrappers/python/
run: pytest -vv
+ linux-example-cpp:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Get dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y ninja-build libssl-dev
+
+ - name: CMake config
+ working-directory: ${{github.workspace}}/examples/cpp
+ run: cmake -B ${{github.workspace}}/examples/cpp/build --preset release -G Ninja
+ env:
+ REGOCPP_REPO: LOCAL
+
+ - name: CMake build
+ working-directory: ${{github.workspace}}/examples/cpp/build
+ run: ninja install
+
+ - name: CMake test
+ working-directory: ${{github.workspace}}/examples/cpp/build
+ run: ctest -V --build-config Release --timeout 120 --output-on-failure -T Test
+
+ linux-example-python:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Use Python
+ uses: actions/setup-python@v6
+ with:
+ python-version: "3.12"
+
+ - name: Get dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libssl-dev
+ python -m pip install --upgrade pip
+
+ - name: Python build
+ working-directory: ${{github.workspace}}/wrappers/python/
+ run: pip install -e .[dev]
+ env:
+ REGOCPP_REPO: LOCAL
+
+ - name: Run example
+ working-directory: ${{github.workspace}}/examples/python
+ run: python example.py
+
+ linux-example-rust:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Get dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y cargo rustc libssl-dev
+
+ - name: Cargo run
+ working-directory: ${{github.workspace}}/examples/rust
+ run: cargo run --config 'patch.crates-io.regorust.path="../../wrappers/rust/regorust"'
+ env:
+ REGOCPP_REPO: LOCAL
+
+ linux-example-dotnet:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Get dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libssl-dev
+
+ - name: Use dotnet
+ uses: actions/setup-dotnet@v5
+ with:
+ dotnet-version: 8.0.x
+
+ - name: Patch project reference
+ working-directory: ${{github.workspace}}/examples/dotnet/example
+ run: sed -i 's|||' example.csproj
+
+ - name: Run example
+ working-directory: ${{github.workspace}}/examples/dotnet/example
+ run: dotnet run
+ env:
+ REGOCPP_REPO: LOCAL
+
linux-cheriot:
runs-on: ubuntu-latest
diff --git a/README.md b/README.md
index 7e45c450..b20ce084 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,35 @@ You can run the test driver from the same directory:
./bin/rego_test tests/regocpp.yaml
+### Installing with vcpkg
+
+You can install rego-cpp using [vcpkg](https://vcpkg.io/):
+
+```bash
+vcpkg install rego-cpp
+```
+
+To enable crypto/JWT built-ins (requires OpenSSL 3):
+
+```bash
+vcpkg install rego-cpp[openssl3]
+```
+
+To also install the `rego` CLI tool:
+
+```bash
+vcpkg install rego-cpp[openssl3,tools]
+```
+
+Then in your CMake project:
+
+```cmake
+find_package(regocpp CONFIG REQUIRED)
+target_link_libraries( PRIVATE regocpp::rego)
+```
+
+For overlay port usage, see [`ports/rego-cpp/`](ports/rego-cpp/).
+
### Using the `rego` Library
See the [examples](examples/README.md) directory for examples of how to use the
diff --git a/examples/README.md b/examples/README.md
index 3004c12e..7f8d414a 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -50,51 +50,48 @@ a@host:dist$ ./bin/regoc -d examples/scalars.rego -q data.scalars.greeting
```
## Python
-The Python example is a [simple command line tool](python/rego.py) that takes zero or more
-Rego data, module, and input files and evaluates a query against them.
-
-Examples:
+The [Python example](python/example.py) is a demonstration program that shows
+how to use all the features of the wrapper, including queries, input/data,
+and bundles.
```bash
a@host:python$ pip install regopy
-a@host:python$ python rego.py eval -d examples/scalars.rego data.scalars.greeting
-{"expressions":["Hello"]}
-
-a@host:python$ python rego.py eval -d examples/objects.rego data.objects.sites[1].name
-{"expressions":["smoke1"]}
-
-a@host:python$ python rego.py eval -d examples/data0.json -d examples/data1.json -d examples/objects.rego -i examples/input0.json "[data.one, input.b, data.objects.sites[1]]"
-{"expressions":[[{"bar":"Foo", "baz":5, "be":true, "bop":23.4},"20",{"name":"smoke1"}]]}
-
-a@host:python$ python rego.py eval "x=5; y=x + (2 - 4 * 0.25) * -3 + 7.4;2 * 5"
+a@host:python$ python example.py
+Query Only
{"expressions":[true, true, 10], "bindings":{"x":5, "y":9.4}}
+x = 5
+10
-a@host:python$ python rego.py eval -d examples/bodies.rego -i examples/input1.json data.bodies.e
-{"expressions":[{"one":15, "two":15}]}
-```
+Input and Data
+{"expressions":[true], "bindings":{"x":[{"bar":"Foo", "baz":5, "be":true, "bop":23.4},"20",{"name":"smoke1"}]}}
+Bundles
+query: {"expressions":[true], "bindings":{"x":4460}}
+example/foo: {"expressions":[2275]}
+```
-## Rust
-The Rust example is another [simple command line tool](rust/src/main.rs) that takes zero or more
+There is also a [command line tool](python/rego.py) that takes zero or more
Rego data, module, and input files and evaluates a query against them.
-Examples:
-
-```bash
-a@host:rust$ cargo run -- eval -d examples/scalars.rego data.scalars.greeting
-{"expressions":["Hello"]}
-
-a@host:rust$ cargo run -- eval -d examples/objects.rego data.objects.sites[1].name
-{"expressions":["smoke1"]}
-a@host:rust$ cargo run -- eval -d examples/data0.json -d examples/data1.json -d examples/objects.rego -i examples/input0.json "[data.one, input.b, data.objects.sites[1]]"
-{"expressions":[[{"bar":"Foo", "baz":5, "be":true, "bop":23.4},"20",{"name":"smoke1"}]]}
+## Rust
+The [Rust example](rust/src/main.rs) is a demonstration program that shows
+how to use all the features of the wrapper, including queries, input/data,
+and bundles.
-a@host:rust$ cargo run -- eval "x=5; y=x + (2 - 4 * 0.25) * -3 + 7.4;5 * 2"
+```bash
+a@host:rust$ cargo run
+Query Only
{"expressions":[true, true, 10], "bindings":{"x":5, "y":9.4}}
+x = 5
+10
+
+Input and Data
+{"expressions":[true], "bindings":{"x":[{"bar":"Foo", "baz":5, "be":true, "bop":23.4},"20",{"name":"smoke1"}]}}
-a@host:rust$ cargo run -- eval -d examples/bodies.rego -i examples/input1.json data.bodies.e
-{"expressions":[{"one":15, "two":15}]}
+Bundles
+query: {"expressions":[true], "bindings":{"x":4460}}
+example/foo: {"expressions":[2275]}
```
## dotnet
diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt
index be7ca965..4f7d84ca 100644
--- a/examples/c/CMakeLists.txt
+++ b/examples/c/CMakeLists.txt
@@ -57,4 +57,9 @@ add_test(
COMMAND bin/regoc -d examples/data0.json -d examples/data1.json -i examples/input0.json -d examples/objects.rego -q data.objects.sites[1]
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist
)
-set_tests_properties(regoc PROPERTIES PASS_REGULAR_EXPRESSION "{\"name\":\"smoke1\"}")
\ No newline at end of file
+set_tests_properties(regoc PROPERTIES PASS_REGULAR_EXPRESSION "{\"name\":\"smoke1\"}")
+add_test(
+ NAME example
+ COMMAND bin/example
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist
+)
\ No newline at end of file
diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt
index ed77e2af..9b8713d7 100644
--- a/examples/cpp/CMakeLists.txt
+++ b/examples/cpp/CMakeLists.txt
@@ -51,4 +51,9 @@ add_test(
COMMAND bin/custom_builtin
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist
)
-set_tests_properties(custom_builtin PROPERTIES PASS_REGULAR_EXPRESSION "5")
\ No newline at end of file
+set_tests_properties(custom_builtin PROPERTIES PASS_REGULAR_EXPRESSION "5")
+add_test(
+ NAME example
+ COMMAND bin/example
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist
+)
\ No newline at end of file
diff --git a/examples/cpp/example.cc b/examples/cpp/example.cc
index b783bcad..546609df 100644
--- a/examples/cpp/example.cc
+++ b/examples/cpp/example.cc
@@ -1,5 +1,3 @@
-#include "trieste/logging.h"
-
#include
int main()
diff --git a/examples/python/example.py b/examples/python/example.py
index 0d533004..0f76fda2 100644
--- a/examples/python/example.py
+++ b/examples/python/example.py
@@ -2,10 +2,34 @@
from regopy import Input, Interpreter
+##############################
+##### Query Only #####
+##############################
+
+print("Query Only")
+
+# You can run simple queries without any input or data.
rego = Interpreter()
-with open("examples/objects.rego") as f:
- rego.add_module("objects.rego", f.read())
+output = rego.query("x=5;y=x + (2 - 4 * 0.25) * -3 + 7.4;2 * 5")
+print(output)
+# {"expressions":[true, true, 10], "bindings":{"x":5, "y":9.4}}
+
+# You can access bound results using the binding method
+print("x =", output.binding("x").json())
+
+# You can also access expressions by index
+print(output[0][2])
+
+print()
+
+##############################
+#### Input and Data #####
+##############################
+print("Input and Data")
+
+# If you provide a dict, it will be converted to JSON before
+# being added to the state.
rego.add_data({
"one": {
"bar": "Foo",
@@ -21,26 +45,102 @@
}
})
-rego.add_data({
+# You can also provide JSON directly.
+rego.add_data_json("""
+{
"three": {
"bar": "Baz",
"baz": 15,
- "be": True,
+ "be": true,
"bop": 4.23
}
-})
+}
+""")
+
+objects_source = """
+package objects
-rego.set_input(Input({
+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"]
+"""
+rego.add_module("objects.rego", objects_source)
+
+# Inputs can be either JSON or Rego, and provided
+# as objects or as text.
+rego.set_input_term("""
+{
"a": 10,
"b": "20",
"c": 30.0,
- "d": True
-}))
+ "d": true
+}
+""")
print(rego.query("[data.one, input.b, data.objects.sites[1]] = x"))
+# {"bindings":{"x":[{"bar":"Foo", "baz":5, "be":true, "bop":23.4}, "20", {"name":"smoke1"}]}}
+
+##############################
+##### Bundles #####
+##############################
+
+print()
+print("Bundles")
+
+# If you want to run the same set of queries against a policy with different
+# inputs, you can create a bundle and use that to save the cost of compilation.
+
+rego_build = Interpreter()
+
+rego_build.add_data_json("""
+{"a": 7,
+"b": 13}
+""")
+
+rego_build.add_module("example.rego", """
+package example
+
+foo := data.a * input.x + data.b * input.y
+bar := data.b * input.x + data.a * input.y
+""")
+
+# We can specify both a default query, and specific entry points into the policy
+# that should be made available to use later.
+bundle = rego_build.build(
+ "x=data.example.foo + data.example.bar",
+ ["example/foo", "example/bar"]
+)
+
+# We can now save the bundle to disk
+rego_build.save_bundle("bundle", bundle)
+
+# And load it again
+rego_run = Interpreter()
+rego_run.load_bundle("bundle")
-bundle = rego.build("[data.one, input.b, data.objects.sites[1]] = x", ["objects/sites"])
+# The most efficient way to provide input to a policy is by constructing it
+# manually, without the need for parsing JSON or Rego.
+rego_run.set_input(Input({"x": 104, "y": 119}))
-print(rego.query_bundle(bundle))
+# We can query the bundle, which will use the entrypoint of the default query
+# provided at build
+print("query:", rego_run.query_bundle(bundle))
+# query: {"expressions":[true], "bindings":{"x":4460}}
-print(rego.query_bundle_entrypoint(bundle, "objects/sites"))
\ No newline at end of file
+# Or we can query specific entrypoints
+print("example/foo:", rego_run.query_bundle_entrypoint(bundle, "example/foo"))
+# example/foo: {"expressions":[2275]}
diff --git a/examples/rust/Cargo.toml b/examples/rust/Cargo.toml
index 9be031ef..b3cfadd2 100644
--- a/examples/rust/Cargo.toml
+++ b/examples/rust/Cargo.toml
@@ -6,5 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-regorust = { version = "1.2.0" }
-clap = { version = "4.0", features = ["derive"] }
\ No newline at end of file
+regorust = { version = "1.4.0" }
\ No newline at end of file
diff --git a/examples/rust/src/main.rs b/examples/rust/src/main.rs
index a6c22e65..a88b5b11 100644
--- a/examples/rust/src/main.rs
+++ b/examples/rust/src/main.rs
@@ -1,197 +1,193 @@
-use clap::{Parser, Subcommand, ValueEnum};
-use regorust::{BundleFormat, Interpreter, LogLevel};
-
-#[derive(Parser)]
-#[command(author, version, about, long_about = None)]
-struct Args {
- #[arg(short, long)]
- loglevel: Option,
-
- #[command(subcommand)]
- command: Commands,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
-enum LogLevelOption {
- None,
- Debug,
- Info,
- Warn,
- Error,
- Output,
- Trace,
-}
-
-#[derive(Subcommand)]
-enum Commands {
- Eval {
- query: String,
-
- #[arg(short, long)]
- data: Vec,
-
- #[arg(short, long)]
- input: Option,
- },
-
- Build {
- #[arg(short, long)]
- query: Option,
-
- #[arg(short, long)]
- data: Vec,
-
- #[arg(short, long)]
- entrypoints: Vec,
-
- #[arg(short, long)]
- bundle: Option,
-
- #[arg(long)]
- binary: bool,
- },
-
- Run {
- #[arg(short, long)]
- input: Option,
-
- #[arg(short, long)]
- entrypoint: Option,
-
- #[arg(short, long)]
- bundle: Option,
-
- #[arg(long)]
- binary: bool,
- },
-}
+use regorust::{BundleFormat, Input, Interpreter};
+use std::path::Path;
fn main() {
- let args = Args::parse();
- let default_path = std::path::PathBuf::from("bundle");
- let rego = Interpreter::new();
+ //////////////////////
+ ///// Query Only /////
+ //////////////////////
- match args.loglevel {
- Some(LogLevelOption::None) => rego.set_log_level(LogLevel::None),
- Some(LogLevelOption::Debug) => rego.set_log_level(LogLevel::Debug),
- Some(LogLevelOption::Info) => rego.set_log_level(LogLevel::Info),
- Some(LogLevelOption::Warn) => rego.set_log_level(LogLevel::Warn),
- Some(LogLevelOption::Error) => rego.set_log_level(LogLevel::Error),
- Some(LogLevelOption::Output) => rego.set_log_level(LogLevel::Output),
- Some(LogLevelOption::Trace) => rego.set_log_level(LogLevel::Trace),
- None => rego.set_log_level(LogLevel::Output),
- }
- .expect("Unable to set log level");
-
- match &args.command {
- Commands::Eval { query, data, input } => {
- if let Some(i) = input {
- rego.set_input_json_file(i.as_path())
- .expect("Failed to read input file");
- }
-
- for d in data {
- if d.extension().unwrap() == "rego" {
- rego.add_module_file(d.as_path())
- .expect("Failed to load module file");
- } else {
- rego.add_data_json_file(d.as_path())
- .expect("Failed to load data file");
- }
- }
-
- println!(
- "{}",
- rego.query(query.as_str())
- .expect("Failed to evaluate query")
- );
- }
+ println!("Query Only");
- Commands::Build {
- query,
- data,
- entrypoints,
- bundle,
- binary,
- } => {
- for d in data {
- if d.extension().unwrap() == "rego" {
- rego.add_module_file(d.as_path())
- .expect("Failed to load module file");
- } else {
- rego.add_data_json_file(d.as_path())
- .expect("Failed to load data file");
- }
- }
-
- let bundle_path = if let Some(b) = bundle {
- b.as_path()
- } else {
- default_path.as_path()
- };
-
- match rego.build(query, entrypoints) {
- Ok(b) => {
- rego.save_bundle(
- bundle_path,
- &b,
- if *binary {
- BundleFormat::Binary
- } else {
- BundleFormat::JSON
- },
- )
- .expect("Unable to save bundle");
- println!("Bundle built successfully");
- }
-
- Err(msg) => {
- println!("Unable to build bundle: {}", msg);
- }
- }
+ // You can run simple queries without any input or data.
+ let rego = Interpreter::new();
+ let output = rego
+ .query("x=5;y=x + (2 - 4 * 0.25) * -3 + 7.4;2 * 5")
+ .expect("Failed to evaluate query");
+ println!("{}", output);
+ // {"expressions":[true, true, 10], "bindings":{"x":5, "y":9.4}}
+
+ // You can access bound results using the binding method
+ let x = output.binding("x").expect("x is not bound");
+ println!("x = {}", x.json().unwrap());
+
+ // You can also access expressions by index
+ let exprs = output.expressions().expect("no expressions");
+ println!("{}", exprs.index(2).unwrap().json().unwrap());
+
+ println!();
+
+ ////////////////////////
+ //// Input and Data ////
+ ////////////////////////
+
+ println!("Input and Data");
+
+ // You can provide JSON data directly.
+ rego.add_data_json(
+ r#"{
+ "one": {
+ "bar": "Foo",
+ "baz": 5,
+ "be": true,
+ "bop": 23.4
+ },
+ "two": {
+ "bar": "Bar",
+ "baz": 12.3,
+ "be": false,
+ "bop": 42
}
-
- Commands::Run {
- input,
- entrypoint,
- bundle,
- binary,
- } => {
- if let Some(i) = input {
- rego.set_input_json_file(i.as_path())
- .expect("Failed to read input file");
- }
-
- let bundle_path = if let Some(b) = bundle {
- b.as_path()
- } else {
- default_path.as_path()
- };
-
- let bundle = rego
- .load_bundle(
- bundle_path,
- if *binary {
- BundleFormat::Binary
- } else {
- BundleFormat::JSON
- },
- )
- .expect("Unable to load bundle");
-
- if let Some(e) = entrypoint {
- println!(
- "{}",
- rego.query_bundle_entrypoint(&bundle, e.as_str())
- .expect("Failed to query bundle")
- );
- return;
- } else {
- println!(
- "{}",
- rego.query_bundle(&bundle).expect("Failed to query bundle")
- );
- }
+ }"#,
+ )
+ .expect("Failed to add data");
+
+ rego.add_data_json(
+ r#"{
+ "three": {
+ "bar": "Baz",
+ "baz": 15,
+ "be": true,
+ "bop": 4.23
}
- }
+ }"#,
+ )
+ .expect("Failed to add data");
+
+ rego.add_module(
+ "objects.rego",
+ 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"]
+"#,
+ )
+ .expect("Failed to add module");
+
+ // Inputs can be either JSON or Rego, and provided as text.
+ rego.set_input_json(
+ r#"{
+ "a": 10,
+ "b": "20",
+ "c": 30.0,
+ "d": true
+ }"#,
+ )
+ .expect("Failed to set input");
+
+ println!(
+ "{}",
+ rego.query("[data.one, input.b, data.objects.sites[1]] = x")
+ .expect("Failed to evaluate query")
+ );
+ // {"bindings":{"x":[{"bar":"Foo", "baz":5, "be":true, "bop":23.4}, "20", {"name":"smoke1"}]}}
+
+ ///////////////////
+ ///// Bundles ////
+ ///////////////////
+
+ println!();
+ println!("Bundles");
+
+ // If you want to run the same set of queries against a policy with different
+ // inputs, you can create a bundle and use that to save the cost of compilation.
+
+ let rego_build = Interpreter::new();
+
+ rego_build
+ .add_data_json(
+ r#"{"a": 7,
+"b": 13}"#,
+ )
+ .expect("Failed to add data");
+
+ rego_build
+ .add_module(
+ "example.rego",
+ r#"package example
+
+foo := data.a * input.x + data.b * input.y
+bar := data.b * input.x + data.a * input.y
+"#,
+ )
+ .expect("Failed to add module");
+
+ // We can specify both a default query, and specific entry points into the policy
+ // that should be made available to use later.
+ let bundle = rego_build
+ .build(
+ &Some("x=data.example.foo + data.example.bar"),
+ &["example/foo", "example/bar"],
+ )
+ .expect("Failed to build bundle");
+
+ // We can now save the bundle to disk
+ let bundle_path = Path::new("bundle");
+ rego_build
+ .save_bundle(bundle_path, &bundle, BundleFormat::JSON)
+ .expect("Failed to save bundle");
+
+ // And load it again
+ let rego_run = Interpreter::new();
+ rego_run
+ .load_bundle(bundle_path, BundleFormat::JSON)
+ .expect("Failed to load bundle");
+
+ // The most efficient way to provide input to a policy is by constructing it
+ // manually, without the need for parsing JSON or Rego.
+ let input = Input::new()
+ .str("x")
+ .int(104)
+ .objectitem()
+ .str("y")
+ .int(119)
+ .objectitem()
+ .object(2)
+ .validate()
+ .expect("Failed to create input");
+
+ rego_run.set_input(&input).expect("Failed to set input");
+
+ // We can query the bundle, which will use the entrypoint of the default query
+ // provided at build
+ println!(
+ "query: {}",
+ rego_run
+ .query_bundle(&bundle)
+ .expect("Failed to query bundle")
+ );
+ // query: {"expressions":[true], "bindings":{"x":4460}}
+
+ // Or we can query specific entrypoints
+ println!(
+ "example/foo: {}",
+ rego_run
+ .query_bundle_entrypoint(&bundle, "example/foo")
+ .expect("Failed to query bundle entrypoint")
+ );
+ // example/foo: {"expressions":[2275]}
}