From 678f8bd9ea03e0dc084a5512fe43f06beb941222 Mon Sep 17 00:00:00 2001 From: alemi Date: Mon, 23 Sep 2024 18:12:13 +0200 Subject: [PATCH] chore: updated jni-toolbox usage --- Cargo.lock | 7 +++---- Cargo.toml | 2 +- src/ffi/java/buffer.rs | 28 ++++++++++++------------- src/ffi/java/client.rs | 28 ++++++++++++------------- src/ffi/java/cursor.rs | 20 +++++++++--------- src/ffi/java/mod.rs | 41 ++++++++++++++++-------------------- src/ffi/java/workspace.rs | 44 +++++++++++++++++++-------------------- 7 files changed, 82 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f0253e..e3b43c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -750,18 +750,17 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jni-toolbox" version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c14725e4fd3fe9ea885cea9df1ff1fa9f4d45a6f4253f6b90802f0941335f6" +source = "git+https://github.com/hexedtech/jni-toolbox?rev=10547d92b02b1af622706443cef835110efcdd0d#10547d92b02b1af622706443cef835110efcdd0d" dependencies = [ "jni", "jni-toolbox-macro", + "uuid", ] [[package]] name = "jni-toolbox-macro" version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9970cad895bb316f70956593710d675d27a480ddbb8099f7e313042463a16d9b" +source = "git+https://github.com/hexedtech/jni-toolbox?rev=10547d92b02b1af622706443cef835110efcdd0d#10547d92b02b1af622706443cef835110efcdd0d" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 72273f1..8841514 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ tracing-subscriber = { version = "0.3", optional = true } # glue (java) lazy_static = { version = "1.5", optional = true } jni = { version = "0.21", features = ["invocation"], optional = true } -jni-toolbox = { version = "0.1.3", optional = true } +jni-toolbox = { git = "https://github.com/hexedtech/jni-toolbox", rev = "10547d92b02b1af622706443cef835110efcdd0d", optional = true, features = ["uuid"] } # glue (lua) mlua-codemp-patch = { version = "0.10.0-beta.2", features = ["module", "send", "serialize"], optional = true } diff --git a/src/ffi/java/buffer.rs b/src/ffi/java/buffer.rs index c5847d4..c1bdd66 100644 --- a/src/ffi/java/buffer.rs +++ b/src/ffi/java/buffer.rs @@ -6,38 +6,38 @@ use crate::{api::{Controller, TextChange}, errors::ControllerError}; use super::null_check; /// Get the name of the buffer. -#[jni(package = "mp.code", class = "BufferController", ptr)] -fn get_name(controller: &mut crate::buffer::Controller) -> String { +#[jni(package = "mp.code", class = "BufferController")] +fn get_name(controller: crate::buffer::Controller) -> String { controller.path().to_string() //TODO: &str is built into the newer version } /// Get the contents of the buffers. -#[jni(package = "mp.code", class = "BufferController", ptr)] -fn get_content(controller: &mut crate::buffer::Controller) -> Result { +#[jni(package = "mp.code", class = "BufferController")] +fn get_content(controller: crate::buffer::Controller) -> Result { super::tokio().block_on(controller.content()) } /// Try to fetch a [TextChange], or return null if there's nothing. -#[jni(package = "mp.code", class = "BufferController", ptr)] -fn try_recv(controller: &mut crate::buffer::Controller) -> Result, ControllerError> { +#[jni(package = "mp.code", class = "BufferController")] +fn try_recv(controller: crate::buffer::Controller) -> Result, ControllerError> { super::tokio().block_on(controller.try_recv()) } /// Block until it receives a [TextChange]. -#[jni(package = "mp.code", class = "BufferController", ptr)] -fn recv(controller: &mut crate::buffer::Controller) -> Result { +#[jni(package = "mp.code", class = "BufferController")] +fn recv(controller: crate::buffer::Controller) -> Result { super::tokio().block_on(controller.recv()) } /// Send a [TextChange] to the server. #[jni(package = "mp.code", class = "BufferController")] -fn send(controller: &mut crate::buffer::Controller, change: TextChange) -> Result<(), ControllerError> { +fn send(controller: crate::buffer::Controller, change: TextChange) -> Result<(), ControllerError> { super::tokio().block_on(controller.send(change)) } /// Register a callback for buffer changes. #[jni(package = "mp.code", class = "BufferController")] -fn callback<'local>(env: &mut JNIEnv<'local>, controller: &mut crate::buffer::Controller, cb: JObject<'local>) { +fn callback<'local>(env: &mut JNIEnv<'local>, controller: crate::buffer::Controller, cb: JObject<'local>) { null_check!(env, cb, {}); let Ok(cb_ref) = env.new_global_ref(cb) else { env.throw_new("mp/code/exceptions/JNIException", "Failed to pin callback reference!") @@ -51,7 +51,7 @@ fn callback<'local>(env: &mut JNIEnv<'local>, controller: &mut crate::buffer::Co .expect("failed attaching to main JVM thread"); if let Err(e) = env.with_local_frame(5, |env| { use jni_toolbox::IntoJavaObject; - let jcontroller = controller.into_java(env)?; + let jcontroller = controller.into_java_object(env)?; if let Err(e) = env.call_method( &cb_ref, "accept", @@ -70,19 +70,19 @@ fn callback<'local>(env: &mut JNIEnv<'local>, controller: &mut crate::buffer::Co /// Clear the callback for buffer changes. #[jni(package = "mp.code", class = "BufferController")] -fn clear_callback(controller: &mut crate::buffer::Controller) { +fn clear_callback(controller: crate::buffer::Controller) { controller.clear_callback() } /// Block until there is a new value available. #[jni(package = "mp.code", class = "BufferController")] -fn poll(controller: &mut crate::buffer::Controller) -> Result<(), ControllerError> { +fn poll(controller: crate::buffer::Controller) -> Result<(), ControllerError> { super::tokio().block_on(controller.poll()) } /// Stop the controller. #[jni(package = "mp.code", class = "BufferController")] -fn stop(controller: &mut crate::buffer::Controller) -> bool { +fn stop(controller: crate::buffer::Controller) -> bool { controller.stop() } diff --git a/src/ffi/java/client.rs b/src/ffi/java/client.rs index 2f3d51b..624ceba 100644 --- a/src/ffi/java/client.rs +++ b/src/ffi/java/client.rs @@ -9,61 +9,61 @@ fn connect(config: Config) -> Result { /// Gets the current [crate::api::User]. #[jni(package = "mp.code", class = "Client", ptr)] -fn get_user(client: &mut Client) -> crate::api::User { +fn get_user(client: Client) -> crate::api::User { client.user().clone() } /// Join a [Workspace] and return a pointer to it. -#[jni(package = "mp.code", class = "Client", ptr)] -fn join_workspace(client: &mut Client, workspace: String) -> Result { +#[jni(package = "mp.code", class = "Client")] +fn join_workspace(client: Client, workspace: String) -> Result { super::tokio().block_on(client.join_workspace(workspace)) } /// Create a workspace on server, if allowed to. #[jni(package = "mp.code", class = "Client")] -fn create_workspace(client: &mut Client, workspace: String) -> Result<(), RemoteError> { +fn create_workspace(client: Client, workspace: String) -> Result<(), RemoteError> { super::tokio().block_on(client.create_workspace(workspace)) } /// Delete a workspace on server, if allowed to. #[jni(package = "mp.code", class = "Client")] -fn delete_workspace(client: &mut Client, workspace: String) -> Result<(), RemoteError> { +fn delete_workspace(client: Client, workspace: String) -> Result<(), RemoteError> { super::tokio().block_on(client.delete_workspace(workspace)) } /// Invite another user to an owned workspace. #[jni(package = "mp.code", class = "Client")] -fn invite_to_workspace(client: &mut Client, workspace: String, user: String) -> Result<(), RemoteError> { +fn invite_to_workspace(client: Client, workspace: String, user: String) -> Result<(), RemoteError> { super::tokio().block_on(client.invite_to_workspace(workspace, user)) } /// List available workspaces. -#[jni(package = "mp.code", class = "Client", ptr)] -fn list_workspaces(client: &mut Client, owned: bool, invited: bool) -> Result, RemoteError> { +#[jni(package = "mp.code", class = "Client")] +fn list_workspaces(client: Client, owned: bool, invited: bool) -> Result, RemoteError> { super::tokio().block_on(client.list_workspaces(owned, invited)) } /// List available workspaces. -#[jni(package = "mp.code", class = "Client", ptr)] -fn active_workspaces(client: &mut Client) -> Vec { +#[jni(package = "mp.code", class = "Client")] +fn active_workspaces(client: Client) -> Vec { client.active_workspaces() } /// Leave a [Workspace] and return whether or not the client was in such workspace. #[jni(package = "mp.code", class = "Client")] -fn leave_workspace(client: &mut Client, workspace: String) -> bool { +fn leave_workspace(client: Client, workspace: String) -> bool { client.leave_workspace(&workspace) } /// Get a [Workspace] by name and returns a pointer to it. -#[jni(package = "mp.code", class = "Client", ptr)] -fn get_workspace(client: &mut Client, workspace: String) -> Option { +#[jni(package = "mp.code", class = "Client")] +fn get_workspace(client: Client, workspace: String) -> Option { client.get_workspace(&workspace) } /// Refresh the client's session token. #[jni(package = "mp.code", class = "Client")] -fn refresh(client: &mut Client) -> Result<(), RemoteError> { +fn refresh(client: Client) -> Result<(), RemoteError> { super::tokio().block_on(client.refresh()) } diff --git a/src/ffi/java/cursor.rs b/src/ffi/java/cursor.rs index 509f868..c68115c 100644 --- a/src/ffi/java/cursor.rs +++ b/src/ffi/java/cursor.rs @@ -5,26 +5,26 @@ use crate::{api::{Controller, Cursor}, errors::ControllerError}; use super::null_check; /// Try to fetch a [Cursor], or returns null if there's nothing. -#[jni(package = "mp.code", class = "CursorController", ptr)] -fn try_recv(controller: &mut crate::cursor::Controller) -> Result, ControllerError> { +#[jni(package = "mp.code", class = "CursorController")] +fn try_recv(controller: crate::cursor::Controller) -> Result, ControllerError> { super::tokio().block_on(controller.try_recv()) } /// Block until it receives a [Cursor]. -#[jni(package = "mp.code", class = "CursorController", ptr)] -fn recv(controller: &mut crate::cursor::Controller) -> Result { +#[jni(package = "mp.code", class = "CursorController")] +fn recv(controller: crate::cursor::Controller) -> Result { super::tokio().block_on(controller.recv()) } /// Receive from Java, converts and sends a [Cursor]. #[jni(package = "mp.code", class = "CursorController")] -fn send(controller: &mut crate::cursor::Controller, cursor: Cursor) -> Result<(), ControllerError> { +fn send(controller: crate::cursor::Controller, cursor: Cursor) -> Result<(), ControllerError> { super::tokio().block_on(controller.send(cursor)) } /// Register a callback for cursor changes. #[jni(package = "mp.code", class = "CursorController")] -fn callback<'local>(env: &mut JNIEnv<'local>, controller: &mut crate::cursor::Controller, cb: JObject<'local>) { +fn callback<'local>(env: &mut JNIEnv<'local>, controller: crate::cursor::Controller, cb: JObject<'local>) { null_check!(env, cb, {}); let Ok(cb_ref) = env.new_global_ref(cb) else { env.throw_new("mp/code/exceptions/JNIException", "Failed to pin callback reference!") @@ -38,7 +38,7 @@ fn callback<'local>(env: &mut JNIEnv<'local>, controller: &mut crate::cursor::Co .expect("failed attaching to main JVM thread"); if let Err(e) = env.with_local_frame(5, |env| { use jni_toolbox::IntoJavaObject; - let jcontroller = controller.into_java(env)?; + let jcontroller = controller.into_java_object(env)?; if let Err(e) = env.call_method( &cb_ref, "accept", @@ -57,19 +57,19 @@ fn callback<'local>(env: &mut JNIEnv<'local>, controller: &mut crate::cursor::Co /// Clear the callback for cursor changes. #[jni(package = "mp.code", class = "CursorController")] -fn clear_callback(controller: &mut crate::cursor::Controller) { +fn clear_callback(controller: crate::cursor::Controller) { controller.clear_callback() } /// Block until there is a new value available. #[jni(package = "mp.code", class = "CursorController")] -fn poll(controller: &mut crate::cursor::Controller) -> Result<(), ControllerError> { +fn poll(controller: crate::cursor::Controller) -> Result<(), ControllerError> { super::tokio().block_on(controller.poll()) } /// Stop the controller. #[jni(package = "mp.code", class = "CursorController")] -fn stop(controller: &mut crate::cursor::Controller) -> bool { +fn stop(controller: crate::cursor::Controller) -> bool { controller.stop() } diff --git a/src/ffi/java/mod.rs b/src/ffi/java/mod.rs index d20f422..a309599 100644 --- a/src/ffi/java/mod.rs +++ b/src/ffi/java/mod.rs @@ -105,9 +105,8 @@ impl jni_toolbox::JniToolboxError for crate::errors::ControllerError { macro_rules! into_java_ptr_class { ($type: ty, $jclass: literal) => { impl<'j> jni_toolbox::IntoJavaObject<'j> for $type { - type T = jni::objects::JObject<'j>; const CLASS: &'static str = $jclass; - fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result { + fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result, jni::errors::Error> { let class = env.find_class(Self::CLASS)?; env.new_object( class, @@ -125,10 +124,9 @@ into_java_ptr_class!(crate::cursor::Controller, "mp/code/CursorController"); into_java_ptr_class!(crate::buffer::Controller, "mp/code/BufferController"); impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::User { - type T = jni::objects::JObject<'j>; const CLASS: &'static str = "mp/code/data/User"; - fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result { - let id_field = self.id.into_java(env)?; + fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result, jni::errors::Error> { + let id_field = self.id.into_java_object(env)?; let name_field = env.new_string(self.name)?; let class = env.find_class(Self::CLASS)?; env.new_object( @@ -143,9 +141,8 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::User { } impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::Event { - type T = jni::objects::JObject<'j>; const CLASS: &'static str = "mp/code/Workspace$Event"; - fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result { + fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result, jni::errors::Error> { let (ordinal, arg) = match self { crate::api::Event::UserJoin(arg) => (0, env.new_string(arg)?), crate::api::Event::UserLeave(arg) => (1, env.new_string(arg)?), @@ -174,9 +171,8 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::Event { } impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::workspace::DetachResult { - type T = jni::objects::JObject<'j>; const CLASS: &'static str = "mp/code/data/DetachResult"; - fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result { + fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result, jni::errors::Error> { let ordinal = match self { crate::workspace::DetachResult::NotAttached => 0, crate::workspace::DetachResult::Detaching => 1, @@ -195,9 +191,8 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::workspace::DetachResult { } impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::TextChange { - type T = jni::objects::JObject<'j>; const CLASS: &'static str = "mp/code/data/TextChange"; - fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result { + fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result, jni::errors::Error> { let content = env.new_string(self.content)?; let hash_class = env.find_class("java/util/OptionalLong")?; @@ -222,9 +217,8 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::TextChange { } impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::Cursor { - type T = jni::objects::JObject<'j>; const CLASS: &'static str = "mp/code/data/Cursor"; - fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result { + fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result, jni::errors::Error> { let class = env.find_class("mp/code/data/Cursor")?; let buffer = env.new_string(&self.buffer)?; let user = if let Some(user) = self.user { @@ -250,10 +244,11 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::Cursor { macro_rules! from_java_ptr { ($type: ty) => { - impl<'j> jni_toolbox::FromJava<'j> for &mut $type { - type T = jni::sys::jobject; - fn from_java(_env: &mut jni::JNIEnv<'j>, value: Self::T) -> Result { - Ok(unsafe { Box::leak(Box::from_raw(value as *mut $type)) }) + impl<'j> jni_toolbox::FromJava<'j> for $type { + type From = jni::sys::jobject; + fn from_java(_env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result { + let original_ptr = unsafe { Box::leak(Box::from_raw(value as *mut $type)) }; + Ok(original_ptr.clone()) } } }; @@ -265,8 +260,8 @@ from_java_ptr!(crate::cursor::Controller); from_java_ptr!(crate::buffer::Controller); impl<'j> jni_toolbox::FromJava<'j> for crate::api::Config { - type T = jni::objects::JObject<'j>; - fn from_java(env: &mut jni::JNIEnv<'j>, config: Self::T) -> Result { + type From = jni::objects::JObject<'j>; + fn from_java(env: &mut jni::JNIEnv<'j>, config: Self::From) -> Result { let username = { let jfield = env.get_field(&config, "username", "Ljava/lang/String;")?.l()?; if jfield.is_null() { @@ -324,8 +319,8 @@ impl<'j> jni_toolbox::FromJava<'j> for crate::api::Config { } impl<'j> jni_toolbox::FromJava<'j> for crate::api::Cursor { - type T = jni::objects::JObject<'j>; - fn from_java(env: &mut jni::JNIEnv<'j>, cursor: Self::T) -> Result { + type From = jni::objects::JObject<'j>; + fn from_java(env: &mut jni::JNIEnv<'j>, cursor: Self::From) -> Result { let start_row = env.get_field(&cursor, "startRow", "I")?.i()?; let start_col = env.get_field(&cursor, "startCol", "I")?.i()?; let end_row = env.get_field(&cursor, "endRow", "I")?.i()?; @@ -353,8 +348,8 @@ impl<'j> jni_toolbox::FromJava<'j> for crate::api::Cursor { } impl<'j> jni_toolbox::FromJava<'j> for crate::api::TextChange { - type T = jni::objects::JObject<'j>; - fn from_java(env: &mut jni::JNIEnv<'j>, change: Self::T) -> Result { + type From = jni::objects::JObject<'j>; + fn from_java(env: &mut jni::JNIEnv<'j>, change: Self::From) -> Result { let start = env.get_field(&change, "start", "J")?.j()?.clamp(0, u32::MAX.into()) as u32; let end = env.get_field(&change, "end", "J")?.j()?.clamp(0, u32::MAX.into()) as u32; diff --git a/src/ffi/java/workspace.rs b/src/ffi/java/workspace.rs index a03508a..c851fe7 100644 --- a/src/ffi/java/workspace.rs +++ b/src/ffi/java/workspace.rs @@ -2,80 +2,80 @@ use jni_toolbox::jni; use crate::{errors::{ConnectionError, ControllerError, RemoteError}, Workspace}; /// Get the workspace id. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn get_workspace_id(workspace: &mut Workspace) -> String { +#[jni(package = "mp.code", class = "Workspace")] +fn get_workspace_id(workspace: Workspace) -> String { workspace.id() } /// Get a cursor controller by name and returns a pointer to it. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn get_cursor(workspace: &mut Workspace) -> crate::cursor::Controller { +#[jni(package = "mp.code", class = "Workspace")] +fn get_cursor(workspace: Workspace) -> crate::cursor::Controller { workspace.cursor() } /// Get a buffer controller by name and returns a pointer to it. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn get_buffer(workspace: &mut Workspace, path: String) -> Option { +#[jni(package = "mp.code", class = "Workspace")] +fn get_buffer(workspace: Workspace, path: String) -> Option { workspace.buffer_by_name(&path) } /// Get the filetree. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn get_file_tree(workspace: &mut Workspace, filter: Option, strict: bool) -> Vec { +#[jni(package = "mp.code", class = "Workspace")] +fn get_file_tree(workspace: Workspace, filter: Option, strict: bool) -> Vec { workspace.filetree(filter.as_deref(), strict) } /// Gets a list of the active buffers. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn active_buffers(workspace: &mut Workspace) -> Vec { +#[jni(package = "mp.code", class = "Workspace")] +fn active_buffers(workspace: Workspace) -> Vec { workspace.buffer_list() } /// Create a new buffer. #[jni(package = "mp.code", class = "Workspace")] -fn create_buffer(workspace: &mut Workspace, path: String) -> Result<(), RemoteError> { +fn create_buffer(workspace: Workspace, path: String) -> Result<(), RemoteError> { super::tokio().block_on(workspace.create(&path)) } /// Attach to a buffer and return a pointer to its [crate::buffer::Controller]. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn attach_to_buffer(workspace: &mut Workspace, path: String) -> Result { +#[jni(package = "mp.code", class = "Workspace")] +fn attach_to_buffer(workspace: Workspace, path: String) -> Result { super::tokio().block_on(workspace.attach(&path)) } /// Detach from a buffer. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn detach_from_buffer(workspace: &mut Workspace, path: String) -> crate::workspace::DetachResult { +#[jni(package = "mp.code", class = "Workspace")] +fn detach_from_buffer(workspace: Workspace, path: String) -> crate::workspace::DetachResult { workspace.detach(&path) } /// Update the local buffer list. #[jni(package = "mp.code", class = "Workspace")] -fn fetch_buffers(workspace: &mut Workspace) -> Result<(), RemoteError> { +fn fetch_buffers(workspace: Workspace) -> Result<(), RemoteError> { super::tokio().block_on(workspace.fetch_buffers()) } /// Update the local user list. #[jni(package = "mp.code", class = "Workspace")] -fn fetch_users(workspace: &mut Workspace) -> Result<(), RemoteError> { +fn fetch_users(workspace: Workspace) -> Result<(), RemoteError> { super::tokio().block_on(workspace.fetch_users()) } /// List users attached to a buffer. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn list_buffer_users(workspace: &mut Workspace, path: String) -> Result, RemoteError> { +#[jni(package = "mp.code", class = "Workspace")] +fn list_buffer_users(workspace: Workspace, path: String) -> Result, RemoteError> { super::tokio().block_on(workspace.list_buffer_users(&path)) } /// Delete a buffer. #[jni(package = "mp.code", class = "Workspace")] -fn delete_buffer(workspace: &mut Workspace, path: String) -> Result<(), RemoteError> { +fn delete_buffer(workspace: Workspace, path: String) -> Result<(), RemoteError> { super::tokio().block_on(workspace.delete(&path)) } /// Receive a workspace event if present. -#[jni(package = "mp.code", class = "Workspace", ptr)] -fn event(workspace: &mut Workspace) -> Result { +#[jni(package = "mp.code", class = "Workspace")] +fn event(workspace: Workspace) -> Result { super::tokio().block_on(workspace.event()) }