C++ binding (#129)

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2024-02-05 00:22:27 -08:00
committed by GitHub
parent 22260ac46f
commit dda525b989
6 changed files with 253 additions and 6 deletions

View File

@@ -11,7 +11,7 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(Corrosion)
project("regorus-test-c")
project("regorus-test")
corrosion_import_crate(
# Path to <regorus-source-folder>/bindings/ffi/Cargo.toml

View File

@@ -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 <regorus-source-folder>/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 <regorus-source-folder>/bindings/ffi
target_include_directories(regorus_test PRIVATE "../ffi")
target_link_libraries(regorus_test regorus-ffi)

118
bindings/cpp/main.cpp Normal file
View File

@@ -0,0 +1,118 @@
#include <iostream>
#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<<result.output()<<std::endl;
} else {
std::cerr<<result.error()<<std::endl;
}
}
int main() {
// Create engine.
regorus::Engine engine;
// Load policies.
const char* policies[] = {
"../../../tests/aci/framework.rego",
"../../../tests/aci/policy.rego",
"../../../tests/aci/api.rego",
};
// Add policies and data.
for (auto policy : policies) {
auto result = engine.add_policy_from_file(policy);
if (!result) {
std::cerr<<result.error()<<std::endl;
return -1;
}
}
{
auto result = engine.add_data_from_json_file("../../../tests/aci/data.json");
if (!result) {
std::cerr<<result.error()<<std::endl;
return -1;
}
}
// Set input and eval query.
{
auto result = engine.set_input_from_json_file("../../../tests/aci/input.json");
if (!result) {
std::cerr<<result.error()<<std::endl;
return -1;
}
}
auto result = engine.eval_query("data.framework.mount_overlay = x");
if (!result) {
std::cerr<<result.error()<<std::endl;
return -1;
}
std::cout<<result.output()<<std::endl;
example();
}

101
bindings/cpp/regorus.hpp Normal file
View File

@@ -0,0 +1,101 @@
#ifndef REGORUS_WRAPPER_HPP
#define REGORUS_WRAPPER_HPP
#include <memory>
#include <variant>
#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<Engine> clone() const {
return std::unique_ptr<Engine>(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

View File

@@ -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")

View File

@@ -1,5 +1,5 @@
#ifndef REGORUS_HPP
#define REGORUS_HPP
#ifndef REGORUS_FFI_HPP
#define REGORUS_FFI_HPP
#include <cstdarg>
#include <cstdint>
@@ -92,4 +92,4 @@ RegorusResult regorus_engine_eval_query(RegorusEngine *engine, const char *query
} // extern "C"
#endif // REGORUS_HPP
#endif // REGORUS_FFI_HPP