Skip to main content

java_jni_extras/
lib.rs

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}