c_no_std binding to show use in C freestanding environments. (#238)

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2024-05-17 21:31:11 -04:00
committed by GitHub
parent 5422bde391
commit 67f65c0561
12 changed files with 202 additions and 13 deletions

View File

@@ -0,0 +1,41 @@
# 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")
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 "regorus-ffi" crate.
CRATES "regorus-ffi"
# Turn off std support in regorus-ffi.
NO_DEFAULT_FEATURES
NO_STD
# custom_allocator allows using a custom memory allocator.
# To use malloc/free remove custom_allocator below.
# Additionally, select specific features in regorus.
# See regorus/opa_no_std
FEATURES "custom_allocator,regorus/semver"
# Link statically
CRATE_TYPES staticlib FLAGS --crate-type=staticlib
)
add_executable(regorus_test_nostd main.c)
# Add path to <regorus-source-folder>/bindings/ffi
target_include_directories(regorus_test_nostd PRIVATE "../ffi")
target_link_libraries(regorus_test_nostd regorus-ffi)

96
bindings/c-nostd/main.c Normal file
View File

@@ -0,0 +1,96 @@
#include <stdio.h>
#include "regorus.h"
// Regorus has been built for no_std and cannot access files.
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);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
return buffer;
}
// 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);
}
void regorus_free(uint8_t* ptr) {
free(ptr);
}
int main() {
// Create engine.
RegorusEngine* engine = regorus_engine_new();
RegorusResult r;
char* buffer = NULL;
// Load policies.
r = regorus_engine_add_policy(engine, "framework.rego", (buffer = file_to_string("../../../tests/aci/framework.rego")));
free(buffer);
if (r.status != RegorusStatusOk)
goto error;
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;
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;
regorus_result_drop(r);
// Add data
r = regorus_engine_add_data_json(engine, (buffer = file_to_string("../../../tests/aci/data.json")));
free(buffer);
if (r.status != RegorusStatusOk)
goto error;
regorus_result_drop(r);
// Set input
r = regorus_engine_set_input_json(engine, (buffer = file_to_string("../../../tests/aci/input.json")));
free(buffer);
if (r.status != RegorusStatusOk)
goto error;
regorus_result_drop(r);
// Eval query
r = regorus_engine_eval_query(engine, "data.framework.mount_overlay=x");
if (r.status != RegorusStatusOk)
goto error;
// 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;
}

View File

@@ -18,8 +18,15 @@ 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.c)
# Add path to <regorus-source-folder>/bindings/ffi

View File

@@ -5,13 +5,18 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
crate-type = ["cdylib", "staticlib"]
[dependencies]
anyhow = "1.0"
regorus = { path = "../.." }
regorus = { path = "../..", default-features = false }
serde_json = "1.0.113"
[features]
default = ["std"]
std = ["regorus/std"]
custom_allocator = []
[build-dependencies]
cbindgen = "0.26.0"
csbindgen = "1.9.0"

View File

@@ -85,4 +85,3 @@ namespace RegorusFFI
}

View File

@@ -137,9 +137,6 @@ bitflags = false
############## Options for How Your Rust library Should Be Parsed ##############
[parse]
@@ -154,5 +151,5 @@ extra_bindings = []
[parse.expand]
crates = []
all_features = false
default_features = true
default_features = false
features = []

View File

@@ -90,6 +90,10 @@ RegorusResult regorus_engine_set_input_from_json_file(RegorusEngine *engine, con
/// * `query`: Rego expression to be evaluate.
RegorusResult regorus_engine_eval_query(RegorusEngine *engine, const char *query);
extern uint8_t *regorus_aligned_alloc(uintptr_t alignment, uintptr_t size);
extern void regorus_free(uint8_t *ptr);
} // extern "C"
#endif // REGORUS_FFI_HPP

View File

@@ -124,4 +124,8 @@ struct RegorusResult regorus_engine_set_input_from_json_file(struct RegorusEngin
*/
struct RegorusResult regorus_engine_eval_query(struct RegorusEngine *engine, const char *query);
extern uint8_t *regorus_aligned_alloc(uintptr_t alignment, uintptr_t size);
extern void regorus_free(uint8_t *ptr);
#endif /* REGORUS_H */

View File

@@ -127,7 +127,6 @@ pub extern "C" fn regorus_engine_drop(engine: *mut RegorusEngine) {
///
/// * `path`: A filename to be associated with the policy.
/// * `rego`: Rego policy.
#[no_mangle]
pub extern "C" fn regorus_engine_add_policy(
engine: *mut RegorusEngine,
@@ -141,6 +140,7 @@ pub extern "C" fn regorus_engine_add_policy(
}())
}
#[cfg(feature = "std")]
#[no_mangle]
pub extern "C" fn regorus_engine_add_policy_from_file(
engine: *mut RegorusEngine,
@@ -169,6 +169,7 @@ pub extern "C" fn regorus_engine_add_data_json(
}())
}
#[cfg(feature = "std")]
#[no_mangle]
pub extern "C" fn regorus_engine_add_data_from_json_file(
engine: *mut RegorusEngine,
@@ -209,6 +210,7 @@ pub extern "C" fn regorus_engine_set_input_json(
}())
}
#[cfg(feature = "std")]
#[no_mangle]
pub extern "C" fn regorus_engine_set_input_from_json_file(
engine: *mut RegorusEngine,
@@ -246,3 +248,32 @@ pub extern "C" fn regorus_engine_eval_query(
Err(e) => to_regorus_result(Err(e)),
}
}
#[cfg(feature = "custom_allocator")]
extern "C" {
fn regorus_aligned_alloc(alignment: usize, size: usize) -> *mut u8;
fn regorus_free(ptr: *mut u8);
}
#[cfg(feature = "custom_allocator")]
mod allocator {
use std::alloc::{GlobalAlloc, Layout};
struct RegorusAllocator {}
unsafe impl GlobalAlloc for RegorusAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let size = layout.size();
let align = layout.align();
crate::regorus_aligned_alloc(align, size)
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
crate::regorus_free(ptr)
}
}
#[global_allocator]
static ALLOCATOR: RegorusAllocator = RegorusAllocator {};
}