From 6c892e7e3abe758cb44208d8976130c4ff5f17d5 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Mon, 28 Aug 2023 16:12:42 +0200 Subject: [PATCH] feat: implemented exception handling (this time for real) --- .gitignore | 4 +-- Cargo.toml | 13 +++++--- build.rs | 69 ++++++++++++++++++++++------------------- src/main/rust/error.rs | 27 ++++++---------- src/main/rust/lib.rs | 70 ++++++++++++++++++++---------------------- 5 files changed, 91 insertions(+), 92 deletions(-) diff --git a/.gitignore b/.gitignore index 165146b..6a739b6 100644 --- a/.gitignore +++ b/.gitignore @@ -44,8 +44,8 @@ bin/ ### Rust ### Cargo.lock -.cargo/* -target/* +.cargo +target # Do not inclue generated code src/main/java/com/codemp/intellij/jni diff --git a/Cargo.toml b/Cargo.toml index 9c4fa7d..fb0ec71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,13 +4,18 @@ version = "0.1.0" edition = "2021" [dependencies] -codemp = { git = "ssh://git@github.com-irl/codewithotherpeopleandchangenamelater/codemp.git", tag = "v0.4.2" } -jni = "0.21.1" -rifgen = "0.1.61" +codemp = { git = "ssh://git@github.com-irl/codewithotherpeopleandchangenamelater/codemp.git", tag = "v0.4.4", features = ["global"] } +jni = { version = "0.21.1", features = ["invocation"] } +rifgen = { path = "/home/zaaarf/dev/irl/rust/jni/rifgen" } +#rifgen = { git = "https://github.com/Kofituo/rifgen.git", rev = "d27d9785b2febcf5527f1deb6a846be5d583f7d7"} +#rifgen = "0.1.7" [build-dependencies] flapigen = "0.6.0" -rifgen = "0.1.61" +rifgen = { path = "/home/zaaarf/dev/irl/rust/jni/rifgen" } +#rifgen = "0.1.7" +#rifgen = { git = "https://github.com/Kofituo/rifgen.git", rev = "d27d9785b2febcf5527f1deb6a846be5d583f7d7"} + [lib] crate_type = ["cdylib"] diff --git a/build.rs b/build.rs index 936fbfd..2c6bb48 100644 --- a/build.rs +++ b/build.rs @@ -1,43 +1,48 @@ use flapigen::{JavaConfig, LanguageConfig}; use std::{env, path::Path}; -use rifgen::{Generator, TypeCases, Language}; +use rifgen::{Generator as RifgenGenerator, TypeCases, Language}; +use flapigen::Generator as FlapigenGenerator; fn main() { - let out_dir_var = env::var("OUT_DIR") - .expect("no OUT_DIR, but cargo should provide it"); - let out_dir = Path::new(&out_dir_var); - let source_folder = "src/main/rust/"; + let out_dir_var = env::var("OUT_DIR") + .expect("no OUT_DIR, but cargo should provide it"); + let out_dir = Path::new(&out_dir_var); - let glue_file = out_dir.join("glue.in"); - Generator::new(TypeCases::CamelCase,Language::Java,source_folder) - .generate_interface(&glue_file); + let mut source_folders = Vec::new(); + source_folders.push(Path::new("src/main/rust/")); - let jni_path = Path::new("src") - .join("main") - .join("java") - .join("com") - .join("codemp") - .join("intellij") - .join("jni"); + let glue_file = out_dir.join("glue.in"); + RifgenGenerator::new(TypeCases::CamelCase, + Language::Java, + source_folders) + .generate_interface(&glue_file); - //create folder if it doesn't exist - std::fs::create_dir_all(&jni_path) - .expect("An error occurred while creating the JNI folder!"); + let jni_path = Path::new("src") + .join("main") + .join("java") + .join("com") + .join("codemp") + .join("intellij") + .join("jni"); - let java_gen = flapigen::Generator::new(LanguageConfig::JavaConfig( - JavaConfig::new( - jni_path, - "com.codemp.intellij.jni".into() - ))).rustfmt_bindings(true); + //create folder if it doesn't exist + std::fs::create_dir_all(&jni_path) + .expect("An error occurred while creating the JNI folder!"); - java_gen.expand( - "codemp-intellij", - &glue_file, - out_dir.join("glue.rs"), - ); + let java_gen = FlapigenGenerator::new(LanguageConfig::JavaConfig( + JavaConfig::new( + jni_path, + "com.codemp.intellij.jni".into() + ))).rustfmt_bindings(true); - println!( - "cargo:rerun-if-changed={}", - Path::new("src/main").join(&glue_file).display() - ); + java_gen.expand( + "codemp-intellij", + &glue_file, + out_dir.join("glue.rs"), + ); + + println!( + "cargo:rerun-if-changed={}", + Path::new("src/main").join(&glue_file).display() + ); } \ No newline at end of file diff --git a/src/main/rust/error.rs b/src/main/rust/error.rs index c62e922..dd32f0d 100644 --- a/src/main/rust/error.rs +++ b/src/main/rust/error.rs @@ -1,6 +1,4 @@ use codemp::prelude::CodempError; -use jni::JNIEnv; -use crate::JAVA_FOLDER; pub struct ErrorWrapper(CodempError); @@ -11,24 +9,19 @@ impl From:: for ErrorWrapper { } impl ErrorWrapper { - pub fn throw(&self, mut env: JNIEnv) { - let exception_package: String = format!("{}/exceptions", JAVA_FOLDER); - let res = match &self.0 { - CodempError::Transport { status, message } => env.throw_new(format!("{}/TransportException", exception_package), format!("Error {}: {}", status, message)), - CodempError::InvalidState { msg } => env.throw_new(format!("{}/InvalidStateException", exception_package), msg), - CodempError::Filler { message } => env.throw_new(format!("{}/CodeMPException", exception_package), message), + pub fn get_error_message(&self) -> String { + match &self.0 { + CodempError::Transport { status, message } => + format!("Error {}: {}", status, message), + CodempError::InvalidState { msg } => msg.to_string(), + CodempError::Filler { message } => message.to_string(), CodempError::Channel { send } => { - let class_name:String = if *send { - format!("{}/ChannelException/Send", exception_package) + if *send { + "Error while sending message on channel: the channel was closed!".to_string() } else { - format!("{}/ChannelException/Read", exception_package) - }; - env.throw_new(class_name, "The requested channel was closed!") + "Error while reading message from channel: the channel was closed!".to_string() + } } - }; - - if let Err(e) = res { - panic!("An error occurred while converting a Rust error to a Java Exception: {}", e); } } } \ No newline at end of file diff --git a/src/main/rust/lib.rs b/src/main/rust/lib.rs index 0865ef9..29b76d7 100644 --- a/src/main/rust/lib.rs +++ b/src/main/rust/lib.rs @@ -1,88 +1,84 @@ mod error; -use std::ffi::c_char; use std::sync::Arc; use codemp::prelude::*; use rifgen::rifgen_attr::generate_interface; use crate::error::ErrorWrapper; -pub const JAVA_PACKAGE: &str = "com.codemp.intellij"; -pub const JAVA_FOLDER: &str = "com/codemp/intellij"; - // #[generate_interface_doc] //TODO struct CodeMPHandler {} impl CodeMPHandler { #[generate_interface(constructor)] - fn new() -> CodeMPHandler { + async fn new() -> CodeMPHandler { CodeMPHandler {} } #[generate_interface] - async fn connect(addr: String) { - CODEMP_INSTANCE.connect(&addr).await; - /*match CODEMP_INSTANCE.connect(&addr) { - Ok(()) => (), - Err(err) => ErrorWrapper(err) //.throw(env) - }*/ + async fn connect(addr: String) -> Result<(), String> { + convert(CODEMP_INSTANCE.connect(&addr).await) } #[generate_interface] - async fn join(session: String) -> CursorHandler { - let controller = CODEMP_INSTANCE.join(&session).await.unwrap(); - CursorHandler { cursor: Some(controller) } //TODO error handling - /*match CODEMP_INSTANCE.join(&session) { - Ok(cursor) => CursorHandler { cursor }, - //Err(err) => ErrorWrapper(err) - }*/ + async fn join(session: String) -> Result { + convert_cursor(CODEMP_INSTANCE.join(&session).await) } #[generate_interface] - async fn create(path: String) { - CODEMP_INSTANCE.create(&path, None).await; + async fn create(path: String) -> Result<(), String> { + convert(CODEMP_INSTANCE.create(&path, None).await) } #[generate_interface] - async fn create_with_content(path: String, content: String) { - CODEMP_INSTANCE.create(&path, Some(&content)).await; + async fn create_with_content(path: String, content: String) -> Result<(), String> { + convert(CODEMP_INSTANCE.create(&path, Some(&content)).await) } #[generate_interface] - async fn attach(path: String) -> BufferHandler { - let controller = CODEMP_INSTANCE.attach(&path).await.unwrap(); - BufferHandler { buffer: Some(controller) } + async fn attach(path: String) -> Result { + convert_buffer(CODEMP_INSTANCE.attach(&path).await) } #[generate_interface] - async fn get_cursor() -> CursorHandler { - let controller = CODEMP_INSTANCE.get_cursor().await.unwrap(); - CursorHandler { cursor: Some(controller) } + async fn get_cursor() -> Result { + convert_cursor(CODEMP_INSTANCE.get_cursor().await) } #[generate_interface] - async fn get_buffer(path: String) -> BufferHandler { - let controller = CODEMP_INSTANCE.get_buffer(&path).await.unwrap(); - BufferHandler { buffer: Some(controller) } + async fn get_buffer(path: String) -> Result { + convert_buffer(CODEMP_INSTANCE.get_buffer(&path).await) } #[generate_interface] - async fn leave_workspace() { - CODEMP_INSTANCE.leave_workspace().await.unwrap() + async fn leave_workspace() -> Result<(), String> { + convert(CODEMP_INSTANCE.leave_workspace().await) } #[generate_interface] - async fn disconnect_buffer(path: String) -> bool { - CODEMP_INSTANCE.disconnect_buffer(&path).await.unwrap() + async fn disconnect_buffer(path: String) -> Result { + convert(CODEMP_INSTANCE.disconnect_buffer(&path).await) } } +fn convert_buffer(result: Result, CodempError>) -> Result { + convert(result).map(|val| BufferHandler { buffer: Some(val) }) +} + +fn convert_cursor(result: Result, CodempError>) -> Result { + convert(result).map(|val| CursorHandler { cursor: Some(val) }) +} + +fn convert(result: Result) -> Result { + result.map_err(|err| ErrorWrapper::from(err).get_error_message()) +} + struct CursorHandler { cursor: Option> } impl CursorHandler { #[generate_interface(constructor)] - fn new() -> CursorHandler { //TODO this sucks but whatever + async fn new() -> CursorHandler { //TODO: this sucks but whatever CursorHandler { cursor: None } } } @@ -94,7 +90,7 @@ struct BufferHandler { impl BufferHandler { #[generate_interface(constructor)] - fn new() -> BufferHandler { //TODO this sucks but whatever + async fn new() -> BufferHandler { //TODO: this sucks but whatever BufferHandler { buffer: None } } } \ No newline at end of file