mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat(bindings)!: add RVM/Program support across FFI and language bindings (#565)
- FFI: add RVM/Program APIs, execution state accessors, HostAwait handling, and buffer/result helpers in rvm.rs, common.rs, engine.rs. - Compiler: emit HostAwait for __builtin_host_await in function_calls.rs. - RVM tests: add HostAwait regression cases and extend harness for suspend/resume responses in host_await.yaml and mod.rs. - C/C++: add RVM tests/examples and wrapper updates in rvm_tests.c, rvm_tests.cpp, regorus.hpp, plus CMake wiring. - C#: add Program/Rvm bindings, SafeHandle/PInvoke, tests, and example usage in Regorus, RvmProgramTests.cs, Program.cs, and README updates. - Go: add Program/Rvm bindings, tests, and examples in rvm.go, rvm_test.go, main.go. - Java: add Program/Rvm bindings, JNI glue, and examples in lib.rs, regorus, Test.java. - Python: add Program/Rvm bindings and examples in lib.rs, test.py. - WASM: add Program/Rvm bindings and examples in lib.rs, test.js. - Tooling: wire binding tests in xtask and ignore generated Java artifacts in .gitignore. Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
0316ccd90c
commit
3f7a5496dc
@@ -2,11 +2,17 @@
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use anyhow::Result;
|
||||
use jni::objects::{JClass, JObject, JString};
|
||||
use jni::sys::{jlong, jstring};
|
||||
use jni::objects::{JBooleanArray, JByteArray, JClass, JObject, JObjectArray, JString};
|
||||
use jni::sys::{jboolean, jbooleanArray, jbyteArray, jlong, jobjectArray, jstring};
|
||||
use jni::JNIEnv;
|
||||
|
||||
use regorus::{Engine, Value};
|
||||
use regorus::languages::rego::compiler::Compiler;
|
||||
use regorus::rvm::program::{
|
||||
generate_assembly_listing, AssemblyListingConfig, DeserializationResult, Program as RvmProgram,
|
||||
};
|
||||
use regorus::rvm::vm::{ExecutionMode, RegoVM};
|
||||
use regorus::{compile_policy_with_entrypoint, Engine, PolicyModule, Rc, Value};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeNewEngine(
|
||||
@@ -370,6 +376,336 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeDestroyEngine(
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Program_nativeCompileFromModules(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
data_json: JString,
|
||||
module_ids: jobjectArray,
|
||||
module_contents: jobjectArray,
|
||||
entry_points: jobjectArray,
|
||||
) -> jlong {
|
||||
let res = throw_err(env, |env| {
|
||||
let data_json: String = env.get_string(&data_json)?.into();
|
||||
let data = Value::from_json_str(&data_json)?;
|
||||
|
||||
let ids = get_string_array(env, module_ids)?;
|
||||
let contents = get_string_array(env, module_contents)?;
|
||||
if ids.len() != contents.len() {
|
||||
return Err(anyhow::anyhow!("module id/content length mismatch"));
|
||||
}
|
||||
|
||||
let mut modules = Vec::with_capacity(ids.len());
|
||||
for (id, content) in ids.into_iter().zip(contents.into_iter()) {
|
||||
modules.push(PolicyModule {
|
||||
id: Rc::from(id.as_str()),
|
||||
content: Rc::from(content.as_str()),
|
||||
});
|
||||
}
|
||||
|
||||
let entry_points_vec = get_string_array(env, entry_points)?;
|
||||
if entry_points_vec.is_empty() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"entry_points must contain at least one entry"
|
||||
));
|
||||
}
|
||||
let entry_points_ref: Vec<&str> = entry_points_vec.iter().map(|s| s.as_str()).collect();
|
||||
let entry_rule = entry_points_ref[0];
|
||||
|
||||
let compiled = compile_policy_with_entrypoint(data, &modules, Rc::from(entry_rule))?;
|
||||
let program = Compiler::compile_from_policy(&compiled, &entry_points_ref)?;
|
||||
Ok(Box::into_raw(Box::new(program)) as jlong)
|
||||
});
|
||||
|
||||
res.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Program_nativeCompileFromEngine(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
engine_ptr: jlong,
|
||||
entry_points: jobjectArray,
|
||||
) -> jlong {
|
||||
let res = throw_err(env, |env| {
|
||||
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
|
||||
let entry_points_vec = get_string_array(env, entry_points)?;
|
||||
if entry_points_vec.is_empty() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"entry_points must contain at least one entry"
|
||||
));
|
||||
}
|
||||
let entry_points_ref: Vec<&str> = entry_points_vec.iter().map(|s| s.as_str()).collect();
|
||||
let entry_rule = Rc::from(entry_points_ref[0]);
|
||||
let compiled = engine.compile_with_entrypoint(&entry_rule)?;
|
||||
let program = Compiler::compile_from_policy(&compiled, &entry_points_ref)?;
|
||||
Ok(Box::into_raw(Box::new(program)) as jlong)
|
||||
});
|
||||
|
||||
res.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Program_nativeGenerateListing(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
program_ptr: jlong,
|
||||
) -> jstring {
|
||||
let res = throw_err(env, |env| {
|
||||
let program = unsafe { &*(program_ptr as *mut Arc<RvmProgram>) };
|
||||
let listing =
|
||||
generate_assembly_listing(program.as_ref(), &AssemblyListingConfig::default());
|
||||
let output = env.new_string(&listing)?;
|
||||
Ok(output.into_raw())
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(_) => JObject::null().into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Program_nativeSerializeBinary(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
program_ptr: jlong,
|
||||
) -> jbyteArray {
|
||||
let res = throw_err(env, |env| {
|
||||
let program = unsafe { &*(program_ptr as *mut Arc<RvmProgram>) };
|
||||
let bytes = program.serialize_binary().map_err(|e| anyhow::anyhow!(e))?;
|
||||
let array = env.byte_array_from_slice(&bytes)?;
|
||||
Ok(array.into_raw())
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(_) => JObject::null().into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
/// # Safety
|
||||
///
|
||||
/// The `data` and `is_partial` pointers must be valid JNI array references
|
||||
/// for the duration of the call. They must come from the JVM for the current
|
||||
/// thread and not be used after this function returns.
|
||||
pub unsafe extern "system" fn Java_com_microsoft_regorus_Program_nativeDeserializeBinary(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
data: jbyteArray,
|
||||
is_partial: jbooleanArray,
|
||||
) -> jlong {
|
||||
let res = throw_err(env, |env| {
|
||||
if data.is_null() {
|
||||
return Err(anyhow::anyhow!("data must not be null"));
|
||||
}
|
||||
|
||||
let data = unsafe { JByteArray::from_raw(data) };
|
||||
let bytes = env.convert_byte_array(&data)?;
|
||||
let (program, partial) =
|
||||
match RvmProgram::deserialize_binary(&bytes).map_err(|e| anyhow::anyhow!(e))? {
|
||||
DeserializationResult::Complete(program) => (program, false),
|
||||
DeserializationResult::Partial(program) => (program, true),
|
||||
};
|
||||
|
||||
if !is_partial.is_null() {
|
||||
let is_partial = unsafe { JBooleanArray::from_raw(is_partial) };
|
||||
let len = env.get_array_length(&is_partial)?;
|
||||
if len > 0 {
|
||||
let value: [jboolean; 1] = [if partial { 1 } else { 0 }];
|
||||
env.set_boolean_array_region(&is_partial, 0, &value)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Box::into_raw(Box::new(Arc::new(program))) as jlong)
|
||||
});
|
||||
|
||||
res.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Program_nativeDrop(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
program_ptr: jlong,
|
||||
) {
|
||||
unsafe {
|
||||
let _program = Box::from_raw(program_ptr as *mut Arc<RvmProgram>);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeNew(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
) -> jlong {
|
||||
let vm = RegoVM::new();
|
||||
Box::into_raw(Box::new(vm)) as jlong
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeLoadProgram(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
program_ptr: jlong,
|
||||
) {
|
||||
let _ = throw_err(env, |_env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let program = unsafe { &*(program_ptr as *mut Arc<RvmProgram>) };
|
||||
vm.load_program(program.clone());
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeSetDataJson(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
data_json: JString,
|
||||
) {
|
||||
let _ = throw_err(env, |env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let data_json: String = env.get_string(&data_json)?.into();
|
||||
let data = Value::from_json_str(&data_json)?;
|
||||
vm.set_data(data)?;
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeSetInputJson(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
input_json: JString,
|
||||
) {
|
||||
let _ = throw_err(env, |env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let input_json: String = env.get_string(&input_json)?.into();
|
||||
let input = Value::from_json_str(&input_json)?;
|
||||
vm.set_input(input);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeSetExecutionMode(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
mode: u8,
|
||||
) {
|
||||
let _ = throw_err(env, |_env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let mode = match mode {
|
||||
0 => ExecutionMode::RunToCompletion,
|
||||
1 => ExecutionMode::Suspendable,
|
||||
_ => return Err(anyhow::anyhow!("invalid execution mode")),
|
||||
};
|
||||
vm.set_execution_mode(mode);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeExecute(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
) -> jstring {
|
||||
let res = throw_err(env, |env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let result = vm.execute()?;
|
||||
let output = env.new_string(result.to_json_str()?)?;
|
||||
Ok(output.into_raw())
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(_) => JObject::null().into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeExecuteEntryPoint(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
entry_point: JString,
|
||||
) -> jstring {
|
||||
let res = throw_err(env, |env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let entry_point: String = env.get_string(&entry_point)?.into();
|
||||
let result = vm.execute_entry_point_by_name(&entry_point)?;
|
||||
let output = env.new_string(result.to_json_str()?)?;
|
||||
Ok(output.into_raw())
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(_) => JObject::null().into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeResume(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
resume_json: JString,
|
||||
has_value: bool,
|
||||
) -> jstring {
|
||||
let res = throw_err(env, |env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let value = if has_value {
|
||||
let resume_json: String = env.get_string(&resume_json)?.into();
|
||||
Some(Value::from_json_str(&resume_json)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let result = vm.resume(value)?;
|
||||
let output = env.new_string(result.to_json_str()?)?;
|
||||
Ok(output.into_raw())
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(_) => JObject::null().into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeGetExecutionState(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
) -> jstring {
|
||||
let res = throw_err(env, |env| {
|
||||
let vm = unsafe { &mut *(vm_ptr as *mut RegoVM) };
|
||||
let output = env.new_string(format!("{:?}", vm.execution_state()))?;
|
||||
Ok(output.into_raw())
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(_) => JObject::null().into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Rvm_nativeDrop(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
vm_ptr: jlong,
|
||||
) {
|
||||
unsafe {
|
||||
let _vm = Box::from_raw(vm_ptr as *mut RegoVM);
|
||||
}
|
||||
}
|
||||
|
||||
fn throw_err<T>(mut env: JNIEnv, mut f: impl FnMut(&mut JNIEnv) -> Result<T>) -> Result<T> {
|
||||
match f(&mut env) {
|
||||
Ok(val) => Ok(val),
|
||||
@@ -379,3 +715,19 @@ fn throw_err<T>(mut env: JNIEnv, mut f: impl FnMut(&mut JNIEnv) -> Result<T>) ->
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_string_array(env: &mut JNIEnv, array: jobjectArray) -> Result<Vec<String>> {
|
||||
if array.is_null() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let array = unsafe { JObjectArray::from_raw(array) };
|
||||
let len = env.get_array_length(&array)?;
|
||||
let mut values = Vec::with_capacity(len as usize);
|
||||
for i in 0..len {
|
||||
let obj = env.get_object_array_element(&array, i)?;
|
||||
let jstr = JString::from(obj);
|
||||
let value: String = env.get_string(&jstr)?.into();
|
||||
values.push(value);
|
||||
}
|
||||
Ok(values)
|
||||
}
|
||||
|
||||
@@ -221,6 +221,8 @@ public class Engine implements AutoCloseable, Cloneable {
|
||||
|
||||
/**
|
||||
* Get coverage report as json string.
|
||||
*
|
||||
* @return Coverage report as a JSON string.
|
||||
*
|
||||
*/
|
||||
public String getCoverageReport() {
|
||||
@@ -229,6 +231,8 @@ public class Engine implements AutoCloseable, Cloneable {
|
||||
|
||||
/**
|
||||
* Get coverage report as ANSI color coded string.
|
||||
*
|
||||
* @return Coverage report formatted for console output.
|
||||
*
|
||||
*/
|
||||
public String getCoverageReportPretty() {
|
||||
@@ -247,12 +251,18 @@ public class Engine implements AutoCloseable, Cloneable {
|
||||
|
||||
/**
|
||||
* Take gathered prints.
|
||||
*
|
||||
* @return Collected print output as JSON.
|
||||
*
|
||||
*/
|
||||
public String takePrints() {
|
||||
return nativeTakePrints(enginePtr);
|
||||
}
|
||||
|
||||
long getPtr() {
|
||||
return enginePtr;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* Licensed under the MIT License.
|
||||
**/
|
||||
|
||||
package com.microsoft.regorus;
|
||||
|
||||
/**
|
||||
* Represents a Rego module used for RVM program compilation.
|
||||
*/
|
||||
public final class PolicyModule {
|
||||
/**
|
||||
* Module identifier or filename.
|
||||
*/
|
||||
public final String id;
|
||||
|
||||
/**
|
||||
* Rego policy content.
|
||||
*/
|
||||
public final String content;
|
||||
|
||||
/**
|
||||
* Create a new policy module.
|
||||
*
|
||||
* @param id Module identifier or filename.
|
||||
* @param content Rego policy content.
|
||||
*/
|
||||
public PolicyModule(String id, String content) {
|
||||
this.id = id;
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
102
bindings/java/src/main/java/com/microsoft/regorus/Program.java
Normal file
102
bindings/java/src/main/java/com/microsoft/regorus/Program.java
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* Licensed under the MIT License.
|
||||
**/
|
||||
|
||||
package com.microsoft.regorus;
|
||||
|
||||
/**
|
||||
* Represents a compiled RVM program.
|
||||
*/
|
||||
public final class Program implements AutoCloseable {
|
||||
private static native long nativeCompileFromModules(
|
||||
String dataJson,
|
||||
String[] moduleIds,
|
||||
String[] moduleContents,
|
||||
String[] entryPoints);
|
||||
|
||||
private static native long nativeCompileFromEngine(long enginePtr, String[] entryPoints);
|
||||
private static native String nativeGenerateListing(long programPtr);
|
||||
private static native byte[] nativeSerializeBinary(long programPtr);
|
||||
private static native long nativeDeserializeBinary(byte[] data, boolean[] isPartial);
|
||||
private static native void nativeDrop(long programPtr);
|
||||
|
||||
private final long programPtr;
|
||||
|
||||
Program(long ptr) {
|
||||
this.programPtr = ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a program from modules and entry points.
|
||||
*
|
||||
* @param dataJson JSON document to merge as static data.
|
||||
* @param modules Policy modules to compile.
|
||||
* @param entryPoints Entry point rule paths.
|
||||
* @return Compiled program instance.
|
||||
*/
|
||||
public static Program compileFromModules(String dataJson, PolicyModule[] modules, String[] entryPoints) {
|
||||
String[] ids = new String[modules.length];
|
||||
String[] contents = new String[modules.length];
|
||||
for (int i = 0; i < modules.length; i++) {
|
||||
ids[i] = modules[i].id;
|
||||
contents[i] = modules[i].content;
|
||||
}
|
||||
long ptr = nativeCompileFromModules(dataJson, ids, contents, entryPoints);
|
||||
return new Program(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a program from an engine and entry points.
|
||||
*
|
||||
* @param engine Engine with loaded policies.
|
||||
* @param entryPoints Entry point rule paths.
|
||||
* @return Compiled program instance.
|
||||
*/
|
||||
public static Program compileFromEngine(Engine engine, String[] entryPoints) {
|
||||
long ptr = nativeCompileFromEngine(engine.getPtr(), entryPoints);
|
||||
return new Program(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a readable assembly listing.
|
||||
*
|
||||
* @return Listing text.
|
||||
*/
|
||||
public String generateListing() {
|
||||
return nativeGenerateListing(programPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the program to binary format.
|
||||
*
|
||||
* @return Serialized bytes.
|
||||
*/
|
||||
public byte[] serializeBinary() {
|
||||
return nativeSerializeBinary(programPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a program from binary format.
|
||||
*
|
||||
* @param data Serialized program bytes.
|
||||
* @param isPartial Optional array to receive the partial flag (index 0).
|
||||
* @return Deserialized program instance.
|
||||
*/
|
||||
public static Program deserializeBinary(byte[] data, boolean[] isPartial) {
|
||||
if (data == null || data.length == 0) {
|
||||
throw new IllegalArgumentException("data must not be empty");
|
||||
}
|
||||
long ptr = nativeDeserializeBinary(data, isPartial);
|
||||
return new Program(ptr);
|
||||
}
|
||||
|
||||
long getPtr() {
|
||||
return programPtr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
nativeDrop(programPtr);
|
||||
}
|
||||
}
|
||||
110
bindings/java/src/main/java/com/microsoft/regorus/Rvm.java
Normal file
110
bindings/java/src/main/java/com/microsoft/regorus/Rvm.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* Licensed under the MIT License.
|
||||
**/
|
||||
|
||||
package com.microsoft.regorus;
|
||||
|
||||
/**
|
||||
* Wrapper for the Regorus RVM runtime.
|
||||
*/
|
||||
public final class Rvm implements AutoCloseable {
|
||||
private static native long nativeNew();
|
||||
private static native void nativeDrop(long vmPtr);
|
||||
private static native void nativeLoadProgram(long vmPtr, long programPtr);
|
||||
private static native void nativeSetDataJson(long vmPtr, String dataJson);
|
||||
private static native void nativeSetInputJson(long vmPtr, String inputJson);
|
||||
private static native void nativeSetExecutionMode(long vmPtr, byte mode);
|
||||
private static native String nativeExecute(long vmPtr);
|
||||
private static native String nativeExecuteEntryPoint(long vmPtr, String entryPoint);
|
||||
private static native String nativeResume(long vmPtr, String resumeJson, boolean hasValue);
|
||||
private static native String nativeGetExecutionState(long vmPtr);
|
||||
|
||||
private final long vmPtr;
|
||||
|
||||
/**
|
||||
* Create a new RVM instance.
|
||||
*/
|
||||
public Rvm() {
|
||||
this.vmPtr = nativeNew();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a program into the VM.
|
||||
*
|
||||
* @param program Compiled program.
|
||||
*/
|
||||
public void loadProgram(Program program) {
|
||||
nativeLoadProgram(vmPtr, program.getPtr());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data JSON for the VM.
|
||||
*
|
||||
* @param dataJson JSON data document.
|
||||
*/
|
||||
public void setDataJson(String dataJson) {
|
||||
nativeSetDataJson(vmPtr, dataJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set input JSON for the VM.
|
||||
*
|
||||
* @param inputJson JSON input document.
|
||||
*/
|
||||
public void setInputJson(String inputJson) {
|
||||
nativeSetInputJson(vmPtr, inputJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set execution mode (0 = run-to-completion, 1 = suspendable).
|
||||
*
|
||||
* @param mode Execution mode.
|
||||
*/
|
||||
public void setExecutionMode(byte mode) {
|
||||
nativeSetExecutionMode(vmPtr, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the program.
|
||||
*
|
||||
* @return JSON result string.
|
||||
*/
|
||||
public String execute() {
|
||||
return nativeExecute(vmPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a named entry point.
|
||||
*
|
||||
* @param entryPoint Entry point rule path.
|
||||
* @return JSON result string.
|
||||
*/
|
||||
public String executeEntryPoint(String entryPoint) {
|
||||
return nativeExecuteEntryPoint(vmPtr, entryPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume execution with an optional JSON value.
|
||||
*
|
||||
* @param resumeJson JSON value to resume with, or null for no value.
|
||||
* @return JSON result string.
|
||||
*/
|
||||
public String resume(String resumeJson) {
|
||||
return nativeResume(vmPtr, resumeJson, resumeJson != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current execution state.
|
||||
*
|
||||
* @return Execution state string.
|
||||
*/
|
||||
public String getExecutionState() {
|
||||
return nativeGetExecutionState(vmPtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
nativeDrop(vmPtr);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user