1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//! Common glue code between Rust and JNI, used in autogenerated `java-spaghetti` glue code.
//!
//! See also the [Android JNI tips](https://developer.android.com/training/articles/perf-jni) documentation as well as the
//! [Java Native Interface Specification](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html).

use std::fmt;
use std::ptr::null_mut;

/// public jni-sys reexport.
pub use ::jni_sys as sys;
use sys::{jobject, jvalue};

mod refs {
    mod arg;
    mod global;
    mod local;
    mod ref_;
    mod return_;

    pub use arg::*;
    pub use global::*;
    pub use local::*;
    pub use ref_::*;
    pub use return_::*;
}

mod array;
mod as_jvalue;
mod env;
mod jni_type;
mod string_chars;
mod vm;

pub use array::*;
pub use as_jvalue::*;
pub use env::*;
pub use jni_type::JniType;
pub use refs::*;
pub use string_chars::*;
pub use vm::*;

/// Error returned on failed `.cast()`.`
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct CastError;

impl std::error::Error for CastError {}
impl fmt::Display for CastError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Cast failed")
    }
}

/// A marker type indicating this is a valid exception type that all exceptions thrown by java should be compatible with
pub trait ThrowableType: ReferenceType {}

/// You should generally not be interacting with this type directly, but it must be public for codegen.
/// This is hideously unsafe to implement:
///
/// 1) You assert the type is a #[repr(transparent)] wrapper around ObjectAndEnv.
/// 2) You assert the type cannot exist with a dangling object or env.
///     2.1) Do not implement Copy or Clone.
///     2.2) Do not allow value access.
///     2.3) Do not allow &mut T access.
///     2.4) Only allow &T access, which cannot be moved from.
#[doc(hidden)]
pub unsafe trait ReferenceType: JniType + 'static {}

/// Marker trait indicating `Self` can be assigned to `T`.
///
/// This is true when `T` is a superclass or superinterface of `Self`.
pub unsafe trait AssignableTo<T: ReferenceType>: ReferenceType {}

/// A type is always assignable to itself.
unsafe impl<T: ReferenceType> AssignableTo<T> for T {}

#[repr(C)] // Given how frequently we transmute to/from this, we'd better keep a consistent layout.
#[doc(hidden)] // You should generally not be interacting with this type directly, but it must be public for codegen.
#[derive(Copy, Clone)]
pub struct ObjectAndEnv {
    pub object: jni_sys::jobject,
    pub env: *mut jni_sys::JNIEnv,
}

pub unsafe trait AsArg<T>: Sized {
    fn as_arg(&self) -> jobject;
    fn as_arg_jvalue(&self) -> jvalue {
        jvalue { l: self.as_arg() }
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Null;

unsafe impl<T: ReferenceType, U: AsArg<T>> AsArg<T> for &U {
    fn as_arg(&self) -> jobject {
        U::as_arg(self)
    }
}

unsafe impl<T: ReferenceType, U: AsArg<T>> AsArg<T> for &mut U {
    fn as_arg(&self) -> jobject {
        U::as_arg(self)
    }
}

unsafe impl<T: ReferenceType> AsArg<T> for Null {
    fn as_arg(&self) -> jobject {
        null_mut()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Ref<'_, U> {
    fn as_arg(&self) -> jobject {
        self.as_raw()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<Ref<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<&Ref<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Local<'_, U> {
    fn as_arg(&self) -> jobject {
        self.as_raw()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<Local<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.as_ref().map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<&Local<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Global<U> {
    fn as_arg(&self) -> jobject {
        self.as_raw()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<Global<U>> {
    fn as_arg(&self) -> jobject {
        self.as_ref().map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<&Global<U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}