oo_bindgen/backend/java/jni/
exceptions.rs

1use crate::backend::*;
2use crate::model::Library;
3
4use crate::backend::java::jni::JniBindgenConfig;
5
6pub(crate) fn generate_exceptions_cache(
7    f: &mut dyn Printer,
8    lib: &Library,
9    config: &JniBindgenConfig,
10) -> FormattingResult<()> {
11    let lib_path = config.java_signature_path(&lib.settings.name);
12
13    f.writeln("/// cached information about an exception")?;
14    f.writeln("pub struct ExceptionInfo {")?;
15    indented(f, |f| {
16        f.writeln("class: jni::objects::GlobalRef,")?;
17        f.writeln("constructor: jni::objects::JMethodID<'static>,")
18    })?;
19    f.writeln("}")?;
20
21    f.newline()?;
22
23    f.writeln("impl ExceptionInfo {")?;
24    indented(f, |f| {
25        f.writeln("pub(crate) fn throw(&self, env: &jni::JNIEnv, error: jni::sys::jobject) {")?;
26        indented(f, |f| {
27            f.writeln("let obj = env.new_object_unchecked(&self.class, self.constructor, &[jni::objects::JValue::Object(error.into())]).unwrap();")?;
28            f.writeln("env.throw(jni::objects::JThrowable::from(obj)).unwrap()")
29        })?;
30        f.writeln("}")?;
31        for error in lib.error_types() {
32            let camel_name = error.exception_name.camel_case();
33            let enum_name = error.inner.name.camel_case();
34            f.newline()?;
35            f.writeln(&format!(
36                "fn init_{}(env: &jni::JNIEnv) -> Self {{",
37                error.exception_name
38            ))?;
39            indented(f, |f| {
40                f.writeln(&format!("let class = env.find_class(\"L{lib_path}/{camel_name};\").expect(\"Unable to find exception {camel_name}\");"))?;
41                f.writeln(&format!("let constructor = env.get_method_id(class, \"<init>\", \"(L{lib_path}/{enum_name};)V\").map(|mid| mid.into_inner().into()).expect(\"Unable to find constructor of {camel_name}\");"))?;
42                f.writeln("Self { class : env.new_global_ref(class).unwrap(), constructor }")
43            })?;
44            f.writeln("}")?;
45        }
46        Ok(())
47    })?;
48    f.writeln("}")?;
49
50    f.newline()?;
51
52    // Top-level exceptions struct
53    f.writeln("pub struct Exceptions")?;
54    blocked(f, |f| {
55        for error in lib.error_types() {
56            f.writeln(&format!(
57                "pub(crate) {}: ExceptionInfo,",
58                error.exception_name
59            ))?;
60        }
61        Ok(())
62    })?;
63
64    f.newline()?;
65
66    f.writeln("impl Exceptions {")?;
67    indented(f, |f| {
68        f.writeln("pub fn init(env: &jni::JNIEnv) -> Self {")?;
69        indented(f, |f| {
70            f.writeln("Self {")?;
71            indented(f, |f| {
72                for error in lib.error_types() {
73                    f.writeln(&format!(
74                        "{}: ExceptionInfo::init_{}(env),",
75                        error.exception_name, error.exception_name
76                    ))?;
77                }
78                Ok(())
79            })?;
80            f.writeln("}")
81        })?;
82        f.writeln("}")
83    })?;
84    f.writeln("}")
85}