diff --git a/Cargo.toml b/Cargo.toml index d6b38ad..5e5ac0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ tracing-subscriber = { version = "0.3.18", optional = true } # glue (java) jni = { version = "0.21.1", features = ["invocation"], optional = true } -#jni-sys = { version = "0.3.0", optional = true } + # glue (lua) mlua = { version = "0.9.6", features = ["module", "luajit", "send"], optional = true } derive_more = { version = "0.99.17", optional = true } diff --git a/src/ffi/java/client.rs b/src/ffi/java/client.rs index ea12e59..4f944a0 100644 --- a/src/ffi/java/client.rs +++ b/src/ffi/java/client.rs @@ -6,7 +6,7 @@ use super::{util::JExceptable, RT}; /// Called by the Java GC to drop a [Client]. #[no_mangle] pub extern "system" fn Java_mp_code_Client_free(_env: JNIEnv, _class: JClass, input: jlong) { - super::util::dereference_and_drop::(input) + let _ = unsafe { Box::from_raw(input as *mut Client) }; } /// Sets up tracing subscriber @@ -38,6 +38,21 @@ pub extern "system" fn Java_mp_code_Client_connect<'local>( .jexcept(&mut env) } +/// Gets a [Workspace] by name and returns a pointer to it. +#[no_mangle] +pub extern "system" fn Java_mp_code_Client_get_1workspace<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + self_ptr: jlong, + input: JString<'local> +) -> jlong { + let client = unsafe { Box::leak(Box::from_raw(self_ptr as *mut Client)) }; + let workspace_id = unsafe { env.get_string_unchecked(&input).expect("Couldn't get java string!") }; + client.get_workspace(workspace_id.to_str().expect("Not UTF-8")) + .map(|workspace| Box::into_raw(Box::new(workspace)) as jlong) + .unwrap_or_default() +} + /// Logs in to a specific [Workspace]. #[no_mangle] pub extern "system" fn Java_mp_code_Client_login<'local>( diff --git a/src/ffi/java/util.rs b/src/ffi/java/util.rs index ca0a6c3..d21e832 100644 --- a/src/ffi/java/util.rs +++ b/src/ffi/java/util.rs @@ -1,11 +1,5 @@ use jni::{JNIEnv, sys::jlong}; -/// A simple utility method that converts a pointer back into a [Box] and then drops it. -pub(crate) fn dereference_and_drop(ptr: jlong) { - let client : Box = unsafe { Box::from_raw(ptr as *mut T) }; - std::mem::drop(client) -} - /// A trait meant for our [crate::Result] type to make converting it to Java easier. pub(crate) trait JExceptable { /// Unwraps it and throws an appropriate Java exception if it's an error. diff --git a/src/ffi/java/workspace.rs b/src/ffi/java/workspace.rs index 09522a9..f42c147 100644 --- a/src/ffi/java/workspace.rs +++ b/src/ffi/java/workspace.rs @@ -1,12 +1,49 @@ -use jni::{objects::{JClass, JString}, sys::jlong, JNIEnv}; -use crate::{Client, Workspace}; +use jni::{objects::{JClass, JString}, sys::{jlong, jstring}, JNIEnv}; +use crate::Workspace; use super::{util::JExceptable, RT}; /// Called by the Java GC to drop a [Workspace]. #[no_mangle] pub extern "system" fn Java_mp_code_Workspace_free(_env: JNIEnv, _class: JClass, input: jlong) { - super::util::dereference_and_drop::(input) + let _ = unsafe { Box::from_raw(input as *mut Workspace) }; +} + +/// Gets the workspace id. +#[no_mangle] +pub extern "system" fn Java_mp_code_Client_get_1workspace_1id<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + self_ptr: jlong +) -> jstring { + let workspace = unsafe { Box::leak(Box::from_raw(self_ptr as *mut Workspace)) }; + env.new_string(workspace.id()) + .expect("Failed to convert to Java String!") + .as_raw() +} + +/// Gets a cursor controller by name and returns a pointer to it. +#[no_mangle] +pub extern "system" fn Java_mp_code_Client_get_1cursor<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + self_ptr: jlong +) -> jlong { + let workspace = unsafe { Box::leak(Box::from_raw(self_ptr as *mut Workspace)) }; + Box::into_raw(Box::new(workspace.cursor())) as jlong +} + +/// Gets a buffer controller by name and returns a pointer to it. +#[no_mangle] +pub extern "system" fn Java_mp_code_Client_get_1buffer<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + self_ptr: jlong, + input: JString<'local> +) -> jlong { + let workspace = unsafe { Box::leak(Box::from_raw(self_ptr as *mut Workspace)) }; + let path = unsafe { env.get_string_unchecked(&input).expect("Couldn't get java string!") }; + Box::into_raw(Box::new(workspace.buffer_by_name(path.to_str().expect("Not UTF-8")))) as jlong } /// Creates a [Buffer] @@ -18,6 +55,6 @@ pub extern "system" fn Java_mp_code_Workspace_create_1buffer<'local>( input: JString<'local> ) { let ws: Box = unsafe { Box::from_raw(self_ptr as *mut Workspace) }; - let path: String = env.get_string(&input).expect("Couldn't get java string!").into(); - RT.block_on(ws.create(&path)).jexcept(&mut env); + let path = unsafe { env.get_string_unchecked(&input).expect("Couldn't get java string!") }; + RT.block_on(ws.create(path.to_str().expect("Not UTF-8"))).jexcept(&mut env); }