diff --git a/.github/workflows/#test-python.yml# b/.github/workflows/#test-python.yml# new file mode 100644 index 00000000..97ff982b --- /dev/null +++ b/.github/workflows/#test-python.yml# @@ -0,0 +1,37 @@ +name: test-python + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + PYTHON_VERSION: "3.10" + +jobs: + setup: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + architecture: x64 + + - name: Build wheels + uses: PyO3/maturin-action@63b75c597b83e247fbf4fb7719801cc4220ae9f3 # v1.43.0 + with: + target: x86_64 + args: --release --out dist --manifest-path bindings/python/Cargo.toml + sccache: 'true' + + - name: Test wheel + run: | + pip3 install dist/regorus-*.whl + cd bindings/python + python3 test.py diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 1dc0a5a7..90ad5724 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,4 +1,4 @@ -name: Rust +name: tests/release on: push: @@ -10,26 +10,18 @@ env: CARGO_TERM_COLOR: always jobs: - build: + test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Add musl target - run: rustup target add x86_64-unknown-linux-musl - - name: Add no_std target - run: rustup target add thumbv7m-none-eabi - - name: Install musl-gcc - run: sudo apt update && sudo apt install -y musl-tools + - uses: actions/checkout@v4 - name: Format Check run: cargo fmt --check - name: Build (all features) - run: cargo build -r --all-features --verbose + run: cargo build -r --all-features - name: Build - run: cargo build -r --verbose - - name: Build no_std - run: cd tests/ensure_no_std && cargo build -r --target thumbv7m-none-eabi + run: cargo build -r - name: Test no_std run: cargo test -r --no-default-features - name: Build only std @@ -37,7 +29,7 @@ jobs: - name: Doc Tests run: cargo test -r --doc - name: Run tests - run: cargo test -r --verbose + run: cargo test -r - name: Run tests (ACI) run: cargo test -r --test aci - name: Run tests (KATA) @@ -45,14 +37,3 @@ jobs: - name: Run tests (OPA Conformance) run: >- cargo test -r --test opa --features opa-testutil,serde_json/arbitrary_precision -- $(tr '\n' ' ' < tests/opa.passing) - - name: Build (MUSL) - run: cargo build --verbose --all-targets --target x86_64-unknown-linux-musl - - name: Run tests (MUSL) - run: cargo test -r --verbose --target x86_64-unknown-linux-musl - - name: Run tests (MUSL ACI) - run: cargo test -r --test aci --target x86_64-unknown-linux-musl - - name: Run tests (KATA ACI) - run: cargo test -r --test kata --target x86_64-unknown-linux-musl - - name: Run tests (MUSL OPA Conformance) - run: >- - cargo test -r --test opa --features opa-testutil,serde_json/arbitrary_precision --target x86_64-unknown-linux-musl -- $(tr '\n' ' ' < tests/opa.passing) diff --git a/.github/workflows/publish-python.yml b/.github/workflows/publish-python.yml index 5ff93124..29eac89a 100644 --- a/.github/workflows/publish-python.yml +++ b/.github/workflows/publish-python.yml @@ -23,7 +23,7 @@ jobs: with: python-version: '3.10' - name: Build wheels - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@63b75c597b83e247fbf4fb7719801cc4220ae9f3 # v1.43.0 with: target: ${{ matrix.target }} args: --release --out dist --find-interpreter --manifest-path bindings/python/Cargo.toml @@ -47,7 +47,7 @@ jobs: python-version: '3.10' architecture: ${{ matrix.target }} - name: Build wheels - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@63b75c597b83e247fbf4fb7719801cc4220ae9f3 # v1.43.0 with: target: ${{ matrix.target }} args: --release --out dist --find-interpreter --manifest-path bindings/python/Cargo.toml @@ -69,7 +69,7 @@ jobs: with: python-version: '3.10' - name: Build wheels - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@63b75c597b83e247fbf4fb7719801cc4220ae9f3 # v1.43.0 with: target: ${{ matrix.target }} args: --release --out dist --find-interpreter --manifest-path bindings/python/Cargo.toml @@ -85,7 +85,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Build sdist - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@63b75c597b83e247fbf4fb7719801cc4220ae9f3 # v1.43.0 with: command: sdist args: --out dist --manifest-path bindings/python/Cargo.toml @@ -106,7 +106,7 @@ jobs: with: name: wheels - name: Publish to PyPI - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@63b75c597b83e247fbf4fb7719801cc4220ae9f3 # v1.43.0 env: MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} with: diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index fcc8b3ef..c7de78b7 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -18,7 +18,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Run release-plz - uses: MarcoIeni/release-plz-action@v0.5 + uses: MarcoIeni/release-plz-action@a10be9933e46ab5005d79ce8b1eafca2ecdcd844 #v0.3.68 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/test-c-cpp.yml b/.github/workflows/test-c-cpp.yml new file mode 100644 index 00000000..609fee3f --- /dev/null +++ b/.github/workflows/test-c-cpp.yml @@ -0,0 +1,43 @@ +name: bindings/c-cpp + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup gcc, g++, cmake, ninja + run: sudo apt update && sudo apt install -y gcc g++ cmake ninja-build + + - name: Test c binding + run: | + mkdir bindings/c/build + cd bindings/c/build + cmake -G Ninja .. + ninja + ./regorus_test + + - name: Test c-nostd binding + run: | + mkdir bindings/c-nostd/build + cd bindings/c-nostd/build + cmake -G Ninja .. + ninja + ./regorus_test + + - name: Test cpp binding + run: | + mkdir bindings/cpp/build + cd bindings/cpp/build + cmake -G Ninja .. + ninja + ./regorus_test diff --git a/.github/workflows/test-go.yml b/.github/workflows/test-go.yml new file mode 100644 index 00000000..8dcc7318 --- /dev/null +++ b/.github/workflows/test-go.yml @@ -0,0 +1,34 @@ +name: bindings/go + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + + - uses: actions/setup-go@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + architecture: x64 + + - name: Build ffi + run: cargo build -r + working-directory: ./bindings/ffi + + - name: Test go + run: | + go mod tidy + go build + cp ../../target/release/libregorus*.so . + ./regorus-test + working-directory: ./bindings/go diff --git a/.github/workflows/test-java.yml b/.github/workflows/test-java.yml new file mode 100644 index 00000000..5d26a701 --- /dev/null +++ b/.github/workflows/test-java.yml @@ -0,0 +1,33 @@ +name: bindings/java + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-java@v4 + with: + java-version: 8 + distribution: "corretto" + - uses: dtolnay/rust-toolchain@stable + + - name: Building binding + run: cargo build --release --manifest-path bindings/java/Cargo.toml + - name: Build jar + run: | + cp ../../target/release/libregorus*.so . + mvn package + working-directory: ./bindings/java + - name: Test jar + run: java -cp target/regorus-java-0.1.5.jar Test.java + working-directory: ./bindings/java diff --git a/.github/workflows/test-musl.yml b/.github/workflows/test-musl.yml new file mode 100644 index 00000000..c848b4a2 --- /dev/null +++ b/.github/workflows/test-musl.yml @@ -0,0 +1,33 @@ +name: musl + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Add musl target + run: rustup target add x86_64-unknown-linux-musl + - name: Install musl-gcc + run: sudo apt update && sudo apt install -y musl-tools + - name: Build (MUSL) + run: cargo build --verbose --all-targets --target x86_64-unknown-linux-musl + - name: Run tests (MUSL) + run: cargo test -r --verbose --target x86_64-unknown-linux-musl + - name: Run tests (MUSL ACI) + run: cargo test -r --test aci --target x86_64-unknown-linux-musl + - name: Run tests (KATA ACI) + run: cargo test -r --test kata --target x86_64-unknown-linux-musl + - name: Run tests (MUSL OPA Conformance) + run: >- + cargo test -r --test opa --features opa-testutil,serde_json/arbitrary_precision --target x86_64-unknown-linux-musl -- $(tr '\n' ' ' < tests/opa.passing) diff --git a/.github/workflows/test-no-std.yml b/.github/workflows/test-no-std.yml new file mode 100644 index 00000000..78ad1b4f --- /dev/null +++ b/.github/workflows/test-no-std.yml @@ -0,0 +1,24 @@ +name: bindings/no-std + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Add no_std target + run: rustup target add thumbv7m-none-eabi + - name: Build + run: cargo build -r --target thumbv7m-none-eabi + working-directory: ./tests/ensure_no_std + diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml new file mode 100644 index 00000000..84a434d8 --- /dev/null +++ b/.github/workflows/test-python.yml @@ -0,0 +1,37 @@ +name: bindings/python + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + PYTHON_VERSION: "3.10" + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + architecture: x64 + + - name: Build wheels + uses: PyO3/maturin-action@63b75c597b83e247fbf4fb7719801cc4220ae9f3 # v1.43.0 + with: + target: x86_64 + args: --release --out dist --manifest-path bindings/python/Cargo.toml + sccache: 'true' + + - name: Test wheel + run: | + pip3 install dist/regorus-*.whl + cd bindings/python + python3 test.py diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml index 16acf741..298e8bc0 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -1,4 +1,4 @@ -name: test-ruby +name: bindings/ruby on: push: @@ -7,7 +7,7 @@ on: branches: [ "main" ] jobs: - setup: + test: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -16,7 +16,7 @@ jobs: fetch-depth: 0 - name: Setup Ruby and Rust - uses: oxidize-rb/actions/setup-ruby-and-rust@v1 + uses: oxidize-rb/actions/setup-ruby-and-rust@7ca44a16e287e5ff7dd72ab53f4bd41cbf34a571 #v1.26 with: ruby-version: "3.3.1" rustup-toolchain: "stable" diff --git a/.github/workflows/test-wasm.yml b/.github/workflows/test-wasm.yml new file mode 100644 index 00000000..1a5e309e --- /dev/null +++ b/.github/workflows/test-wasm.yml @@ -0,0 +1,30 @@ +name: bindings/wasm + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Install wasmlpack + run: cargo install wasm-pack + + - name: Test wasm binding + run: | + cd bindings/wasm + wasm-pack build --target nodejs --release + node test.js diff --git a/.github/workflows/tests-debug.yml b/.github/workflows/tests-debug.yml new file mode 100644 index 00000000..873c123d --- /dev/null +++ b/.github/workflows/tests-debug.yml @@ -0,0 +1,37 @@ +name: tests/debug + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build (all features) + run: cargo build --all-features + - name: Build + run: cargo build + - name: Test no_std + run: cargo test --no-default-features + - name: Build only std + run: cargo build --example regorus --no-default-features --features "std" + - name: Doc Tests + run: cargo test --doc + - name: Run tests + run: cargo test + - name: Run tests (ACI) + run: cargo test --test aci + - name: Run tests (KATA) + run: cargo test --test kata + - name: Run tests (OPA Conformance) + run: >- + cargo test --test opa --features opa-testutil,serde_json/arbitrary_precision -- $(tr '\n' ' ' < tests/opa.passing) diff --git a/bindings/c-nostd/CMakeLists.txt b/bindings/c-nostd/CMakeLists.txt index 1d554bef..3cc4e93b 100644 --- a/bindings/c-nostd/CMakeLists.txt +++ b/bindings/c-nostd/CMakeLists.txt @@ -35,7 +35,7 @@ corrosion_import_crate( CRATE_TYPES staticlib FLAGS --crate-type=staticlib ) -add_executable(regorus_test_nostd main.c) +add_executable(regorus_test main.c) # Add path to /bindings/ffi -target_include_directories(regorus_test_nostd PRIVATE "../ffi") -target_link_libraries(regorus_test_nostd regorus-ffi) +target_include_directories(regorus_test PRIVATE "../ffi") +target_link_libraries(regorus_test regorus-ffi) diff --git a/bindings/c-nostd/main.c b/bindings/c-nostd/main.c index 0ac88046..9cd54e71 100644 --- a/bindings/c-nostd/main.c +++ b/bindings/c-nostd/main.c @@ -7,13 +7,14 @@ char* file_to_string(const char* file) { char * buffer = 0; long length; FILE * f = fopen (file, "rb"); - + if (f) { fseek (f, 0, SEEK_END); length = ftell (f); fseek (f, 0, SEEK_SET); - buffer = malloc (length); + buffer = malloc (length + 1); + buffer[length] = '\0'; if (buffer) { fread (buffer, 1, length, f); @@ -26,8 +27,6 @@ char* file_to_string(const char* file) { // If regorus is built with custom-allocator, then provide implementation. uint8_t* regorus_aligned_alloc(size_t alignment, size_t size) { - printf("%ld %ld\n", size, alignment); - fflush(stdout); return aligned_alloc(alignment, size); } @@ -47,18 +46,21 @@ int main() { free(buffer); if (r.status != RegorusStatusOk) goto error; + printf("Loaded policy %s\n", r.output); regorus_result_drop(r); r = regorus_engine_add_policy(engine, "api.rego", (buffer = file_to_string("../../../tests/aci/api.rego"))); free(buffer); if (r.status != RegorusStatusOk) goto error; + printf("Loaded policy %s\n", r.output); regorus_result_drop(r); - + r = regorus_engine_add_policy(engine, "policy.rego", (buffer = file_to_string("../../../tests/aci/policy.rego"))); free(buffer); if (r.status != RegorusStatusOk) goto error; + printf("Loaded policy %s\n", r.output); regorus_result_drop(r); // Add data @@ -83,14 +85,14 @@ int main() { // Print output printf("%s", r.output); regorus_result_drop(r); - - + + // Free the engine. regorus_engine_drop(engine); return 0; error: printf("%s", r.error_message); - + return 1; } diff --git a/bindings/c/main.c b/bindings/c/main.c index 53197989..17651ba6 100644 --- a/bindings/c/main.c +++ b/bindings/c/main.c @@ -10,16 +10,19 @@ int main() { r = regorus_engine_add_policy_from_file(engine, "../../../tests/aci/framework.rego"); if (r.status != RegorusStatusOk) goto error; + printf("Loaded policy %s\n", r.output); regorus_result_drop(r); r = regorus_engine_add_policy_from_file(engine, "../../../tests/aci/api.rego"); if (r.status != RegorusStatusOk) goto error; + printf("Loaded policy %s\n", r.output); regorus_result_drop(r); r = regorus_engine_add_policy_from_file(engine, "../../../tests/aci/policy.rego"); if (r.status != RegorusStatusOk) goto error; + printf("Loaded policy %s\n", r.output); regorus_result_drop(r); // Add data diff --git a/bindings/cpp/CMakeLists.txt b/bindings/cpp/CMakeLists.txt index 18ce8fb8..a510438b 100644 --- a/bindings/cpp/CMakeLists.txt +++ b/bindings/cpp/CMakeLists.txt @@ -19,8 +19,14 @@ corrosion_import_crate( MANIFEST_PATH "../ffi/Cargo.toml" # Always build regorus in Release mode. PROFILE "release" - # Only build the "regorusc" crate. - CRATES "regorus-ffi") + # Only build the "regorus-ffi" crate. + CRATES "regorus-ffi" + + # Select specific features in regorus. + FEATURES "regorus/semver" + + # Link statically + CRATE_TYPES "staticlib") add_executable(regorus_test main.cpp) # Add path to /bindings/ffi diff --git a/bindings/cpp/main.cpp b/bindings/cpp/main.cpp index 7706e1bf..08145249 100644 --- a/bindings/cpp/main.cpp +++ b/bindings/cpp/main.cpp @@ -89,6 +89,7 @@ int main() { std::cerr< *mut c_char { } } -fn from_c_str(s: *const c_char) -> Result { +fn from_c_str(name: &str, s: *const c_char) -> Result { if s.is_null() { bail!("null pointer"); } unsafe { CStr::from_ptr(s) .to_str() - .map_err(|_| anyhow!("`path`: invalid utf8")) + .map_err(|e| anyhow!("`{name}`: invalid utf8.\n{e}")) .map(|s| s.to_string()) } } @@ -70,6 +70,21 @@ fn to_regorus_result(r: Result<()>) -> RegorusResult { } } +fn to_regorus_string_result(r: Result) -> RegorusResult { + match r { + Ok(s) => RegorusResult { + status: RegorusStatus::RegorusStatusOk, + output: to_c_str(s), + error_message: std::ptr::null_mut(), + }, + Err(e) => RegorusResult { + status: RegorusStatus::RegorusStatusError, + output: std::ptr::null_mut(), + error_message: to_c_str(format!("{e}")), + }, + } +} + /// Wrapper for `regorus::Engine`. #[derive(Clone)] pub struct RegorusEngine { @@ -81,10 +96,13 @@ pub struct RegorusEngine { /// `output` and `error_message` strings are not valid after drop. #[no_mangle] pub extern "C" fn regorus_result_drop(r: RegorusResult) { - if !r.error_message.is_null() { - unsafe { + unsafe { + if !r.error_message.is_null() { let _ = CString::from_raw(r.error_message); } + if !r.output.is_null() { + let _ = CString::from_raw(r.output); + } } } @@ -133,10 +151,10 @@ pub extern "C" fn regorus_engine_add_policy( path: *const c_char, rego: *const c_char, ) -> RegorusResult { - to_regorus_result(|| -> Result<()> { + to_regorus_string_result(|| -> Result { to_ref(&engine)? .engine - .add_policy(from_c_str(path)?, from_c_str(rego)?) + .add_policy(from_c_str("path", path)?, from_c_str("rego", rego)?) }()) } @@ -146,10 +164,10 @@ pub extern "C" fn regorus_engine_add_policy_from_file( engine: *mut RegorusEngine, path: *const c_char, ) -> RegorusResult { - to_regorus_result(|| -> Result<()> { + to_regorus_string_result(|| -> Result { to_ref(&engine)? .engine - .add_policy_from_file(from_c_str(path)?) + .add_policy_from_file(from_c_str("path", path)?) }()) } @@ -165,7 +183,7 @@ pub extern "C" fn regorus_engine_add_data_json( to_regorus_result(|| -> Result<()> { to_ref(&engine)? .engine - .add_data(regorus::Value::from_json_str(&from_c_str(data)?)?) + .add_data(regorus::Value::from_json_str(&from_c_str("data", data)?)?) }()) } @@ -178,7 +196,7 @@ pub extern "C" fn regorus_engine_add_data_from_json_file( to_regorus_result(|| -> Result<()> { to_ref(&engine)? .engine - .add_data(regorus::Value::from_json_file(&from_c_str(path)?)?) + .add_data(regorus::Value::from_json_file(&from_c_str("path", path)?)?) }()) } @@ -205,7 +223,7 @@ pub extern "C" fn regorus_engine_set_input_json( to_regorus_result(|| -> Result<()> { to_ref(&engine)? .engine - .set_input(regorus::Value::from_json_str(&from_c_str(input)?)?); + .set_input(regorus::Value::from_json_str(&from_c_str("input", input)?)?); Ok(()) }()) } @@ -219,7 +237,7 @@ pub extern "C" fn regorus_engine_set_input_from_json_file( to_regorus_result(|| -> Result<()> { to_ref(&engine)? .engine - .set_input(regorus::Value::from_json_file(&from_c_str(path)?)?); + .set_input(regorus::Value::from_json_file(&from_c_str("path", path)?)?); Ok(()) }()) } @@ -236,7 +254,7 @@ pub extern "C" fn regorus_engine_eval_query( let output = || -> Result { let results = to_ref(&engine)? .engine - .eval_query(from_c_str(query)?, false)?; + .eval_query(from_c_str("query", query)?, false)?; Ok(serde_json::to_string_pretty(&results)?) }(); match output { diff --git a/bindings/java/Cargo.toml b/bindings/java/Cargo.toml index 57471aa4..33b1840f 100644 --- a/bindings/java/Cargo.toml +++ b/bindings/java/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "regorus-java" -version = "0.1.0" +version = "0.1.5" edition = "2021" repository = "https://github.com/microsoft/regorus/bindings/java" description = "Java bindings for Regorus - a fast, lightweight Rego interpreter written in Rust" diff --git a/bindings/java/README.md b/bindings/java/README.md index 8918c094..608ea39d 100644 --- a/bindings/java/README.md +++ b/bindings/java/README.md @@ -30,7 +30,7 @@ You then need to build Java bindings using: $ mvn package ``` -And you will have a JAR at `./target/regorus-java-0.0.1.jar`. +And you will have a JAR at `./target/regorus-java-0.1.5.jar`. ## Usage @@ -60,10 +60,10 @@ You need to ensure artifacts built in [previous section](#building) are in Java' For example with `java` CLI: ```bash -$ java -Djava.library.path=../../target/aarch64-apple-darwin/release/ -cp target/regorus-java-0.0.1.jar Test.java +$ java -Djava.library.path=../../target/aarch64-apple-darwin/release/ -cp target/regorus-java-0.1.5.jar Test.java ``` should gave you the output: ``` {"result":[{"expressions":[{"value":"Hello, World!","text":"data.test.message","location":{"row":1,"col":1}}]}]} -``` \ No newline at end of file +``` diff --git a/bindings/java/Test.java b/bindings/java/Test.java new file mode 100644 index 00000000..c36e7fb6 --- /dev/null +++ b/bindings/java/Test.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import com.microsoft.regorus.Engine; + +public class Test { + public static void main(String[] args) { + try (Engine engine = new Engine()) { + engine.addPolicy( + "hello.rego", + "package test\nmessage = concat(\", \", [input.message, data.message])" + ); + engine.addDataJson("{\"message\":\"World!\"}"); + engine.setInputJson("{\"message\":\"Hello\"}"); + String resJson = engine.evalQuery("data.test.message"); + + System.out.println(resJson); + } + } +} diff --git a/bindings/java/pom.xml b/bindings/java/pom.xml index 6b5ed292..fe8981e4 100644 --- a/bindings/java/pom.xml +++ b/bindings/java/pom.xml @@ -9,7 +9,7 @@ com.microsoft.regorus regorus-java - 0.0.1 + 0.1.5 Regorus Java Java bindings for Regorus - a fast, lightweight Rego interpreter written in Rust diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index e47e29ee..d62f688d 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "regoruspy" -version = "0.1.0" +version = "0.1.5" edition = "2021" repository = "https://github.com/microsoft/regorus/bindings/python" description = "Python bindings for Regorus - a fast, lightweight Rego interpreter written in Rust" diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index ee1dc93d..4502cddc 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -33,12 +33,12 @@ impl Clone for Engine { } } -fn from<'source>(ob: &'source PyAny) -> Result { +fn from<'source>(ob: &Bound<'_, PyAny>) -> Result { // dicts Ok(if let Ok(dict) = ob.downcast::() { let mut map = BTreeMap::new(); for (k, v) in dict { - map.insert(from(k)?, from(v)?); + map.insert(from(&k)?, from(&v)?); } map.into() } @@ -46,7 +46,7 @@ fn from<'source>(ob: &'source PyAny) -> Result { else if let Ok(pset) = ob.downcast::() { let mut set = BTreeSet::new(); for v in pset { - set.insert(from(v)?); + set.insert(from(&v)?); } set.into() } @@ -55,7 +55,7 @@ fn from<'source>(ob: &'source PyAny) -> Result { // let mut set = BTreeSet::new(); for v in pfset { - set.insert(from(v)?); + set.insert(from(&v)?); } set.into() } @@ -63,30 +63,30 @@ fn from<'source>(ob: &'source PyAny) -> Result { else if let Ok(plist) = ob.downcast::() { let mut array = Vec::new(); for v in plist { - array.push(from(v)?); + array.push(from(&v)?); } array.into() } else if let Ok(ptuple) = ob.downcast::() { let mut array = Vec::new(); for v in ptuple { - array.push(from(v)?); + array.push(from(&v)?); } array.into() } // String - else if let Ok(s) = String::extract(ob) { + else if let Ok(s) = ob.extract::() { s.into() } // Numeric - else if let Ok(v) = i64::extract(ob) { + else if let Ok(v) = ob.extract::() { v.into() - } else if let Ok(v) = u64::extract(ob) { + } else if let Ok(v) = ob.extract::() { v.into() - } else if let Ok(v) = f64::extract(ob) { + } else if let Ok(v) = ob.extract::() { v.into() } // Boolean - else if let Ok(b) = bool::extract(ob) { + else if let Ok(b) = ob.extract::() { b.into() } // None @@ -97,7 +97,7 @@ fn from<'source>(ob: &'source PyAny) -> Result { else if let Ok(pseq) = ob.downcast::() { let mut array = Vec::new(); for i in 0..pseq.len()? { - array.push(from(pseq.get_item(i)?)?); + array.push(from(&pseq.get_item(i)?)?); } array.into() } @@ -109,7 +109,7 @@ fn from<'source>(ob: &'source PyAny) -> Result { for i in 0..keys.len()? { let key = keys.get_item(i)?; let value = values.get_item(i)?; - map.insert(from(key)?, from(value)?); + map.insert(from(&key)?, from(&value)?); } map.into() } else { @@ -140,7 +140,7 @@ fn to(mut v: Value, py: Python<'_>) -> Result { } Value::Array(_) => { - let list = PyList::empty(py); + let list = PyList::empty_bound(py); for v in std::mem::replace(v.as_array_mut()?, Vec::new()) { list.append(to(v, py)?)?; } @@ -148,7 +148,7 @@ fn to(mut v: Value, py: Python<'_>) -> Result { } Value::Set(_) => { - let set = PySet::empty(py)?; + let set = PySet::empty_bound(py)?; for v in std::mem::replace(v.as_set_mut()?, BTreeSet::new()) { set.add(to(v, py)?)?; } @@ -156,7 +156,7 @@ fn to(mut v: Value, py: Python<'_>) -> Result { } Value::Object(_) => { - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); for (k, v) in std::mem::replace(v.as_object_mut()?, BTreeMap::new()) { dict.set_item(to(k, py)?, to(v, py)?)?; } @@ -181,7 +181,7 @@ impl Engine { /// /// * `path`: A filename to be associated with the policy. /// * `rego`: Rego policy. - pub fn add_policy(&mut self, path: String, rego: String) -> Result<()> { + pub fn add_policy(&mut self, path: String, rego: String) -> Result { self.engine.add_policy(path, rego) } @@ -190,15 +190,21 @@ impl Engine { /// The policy is parsed into AST. /// /// * `path`: Path to the policy file. - pub fn add_policy_from_file(&mut self, path: String) -> Result<()> { + pub fn add_policy_from_file(&mut self, path: String) -> Result { self.engine.add_policy_from_file(path) } + /// Get the list of packages defined by loaded policies. + /// + pub fn get_packages(&mut self) -> Result> { + self.engine.get_packages() + } + /// Add policy data. /// /// * `data`: Rego value. A Rego value is a number, bool, string, None /// or a list/set/map whose items themselves are Rego values. - pub fn add_data(&mut self, data: &PyAny) -> Result<()> { + pub fn add_data(&mut self, data: &Bound<'_, PyAny>) -> Result<()> { let data = from(data)?; self.engine.add_data(data) } @@ -229,7 +235,7 @@ impl Engine { /// /// * `input`: Rego value. A Rego value is a number, bool, string, None /// or a list/set/map whose items themselves are Rego values. - pub fn set_input(&mut self, input: &PyAny) -> Result<()> { + pub fn set_input(&mut self, input: &Bound<'_, PyAny>) -> Result<()> { let input = from(input)?; self.engine.set_input(input); Ok(()) @@ -259,17 +265,17 @@ impl Engine { pub fn eval_query(&mut self, query: String, py: Python<'_>) -> Result { let results = self.engine.eval_query(query, false)?; - let rlist = PyList::empty(py); + let rlist = PyList::empty_bound(py); for result in results.result.into_iter() { - let rdict = PyDict::new(py); + let rdict = PyDict::new_bound(py); - let elist = PyList::empty(py); + let elist = PyList::empty_bound(py); for expr in result.expressions.into_iter() { - let edict = PyDict::new(py); + let edict = PyDict::new_bound(py); edict.set_item("value".to_object(py), to(expr.value, py)?)?; edict.set_item("text".to_object(py), expr.text.as_ref().to_object(py))?; - let ldict = PyDict::new(py); + let ldict = PyDict::new_bound(py); ldict.set_item("row".to_object(py), expr.location.row.to_object(py))?; ldict.set_item("col".to_object(py), expr.location.col.to_object(py))?; @@ -281,7 +287,7 @@ impl Engine { rdict.set_item("bindings".to_object(py), to(result.bindings, py)?)?; rlist.append(rdict)?; } - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); dict.set_item("result".to_object(py), rlist)?; Ok(dict.into()) } @@ -296,6 +302,6 @@ impl Engine { } #[pymodule] -pub fn regorus(_py: Python<'_>, m: &PyModule) -> PyResult<()> { +pub fn regorus(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::() } diff --git a/bindings/python/test.py b/bindings/python/test.py index 9cf0d592..014a77fc 100644 --- a/bindings/python/test.py +++ b/bindings/python/test.py @@ -7,9 +7,14 @@ engine = regorus.Engine() # Load policies -engine.add_policy_from_file('../../tests/aci/framework.rego') -engine.add_policy_from_file('../../tests/aci/api.rego') -engine.add_policy_from_file('../../tests/aci/policy.rego') +pkg = engine.add_policy_from_file('../../tests/aci/framework.rego') +print(' Loaded Policy %s' % pkg) + +pkg = engine.add_policy_from_file('../../tests/aci/api.rego') +print(' Loaded Policy %s' % pkg) + +pkg = engine.add_policy_from_file('../../tests/aci/policy.rego') +print(' Loaded Policy %s' % pkg) # Add policy data data = { diff --git a/bindings/ruby/ext/regorusrb/Cargo.toml b/bindings/ruby/ext/regorusrb/Cargo.toml index 180b5c0e..cf6574b6 100644 --- a/bindings/ruby/ext/regorusrb/Cargo.toml +++ b/bindings/ruby/ext/regorusrb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "regorusrb" -version = "0.1.0" +version = "0.1.5" edition = "2021" description = "Ruby bindings for Regorus - a fast, lightweight Rego interpreter written in Rust" publish = false diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index 03ad8358..ba588e03 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "regorusjs" -version = "0.1.0" +version = "0.1.5" edition = "2021" repository = "https://github.com/microsoft/regorus/bindings/wasm" description = "WASM bindings for Regorus - a fast, lightweight Rego interpreter written in Rust" diff --git a/bindings/wasm/src/lib.rs b/bindings/wasm/src/lib.rs index 08435f57..397bb74f 100644 --- a/bindings/wasm/src/lib.rs +++ b/bindings/wasm/src/lib.rs @@ -50,7 +50,7 @@ impl Engine { /// /// * `path`: A filename to be associated with the policy. /// * `rego`: Rego policy. - pub fn add_policy(&mut self, path: String, rego: String) -> Result<(), JsValue> { + pub fn add_policy(&mut self, path: String, rego: String) -> Result { self.engine.add_policy(path, rego).map_err(error_to_jsvalue) } diff --git a/bindings/wasm/test.js b/bindings/wasm/test.js index bd2d7ddc..a0304bc2 100644 --- a/bindings/wasm/test.js +++ b/bindings/wasm/test.js @@ -7,7 +7,7 @@ var regorus = require('./pkg/regorusjs') var engine = new regorus.Engine(); // Add Rego policy. -engine.add_policy( +var pkg = engine.add_policy( // Associate this file name with policy 'hello.rego', @@ -18,6 +18,7 @@ engine.add_policy( # Join messages message = concat(", ", [input.message, data.message]) `) +console.log("Loaded policy " + pkg) // Set policy data engine.add_data_json(` @@ -34,7 +35,7 @@ engine.set_input_json(` `) // Eval query -results = engine.eval_query('data.test.message') +var results = engine.eval_query('data.test.message') // Display console.log(results)