From 56859c07fab8e7f303e1946b8e4c961b85a77199 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Tue, 14 May 2024 14:18:10 +0530 Subject: [PATCH] Add jni bindings for FileStorage --- fs-storage/Cargo.toml | 3 +- fs-storage/src/file_storage.rs | 111 +++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/fs-storage/Cargo.toml b/fs-storage/Cargo.toml index 518eabf5..61f378ce 100644 --- a/fs-storage/Cargo.toml +++ b/fs-storage/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [lib] name = "fs_storage" -crate-type = ["rlib"] +crate-type = ["rlib", "cdylib"] bench = false [[example]] @@ -16,6 +16,7 @@ data-error = { path = "../data-error" } log = { version = "0.4.17", features = ["release_max_level_off"] } serde_json = "1.0.82" serde = { version = "1.0.138", features = ["derive"] } +jni = "0.21.1" [dev-dependencies] anyhow = "1.0.81" diff --git a/fs-storage/src/file_storage.rs b/fs-storage/src/file_storage.rs index 720330d8..b231f4ca 100644 --- a/fs-storage/src/file_storage.rs +++ b/fs-storage/src/file_storage.rs @@ -256,3 +256,114 @@ mod tests { assert_eq!(file_storage.is_storage_updated().unwrap(), true); } } + +// This is the interface to the JVM that we'll call the majority of our +// methods on. +use jni::JNIEnv; + +// These objects are what you should use as arguments to your native +// function. They carry extra lifetime information to prevent them escaping +// this context and getting used after being GC'd. +use jni::objects::{JClass, JString}; + +// This is just a pointer. We'll be returning it from our function. We +// can't return one of the objects with lifetime information because the +// lifetime checker won't let us. +use jni::sys::{jboolean, jlong, jobject}; + +impl FileStorage { + fn from_jlong<'a>(value: jlong) -> &'a mut Self { + unsafe { &mut *(value as *mut FileStorage) } + } +} + +#[no_mangle] +pub extern "system" fn Java_FileStorage_create( + env: &mut JNIEnv, + _class: JClass, + label: JString, + path: JString, +) -> jlong { + let label: String = env.get_string(&label).unwrap().into(); + let path: String = env.get_string(&path).unwrap().into(); + + let file_storage: FileStorage = + FileStorage::new(label, Path::new(&path)); + Box::into_raw(Box::new(file_storage)) as jlong +} + +#[no_mangle] +pub extern "system" fn Java_FileStorage_set( + env: &mut JNIEnv, + _class: JClass, + id: JString, + value: JString, + file_storage_ptr: jlong, +) { + let id: String = env.get_string(&id).unwrap().into(); + let value: String = env.get_string(&value).unwrap().into(); + + FileStorage::from_jlong(file_storage_ptr).set(id, value); +} + +#[no_mangle] +pub extern "system" fn Java_FileStorage_remove( + env: &mut JNIEnv, + _class: JClass, + id: JString, + file_storage_ptr: jlong, +) { + let id: String = env.get_string(&id).unwrap().into(); + + FileStorage::from_jlong(file_storage_ptr) + .remove(&id) + .unwrap(); +} + +#[no_mangle] +pub extern "system" fn Java_FileStorage_is_storage_updated( + env: &mut JNIEnv, + _class: JClass, + file_storage_ptr: jlong, +) -> jboolean { + match FileStorage::from_jlong(file_storage_ptr).is_storage_updated() { + Ok(updated) => updated as jboolean, + Err(_) => 0, // handle error here + } +} + +#[no_mangle] +pub extern "system" fn Java_FileStorage_read_fs( + env: &mut JNIEnv, + _class: JClass, + file_storage_ptr: jlong, +) -> jobject { + let data = FileStorage::from_jlong(file_storage_ptr) + .read_fs() + .unwrap(); + todo!() +} + +#[no_mangle] +pub extern "system" fn Java_FileStorage_write_fs( + env: &mut JNIEnv, + _class: JClass, + file_storage_ptr: jlong, +) { + FileStorage::from_jlong(file_storage_ptr) + .write_fs() + .unwrap() +} + +///! Safety: The FileStorage instance is dropped after this call +#[no_mangle] +pub extern "system" fn Java_FileStorage_erase( + env: &mut JNIEnv, + _class: JClass, + file_storage_ptr: jlong, +) { + let file_storage = unsafe { + Box::from_raw(file_storage_ptr as *mut FileStorage) + }; + file_storage.erase().unwrap(); +}