1use jni::Env;
2use jni::objects::{JObject, JObjectArray, JPrimitiveArray, JString, Reference, TypeArray};
3use jni::sys::{jboolean, jbyte, jchar, jdouble, jfloat, jint, jlong, jshort};
4pub use java_jni_extras_proc::java_class;
5
6pub trait JavaTyped<'c> {
7 type JType;
8 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType>;
9}
10
11trait JavaObject {}
12impl<'c> JavaObject for JObject<'c> {}
13impl<'c> JavaObject for JObjectArray<'c> {}
14impl<'c, T: TypeArray> JavaObject for JPrimitiveArray<'c, T> {}
15
16pub trait JavaPrimitive: Sized {
17 type P: Sized + TypeArray;
18 fn as_java(&self) -> Self::P;
19}
20macro_rules! java_primitive {
21 ( $T:ty, $j:ty ) => {
22 const _: () = const {
23 assert!(std::mem::size_of::<$T>() == std::mem::size_of::<<$T as JavaPrimitive>::P>());
24 };
25 impl JavaPrimitive for $T {
26 type P = $j;
27 fn as_java(&self) -> Self::P {
28 *self
29 }
30 }
31 impl<'c, 'r> JavaTyped<'c> for &[$T]
32 {
33 type JType = JPrimitiveArray<'c, <$T as JavaPrimitive>::P>;
34 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
35 let arr = JPrimitiveArray::<<$T as JavaPrimitive>::P>::new(env, self.len())?;
36 arr.set_region(env, 0, unsafe { std::mem::transmute(self) })?;
37 Ok(arr)
38 }
39 }
40 impl<'c, 'r, const N: usize> JavaTyped<'c> for &[$T; N]
41 {
42 type JType = JPrimitiveArray<'c, <$T as JavaPrimitive>::P>;
43 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
44 let arr = JPrimitiveArray::<<$T as JavaPrimitive>::P>::new(env, self.len())?;
45 arr.set_region(env, 0, unsafe { std::mem::transmute(self.as_slice()) })?;
46 Ok(arr)
47 }
48 }
49 impl<'c, 'r> JavaTyped<'c> for Vec<$T>
50 {
51 type JType = JPrimitiveArray<'c, <$T as JavaPrimitive>::P>;
52 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
53 let arr = JPrimitiveArray::<<$T as JavaPrimitive>::P>::new(env, self.len())?;
54 arr.set_region(env, 0, unsafe { std::mem::transmute(self.as_slice()) })?;
55 Ok(arr)
56 }
57 }
58 };
59}
60
61java_primitive! { i8, jbyte }
62java_primitive! { u16, jchar }
63java_primitive! { i16, jshort }
64java_primitive! { i32, jint }
65java_primitive! { i64, jlong }
66java_primitive! { f32, jfloat }
67java_primitive! { f64, jdouble }
68java_primitive! { bool, jboolean }
69
70impl<'c, T: Sized + JavaPrimitive> JavaTyped<'c> for T {
71 type JType = T::P;
72 fn into_java<'local>(self, _env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
73 Ok(self.as_java())
74 }
75}
76
77impl<'c, 'r> JavaTyped<'c> for &str {
78 type JType = JString<'c>;
79 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
80 env.new_string(self)
81 }
82}
83
84impl<'c, 'r> JavaTyped<'c> for String {
85 type JType = JString<'c>;
86 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
87 env.new_string(self)
88 }
89}
90
91impl<'c, 'r, T> JavaTyped<'c> for &[T]
92where
93 T: JavaObject + JavaTyped<'c> + Reference<Kind<'c> = T> + AsRef<JObject<'c>>,
94 T::JType: 'c + Reference<Kind<'c> = T::JType> + AsRef<T::JType>,
95{
96 type JType = JObjectArray<'c, T::JType>;
97 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
98 let null = T::JType::null();
99 let arr: Self::JType = JObjectArray::<'c, T::JType>::new(env, self.len(), null)?;
100 for (i, v) in self.iter().enumerate() {
101 let v = env.new_local_ref(v)?;
102 let v = JavaTyped::<'c>::into_java(v, env)?;
103 arr.set_element(env, i, v)?;
104 }
105 Ok(arr)
106 }
107}
108
109impl<'c, 'r, T, const N: usize> JavaTyped<'c> for &[T; N]
110where
111 T: JavaObject + JavaTyped<'c> + Reference<Kind<'c> = T> + AsRef<JObject<'c>>,
112 T::JType: 'c + Reference<Kind<'c> = T::JType> + AsRef<T::JType>,
113{
114 type JType = JObjectArray<'c, T::JType>;
115 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
116 let null = T::JType::null();
117 let arr: Self::JType = JObjectArray::<'c, T::JType>::new(env, self.len(), null)?;
118 for (i, v) in self.iter().enumerate() {
119 let v = env.new_local_ref(v)?;
120 let v = JavaTyped::<'c>::into_java(v, env)?;
121 arr.set_element(env, i, v)?;
122 }
123 Ok(arr)
124 }
125}
126
127impl<'c, 'r, T> JavaTyped<'c> for Vec<T>
128where
129 T: JavaObject + JavaTyped<'c> + Reference<Kind<'c> = T> + AsRef<JObject<'c>>,
130 T::JType: 'c + Reference<Kind<'c> = T::JType> + AsRef<T::JType>,
131{
132 type JType = JObjectArray<'c, T::JType>;
133 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
134 let null = T::JType::null();
135 let arr: Self::JType = JObjectArray::<'c, T::JType>::new(env, self.len(), null)?;
136 for (i, v) in self.into_iter().enumerate() {
137 let v = JavaTyped::<'c>::into_java(v, env)?;
138 arr.set_element(env, i, v)?;
139 }
140 Ok(arr)
141 }
142}
143
144impl<'c, 'r> JavaTyped<'c> for &[&str] {
145 type JType = JObjectArray<'c, JString<'c>>;
146 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
147 let null = JString::null();
148 let arr: Self::JType = JObjectArray::<'c, JString>::new(env, self.len(), null)?;
149 for (i, v) in self.iter().enumerate() {
150 let v = v.into_java(env)?;
151 arr.set_element(env, i, v)?;
152 }
153 Ok(arr)
154 }
155}
156
157impl<'c, 'r, const N: usize> JavaTyped<'c> for &[&str; N] {
158 type JType = JObjectArray<'c, JString<'c>>;
159 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
160 let null = JString::null();
161 let arr: Self::JType = JObjectArray::<'c, JString>::new(env, self.len(), null)?;
162 for (i, v) in self.iter().enumerate() {
163 let v = v.into_java(env)?;
164 arr.set_element(env, i, v)?;
165 }
166 Ok(arr)
167 }
168}
169
170impl<'c, 'r> JavaTyped<'c> for Vec<&str> {
171 type JType = JObjectArray<'c, JString<'c>>;
172 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
173 let null = JString::null();
174 let arr: Self::JType = JObjectArray::<'c, JString>::new(env, self.len(), null)?;
175 for (i, v) in self.into_iter().enumerate() {
176 let v = v.into_java(env)?;
177 arr.set_element(env, i, v)?;
178 }
179 Ok(arr)
180 }
181}
182
183impl<'c, 'r> JavaTyped<'c> for &[String] {
184 type JType = JObjectArray<'c, JString<'c>>;
185 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
186 let null = JString::null();
187 let arr: Self::JType = JObjectArray::<'c, JString>::new(env, self.len(), null)?;
188 for (i, v) in self.iter().enumerate() {
189 let v = v.clone().into_java(env)?;
190 arr.set_element(env, i, v)?;
191 }
192 Ok(arr)
193 }
194}
195
196impl<'c, 'r, const N: usize> JavaTyped<'c> for &[String; N] {
197 type JType = JObjectArray<'c, JString<'c>>;
198 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
199 let null = JString::null();
200 let arr: Self::JType = JObjectArray::<'c, JString>::new(env, self.len(), null)?;
201 for (i, v) in self.iter().enumerate() {
202 let v = v.clone().into_java(env)?;
203 arr.set_element(env, i, v)?;
204 }
205 Ok(arr)
206 }
207}
208
209impl<'c, 'r> JavaTyped<'c> for Vec<String> {
210 type JType = JObjectArray<'c, JString<'c>>;
211 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
212 let null = JString::null();
213 let arr: Self::JType = JObjectArray::<'c, JString>::new(env, self.len(), null)?;
214 for (i, v) in self.into_iter().enumerate() {
215 let v = v.into_java(env)?;
216 arr.set_element(env, i, v)?;
217 }
218 Ok(arr)
219 }
220}
221
222impl<'c> JavaTyped<'c> for JObject<'c> {
223 type JType = Self;
224 fn into_java<'local>(self, _env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
225 Ok(self)
226 }
227}
228
229impl<'c> JavaTyped<'c> for JObjectArray<'c> {
230 type JType = Self;
231 fn into_java<'local>(self, _env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
232 Ok(self)
233 }
234}
235
236impl<'c, T: TypeArray> JavaTyped<'c> for JPrimitiveArray<'c, T> {
237 type JType = Self;
238 fn into_java<'local>(self, _env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
239 Ok(self)
240 }
241}
242
243pub enum MaybeJavaTyped<'c, T>
244where
245 T: JavaTyped<'c>
246{
247 Java(T::JType),
248 Rust(T),
249}
250
251impl<'c, T> JavaTyped<'c> for MaybeJavaTyped<'c, T>
252where
253 T: JavaTyped<'c>
254{
255 type JType = T::JType;
256 fn into_java<'local>(self, env: &'local mut Env<'c>) -> jni::errors::Result<Self::JType> {
257 match self {
258 Self::Rust(r) => r.into_java(env),
259 Self::Java(j) => Ok(j)
260 }
261 }
262}