diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index df3a49d..9cc9222 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -11,7 +11,7 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(Corrosion) -project("regorus-test-c") +project("regorus-test") corrosion_import_crate( # Path to /bindings/ffi/Cargo.toml diff --git a/bindings/cpp/CMakeLists.txt b/bindings/cpp/CMakeLists.txt new file mode 100644 index 0000000..18ce8fb --- /dev/null +++ b/bindings/cpp/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (c) Microsoft +# Licensed under the MIT License. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) +include(FetchContent) + +FetchContent_Declare( + Corrosion + GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git + GIT_TAG v0.4 # Optionally specify a commit hash, version tag or branch here +) +FetchContent_MakeAvailable(Corrosion) + +project("regorus-test") +set(CMAKE_CXX_STANDARD 17) + +corrosion_import_crate( + # Path to /bindings/ffi/Cargo.toml + MANIFEST_PATH "../ffi/Cargo.toml" + # Always build regorus in Release mode. + PROFILE "release" + # Only build the "regorusc" crate. + CRATES "regorus-ffi") + +add_executable(regorus_test main.cpp) +# Add path to /bindings/ffi +target_include_directories(regorus_test PRIVATE "../ffi") +target_link_libraries(regorus_test regorus-ffi) diff --git a/bindings/cpp/main.cpp b/bindings/cpp/main.cpp new file mode 100644 index 0000000..7706e1b --- /dev/null +++ b/bindings/cpp/main.cpp @@ -0,0 +1,118 @@ +#include +#include "regorus.hpp" + +void example() +{ + // Create engine + regorus::Engine engine; + + // Add policies. + engine.add_policy("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"])"); + + // Add data. + engine.add_data_json(R"({ + "one": { + "bar": "Foo", + "baz": 5, + "be": true, + "bop": 23.4 + }, + "two": { + "bar": "Bar", + "baz": 12.3, + "be": false, + "bop": 42 + } +})"); + + engine.add_data_json(R"({ + "three": { + "bar": "Baz", + "baz": 15, + "be": true, + "bop": 4.23 + } +})"); + + // Set input. + engine.set_input_json(R"({ + "a": 10, + "b": "20", + "c": 30.0, + "d": true +})"); + + // Eval query. + auto result = engine.eval_query("[data.one, input.b, data.objects.sites[1]] = x"); + if (result) { + std::cout< +#include + +#include "regorus.ffi.hpp" + +namespace regorus { + + class Result { + public: + + operator bool() const { return result.status == RegorusStatus::RegorusStatusOk; } + bool operator !() const { return result.status != RegorusStatus::RegorusStatusOk; } + + const char* output() const { + if (*this && result.output) { + return result.output; + } else { + return ""; + } + } + + const char* error() const { + if (!*this && result.error_message) { + return result.error_message; + } else { + return ""; + } + } + + ~Result() { + regorus_result_drop(result); + } + + private: + friend class Engine; + RegorusResult result; + + Result(RegorusResult r) : result(r) {} + private: + Result(const Result&) = delete; + Result(Result&&) = delete; + Result& operator=(const Result&) = delete; + + }; + + class Engine { + public: + Engine() : Engine(regorus_engine_new()) {} + + std::unique_ptr clone() const { + return std::unique_ptr(new Engine(regorus_engine_clone(engine))); + } + + + Result add_policy(const char* path, const char* policy) { + return Result(regorus_engine_add_policy(engine, path, policy)); + } + + Result add_policy_from_file(const char* path) { + return Result(regorus_engine_add_policy_from_file(engine, path)); + } + + Result add_data_json(const char* data) { + return Result(regorus_engine_add_data_json(engine, data)); + } + + Result add_data_from_json_file(const char* path) { + return Result(regorus_engine_add_data_from_json_file(engine, path)); + } + + Result set_input_json(const char* input) { + return Result(regorus_engine_set_input_json(engine, input)); + } + + Result set_input_from_json_file(const char* path) { + return Result(regorus_engine_set_input_from_json_file(engine, path)); + } + + Result eval_query(const char* query) { + return Result(regorus_engine_eval_query(engine, query)); + } + + ~Engine() { + regorus_engine_drop(engine); + } + + + private: + RegorusEngine* engine; + private: + Engine(RegorusEngine* e) : engine(e) {} + Engine(const Engine&) = delete; + Engine(Engine&&) = delete; + Engine& operator=(const Engine&) = delete; + }; +} + +#endif // REGORUS_WRAPPER_HPP diff --git a/bindings/ffi/build.rs b/bindings/ffi/build.rs index 8707ad5..a48986d 100644 --- a/bindings/ffi/build.rs +++ b/bindings/ffi/build.rs @@ -17,10 +17,10 @@ fn main() { cbindgen::Builder::new() .with_crate(crate_dir) .with_language(cbindgen::Language::Cxx) - .with_include_guard("REGORUS_HPP") + .with_include_guard("REGORUS_FFI_HPP") .generate() .expect("Unable to generate bindings") - .write_to_file("regorus.hpp"); + .write_to_file("regorus.ffi.hpp"); csbindgen::Builder::default() .input_extern_file("src/lib.rs") diff --git a/bindings/ffi/regorus.hpp b/bindings/ffi/regorus.ffi.hpp similarity index 97% rename from bindings/ffi/regorus.hpp rename to bindings/ffi/regorus.ffi.hpp index e58b9d0..a8b8a64 100644 --- a/bindings/ffi/regorus.hpp +++ b/bindings/ffi/regorus.ffi.hpp @@ -1,5 +1,5 @@ -#ifndef REGORUS_HPP -#define REGORUS_HPP +#ifndef REGORUS_FFI_HPP +#define REGORUS_FFI_HPP #include #include @@ -92,4 +92,4 @@ RegorusResult regorus_engine_eval_query(RegorusEngine *engine, const char *query } // extern "C" -#endif // REGORUS_HPP +#endif // REGORUS_FFI_HPP