1 // A JNI call that is expected to return a non-null pointer when successful.
2 // If a null pointer is returned, it is converted to an Err.
3 // Returns Err if there is a pending exception after the call.
4 macro_rules! jni_non_null_call {
5     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
6         let res = jni_non_void_call!($jnienv, $name $(, $args)*);
7         non_null!(res, concat!(stringify!($name), " result"))
8     })
9 }
10 
11 // A non-void JNI call. May return anything — primitives, references, error codes.
12 // Returns Err if there is a pending exception after the call.
13 macro_rules! jni_non_void_call {
14     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
15         log::trace!("calling checked jni method: {}", stringify!($name));
16 
17         #[allow(unused_unsafe)]
18         let res = unsafe {
19             jni_method!($jnienv, $name)($jnienv, $($args),*)
20         };
21 
22         check_exception!($jnienv);
23         res
24     })
25 }
26 
27 macro_rules! non_null {
28     ( $obj:expr, $ctx:expr ) => {
29         if $obj.is_null() {
30             return Err($crate::errors::Error::NullPtr($ctx));
31         } else {
32             $obj
33         }
34     };
35 }
36 
37 // A void JNI call.
38 // Returns Err if there is a pending exception after the call.
39 macro_rules! jni_void_call {
40     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
41         log::trace!("calling checked jni method: {}", stringify!($name));
42 
43         #[allow(unused_unsafe)]
44         unsafe {
45             jni_method!($jnienv, $name)($jnienv, $($args),*)
46         };
47 
48         check_exception!($jnienv);
49     })
50 }
51 
52 // A JNI call that does not check for exceptions or verify
53 // error codes (if any).
54 macro_rules! jni_unchecked {
55     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
56         log::trace!("calling unchecked jni method: {}", stringify!($name));
57 
58         #[allow(unused_unsafe)]
59         unsafe {
60             jni_method!($jnienv, $name)($jnienv, $($args),*)
61         }
62     })
63 }
64 
65 macro_rules! jni_method {
66     ( $jnienv:expr, $name:tt ) => {{
67         log::trace!("looking up jni method {}", stringify!($name));
68         let env = $jnienv;
69         match deref!(deref!(env, "JNIEnv"), "*JNIEnv").$name {
70             Some(method) => {
71                 log::trace!("found jni method");
72                 method
73             }
74             None => {
75                 log::trace!("jnienv method not defined, returning error");
76                 return Err($crate::errors::Error::JNIEnvMethodNotFound(stringify!(
77                     $name
78                 )));
79             }
80         }
81     }};
82 }
83 
84 macro_rules! check_exception {
85     ( $jnienv:expr ) => {
86         log::trace!("checking for exception");
87         let check = { jni_unchecked!($jnienv, ExceptionCheck) } == $crate::sys::JNI_TRUE;
88         if check {
89             log::trace!("exception found, returning error");
90             return Err($crate::errors::Error::JavaException);
91         }
92         log::trace!("no exception found");
93     };
94 }
95 
96 macro_rules! catch {
97     ( move $b:block ) => {
98         (move || $b)()
99     };
100     ( $b:block ) => {
101         (|| $b)()
102     };
103 }
104 
105 macro_rules! java_vm_unchecked {
106     ( $java_vm:expr, $name:tt $(, $args:expr )* ) => ({
107         log::trace!("calling unchecked JavaVM method: {}", stringify!($name));
108         java_vm_method!($java_vm, $name)($java_vm, $($args),*)
109     })
110 }
111 
112 macro_rules! java_vm_method {
113     ( $jnienv:expr, $name:tt ) => {{
114         log::trace!("looking up JavaVM method {}", stringify!($name));
115         let env = $jnienv;
116         match deref!(deref!(env, "JavaVM"), "*JavaVM").$name {
117             Some(meth) => {
118                 log::trace!("found JavaVM method");
119                 meth
120             }
121             None => {
122                 log::trace!("JavaVM method not defined, returning error");
123                 return Err($crate::errors::Error::JavaVMMethodNotFound(stringify!(
124                     $name
125                 )));
126             }
127         }
128     }};
129 }
130 
131 macro_rules! deref {
132     ( $obj:expr, $ctx:expr ) => {
133         if $obj.is_null() {
134             return Err($crate::errors::Error::NullDeref($ctx));
135         } else {
136             #[allow(unused_unsafe)]
137             unsafe {
138                 *$obj
139             }
140         }
141     };
142 }
143