java_bindgen/
interop.rs

1use crate::{exception::JavaCatchINI, j2r::IntoRustType, r2j::IntoJavaType};
2use std::borrow::BorrowMut;
3
4// Java primary types wrappers
5#[repr(transparent)]
6#[derive(Default, Debug)]
7pub struct JByte(pub i8);
8#[repr(transparent)]
9#[derive(Default, Debug)]
10pub struct JShort(pub i16);
11#[repr(transparent)]
12#[derive(Default, Debug)]
13pub struct JInt(pub i32);
14#[repr(transparent)]
15#[derive(Default, Debug)]
16pub struct JLong(pub i64);
17#[repr(transparent)]
18#[derive(Default, Debug)]
19pub struct JFloat(pub f32);
20#[repr(transparent)]
21#[derive(Default, Debug)]
22pub struct JDouble(pub f64);
23#[repr(transparent)]
24#[derive(Default, Debug)]
25pub struct JBoolean(pub bool);
26#[repr(transparent)]
27#[derive(Default, Debug)]
28pub struct JChar(pub char);
29
30#[repr(transparent)]
31#[derive(Default, Debug)]
32pub struct JVoid();
33
34// Getters
35pub trait JObjectGetters<'l> {
36    fn call_getter<T>(&self, name: &str, env: &mut jni::JNIEnv<'l>) -> crate::JResult<T>
37    where
38        T: JTypeInfo<'l>,
39        JValueGen<jni::objects::JObject<'l>>: crate::j2r::IntoRustType<'l, T>;
40}
41
42impl<'local> JObjectGetters<'local> for jni::objects::JObject<'local> {
43    fn call_getter<T>(&self, name: &str, env: &mut jni::JNIEnv<'local>) -> crate::JResult<T>
44    where
45        T: JTypeInfo<'local>,
46        JValueGen<jni::objects::JObject<'local>>: crate::j2r::IntoRustType<'local, T>,
47    {
48        let ty = T::j_type().to_string();
49        let e = env
50            .call_method(self, name, format!("(){ty}"), &[])
51            .j_catch_ini(env, &format!("Call Java getter: {name}()"))?;
52
53        e.into_rust(env)
54    }
55}
56
57use jni::objects::{JValueGen, JValueOwned};
58
59pub use jtypes::*;
60mod jtypes {
61    use crate::prelude::*;
62    // use crate::{prelude::JavaCatchINI, JResult};
63    use jni::{
64        objects::{JObject, JValueOwned},
65        signature::{JavaType, ReturnType},
66    };
67
68    // Signature Builder
69    #[doc(hidden)]
70    pub struct TypeSignatureBuilder {
71        args: Vec<jni::signature::JavaType>,
72    }
73
74    #[allow(dead_code)]
75    impl<'l> TypeSignatureBuilder {
76        pub fn new1<V: JTypeInfo<'l>>(_: &V) -> Self {
77            Self {
78                args: vec![V::j_type()],
79            }
80        }
81
82        pub fn new_noargs1<R: JTypeInfo<'l>>(_: &R) -> jni::signature::TypeSignature {
83            jni::signature::TypeSignature {
84                args: vec![],
85                ret: R::j_return_type(),
86            }
87        }
88
89        pub fn arg1<V: JTypeInfo<'l>>(mut self, _: &V) -> Self {
90            self.args.push(V::j_type());
91            self
92        }
93
94        pub fn ret1<R: JTypeInfo<'l>>(self, _: &R) -> jni::signature::TypeSignature {
95            jni::signature::TypeSignature {
96                args: self.args,
97                ret: R::j_return_type(),
98            }
99        }
100
101        pub fn new<V: JTypeInfo<'l>>() -> Self {
102            Self {
103                args: vec![V::j_type()],
104            }
105        }
106
107        pub fn new_noargs<R: JTypeInfo<'l>>() -> jni::signature::TypeSignature {
108            jni::signature::TypeSignature {
109                args: vec![],
110                ret: R::j_return_type(),
111            }
112        }
113
114        pub fn arg<V: JTypeInfo<'l>>(mut self) -> Self {
115            self.args.push(V::j_type());
116            self
117        }
118
119        pub fn ret<R: JTypeInfo<'l>>(self) -> jni::signature::TypeSignature {
120            jni::signature::TypeSignature {
121                args: self.args,
122                ret: R::j_return_type(),
123            }
124        }
125    }
126
127    #[doc(hidden)]
128    pub fn arg1<V: for<'l> JTypeInfo<'l>>(v: &V) -> TypeSignatureBuilder {
129        TypeSignatureBuilder::new1(v)
130    }
131
132    pub fn arg<V: for<'l> JTypeInfo<'l>>() -> TypeSignatureBuilder {
133        TypeSignatureBuilder::new::<V>()
134    }
135
136    #[macro_export]
137    macro_rules! signature_by_type {
138       ($a1:ty , $($arg:ty),* => $_return:ty) => {
139            TypeSignatureBuilder::new::<$a1>()
140            $(.arg::<$arg>())
141            *
142            .ret::<$_return>()
143        };
144        ( => $_return:ty) => { TypeSignatureBuilder::new_noargs::<$_return>() };
145        ( $a1:ty => $_return:ty) => { TypeSignatureBuilder::new::<$a1>().ret::<$_return>() };
146
147        ( => ) => { signature_by_type! {=> JVoid} };
148        ( $a1:ty => ) => { signature_by_type!($a1 => JVoid) };
149        ($a1:ty , $($arg:ty),* => ) => { signature_by_type!( $a1 , $($arg)* => JVoid) };
150    }
151
152    #[macro_export]
153    macro_rules! signature_by_value {
154         ($a1:expr , $($arg:expr),* => $_return:expr) => {
155            TypeSignatureBuilder::new1(&$a1)
156            $(.arg1(&$arg))
157            *
158            .ret1(&$_return)
159        };
160        ( => $_return:expr) => { TypeSignatureBuilder::new_noargs1(&$_return) };
161        ( $a1:expr => $_return:expr) => { TypeSignatureBuilder::new1(&$a1).ret1(&$_return) };
162
163        ( => ) => { signature_by_value! { => JVoid() } };
164        ( $a1:expr => ) => { signature_by_value!( $a1 => JVoid()) };
165        ($a1:expr , $($arg:expr),* => ) => { signature_by_value!( $a1 , $($arg)* => JVoid())  };
166    }
167
168    // Rust to JavaType Info
169    pub trait JTypeInfo<'local>
170    where
171        Self: Sized,
172    {
173        fn j_return_type() -> jni::signature::ReturnType;
174        fn j_type() -> jni::signature::JavaType;
175        fn j_value_type(&self) -> jni::signature::JavaType {
176            Self::j_type()
177        }
178        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>>;
179    }
180
181    impl<'local, T: JTypeInfo<'local> + Default> JTypeInfo<'local> for Option<T> {
182        fn j_return_type() -> ReturnType {
183            T::j_return_type()
184        }
185
186        fn j_type() -> JavaType {
187            T::j_type()
188        }
189
190        fn into_j_value(self, env: &mut JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
191            match self {
192                None => {
193                    match T::j_type() {
194                        JavaType::Primitive(_) => T::default().into_j_value(env),
195                        _ => Ok(JValueOwned::Object(JObject::null()))
196                    }
197                }
198                Some(v) => v.into_j_value(env)
199            }
200        }
201    }
202
203    impl<'local> JTypeInfo<'local> for JVoid {
204        fn j_return_type() -> jni::signature::ReturnType {
205            ReturnType::Primitive(jni::signature::Primitive::Void)
206        }
207
208        fn j_type() -> jni::signature::JavaType {
209            JavaType::Primitive(jni::signature::Primitive::Void)
210        }
211
212        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
213            Ok(JValueOwned::Void)
214        }
215    }
216
217    impl<'local> JTypeInfo<'local> for u8 {
218        fn j_return_type() -> jni::signature::ReturnType {
219            ReturnType::Primitive(jni::signature::Primitive::Byte)
220        }
221
222        fn j_type() -> jni::signature::JavaType {
223            JavaType::Primitive(jni::signature::Primitive::Byte)
224        }
225
226        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
227            Ok(JValueOwned::Byte(self as i8))
228        }
229    }
230
231    impl<'local> JTypeInfo<'local> for i16 {
232        fn j_return_type() -> jni::signature::ReturnType {
233            ReturnType::Primitive(jni::signature::Primitive::Short)
234        }
235
236        fn j_type() -> jni::signature::JavaType {
237            JavaType::Primitive(jni::signature::Primitive::Short)
238        }
239
240        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
241            Ok(JValueOwned::Short(self))
242        }
243    }
244
245    impl<'local> JTypeInfo<'local> for i32 {
246        fn j_return_type() -> jni::signature::ReturnType {
247            ReturnType::Primitive(jni::signature::Primitive::Int)
248        }
249
250        fn j_type() -> jni::signature::JavaType {
251            JavaType::Primitive(jni::signature::Primitive::Int)
252        }
253
254        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
255            Ok(JValueOwned::Int(self))
256        }
257    }
258
259    impl<'local> JTypeInfo<'local> for i64 {
260        fn j_return_type() -> jni::signature::ReturnType {
261            ReturnType::Primitive(jni::signature::Primitive::Long)
262        }
263
264        fn j_type() -> jni::signature::JavaType {
265            JavaType::Primitive(jni::signature::Primitive::Long)
266        }
267
268        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
269            Ok(JValueOwned::Long(self))
270        }
271    }
272
273    impl<'local> JTypeInfo<'local> for f32 {
274        fn j_return_type() -> jni::signature::ReturnType {
275            ReturnType::Primitive(jni::signature::Primitive::Float)
276        }
277
278        fn j_type() -> jni::signature::JavaType {
279            JavaType::Primitive(jni::signature::Primitive::Float)
280        }
281
282        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
283            Ok(JValueOwned::Float(self))
284        }
285    }
286
287    impl<'local> JTypeInfo<'local> for f64 {
288        fn j_return_type() -> jni::signature::ReturnType {
289            ReturnType::Primitive(jni::signature::Primitive::Double)
290        }
291
292        fn j_type() -> jni::signature::JavaType {
293            JavaType::Primitive(jni::signature::Primitive::Double)
294        }
295
296        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
297            Ok(JValueOwned::Double(self))
298        }
299    }
300
301    impl<'local> JTypeInfo<'local> for bool {
302        fn j_return_type() -> jni::signature::ReturnType {
303            ReturnType::Primitive(jni::signature::Primitive::Boolean)
304        }
305
306        fn j_type() -> jni::signature::JavaType {
307            JavaType::Primitive(jni::signature::Primitive::Boolean)
308        }
309
310        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
311            Ok(JValueOwned::Bool(self as u8))
312        }
313    }
314
315    impl<'local> JTypeInfo<'local> for char {
316        fn j_return_type() -> jni::signature::ReturnType {
317            ReturnType::Primitive(jni::signature::Primitive::Char)
318        }
319
320        fn j_type() -> jni::signature::JavaType {
321            JavaType::Primitive(jni::signature::Primitive::Char)
322        }
323
324        fn into_j_value(self, _: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
325            Ok(JValueOwned::Char(self as u16))
326        }
327    }
328
329    // Implementing JTypeInfo for wrapper classes
330
331    impl<'local> JTypeInfo<'local> for JByte {
332        fn j_return_type() -> jni::signature::ReturnType {
333            ReturnType::Object
334        }
335
336        fn j_type() -> jni::signature::JavaType {
337            JavaType::Object("java/lang/Byte".to_string())
338        }
339
340        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
341            let obj = self.into_java(env)?;
342            Ok(JValueOwned::Object(obj))
343        }
344    }
345
346    impl<'local> JTypeInfo<'local> for JShort {
347        fn j_return_type() -> jni::signature::ReturnType {
348            ReturnType::Object
349        }
350
351        fn j_type() -> jni::signature::JavaType {
352            JavaType::Object("java/lang/Short".to_string())
353        }
354
355        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
356            let obj = self.into_java(env)?;
357            Ok(JValueOwned::Object(obj))
358        }
359    }
360
361    impl<'local> JTypeInfo<'local> for JInt {
362        fn j_return_type() -> jni::signature::ReturnType {
363            ReturnType::Object
364        }
365
366        fn j_type() -> jni::signature::JavaType {
367            JavaType::Object("java/lang/Integer".to_string())
368        }
369
370        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
371            let obj = self.into_java(env)?;
372            Ok(JValueOwned::Object(obj))
373        }
374    }
375
376    impl<'local> JTypeInfo<'local> for JLong {
377        fn j_return_type() -> jni::signature::ReturnType {
378            ReturnType::Object
379        }
380
381        fn j_type() -> jni::signature::JavaType {
382            JavaType::Object("java/lang/Long".to_string())
383        }
384
385        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
386            let obj = self.0.into_java(env)?;
387            Ok(JValueOwned::Object(obj))
388        }
389    }
390
391    impl<'local> JTypeInfo<'local> for JFloat {
392        fn j_return_type() -> jni::signature::ReturnType {
393            ReturnType::Object
394        }
395
396        fn j_type() -> jni::signature::JavaType {
397            JavaType::Object("java/lang/Float".to_string())
398        }
399
400        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
401            let obj = self.into_java(env)?;
402            Ok(JValueOwned::Object(obj))
403        }
404    }
405
406    impl<'local> JTypeInfo<'local> for JDouble {
407        fn j_return_type() -> jni::signature::ReturnType {
408            ReturnType::Object
409        }
410
411        fn j_type() -> jni::signature::JavaType {
412            JavaType::Object("java/lang/Double".to_string())
413        }
414
415        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
416            let obj = self.into_java(env)?;
417            Ok(JValueOwned::Object(obj))
418        }
419    }
420
421    impl<'local> JTypeInfo<'local> for JBoolean {
422        fn j_return_type() -> jni::signature::ReturnType {
423            ReturnType::Object
424        }
425
426        fn j_type() -> jni::signature::JavaType {
427            JavaType::Object("java/lang/Boolean".to_string())
428        }
429
430        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
431            let obj = self.into_java(env)?;
432            Ok(JValueOwned::Object(obj))
433        }
434    }
435
436    impl<'local> JTypeInfo<'local> for JChar {
437        fn j_return_type() -> jni::signature::ReturnType {
438            ReturnType::Object
439        }
440
441        fn j_type() -> jni::signature::JavaType {
442            JavaType::Object("java/lang/Character".to_string())
443        }
444
445        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
446            let obj = self.into_java(env)?;
447            Ok(JValueOwned::Object(obj))
448        }
449    }
450
451    // String
452
453    impl<'local> JTypeInfo<'local> for String {
454        fn j_return_type() -> jni::signature::ReturnType {
455            ReturnType::Object
456        }
457
458        fn j_type() -> jni::signature::JavaType {
459            JavaType::Object("java/lang/String".to_string())
460        }
461
462        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
463            let obj = env
464                .new_string(&self)
465                .j_catch_ini(env, "String -> JString")?;
466            Ok(JValueOwned::Object(JObject::from(obj)))
467        }
468    }
469
470    impl<'local> JTypeInfo<'local> for Vec<u8> {
471        fn j_return_type() -> jni::signature::ReturnType {
472            ReturnType::Object
473        }
474
475        fn j_type() -> jni::signature::JavaType {
476            JavaType::Array(Box::new(JavaType::Primitive(
477                jni::signature::Primitive::Byte,
478            )))
479        }
480
481        fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> JResult<JValueOwned<'local>> {
482            let array = env
483                .byte_array_from_slice(&self)
484                .j_catch_ini(env, "Vec<u8> -> JByteArray")?;
485            Ok(JValueOwned::Object(JObject::from(array)))
486        }
487    }
488
489    #[cfg(test)]
490    pub mod tests {
491        use jni::signature::{Primitive, TypeSignature};
492
493        use super::*;
494
495        #[test]
496        pub fn test_primitive_types() {
497            assert_eq!(100u8.j_value_type(), JavaType::Primitive(Primitive::Byte));
498
499            assert_eq!(100i16.j_value_type(), JavaType::Primitive(Primitive::Short));
500
501            assert_eq!(100i32.j_value_type(), JavaType::Primitive(Primitive::Int));
502
503            assert_eq!(100i64.j_value_type(), JavaType::Primitive(Primitive::Long));
504
505            assert_eq!(
506                100.0f32.j_value_type(),
507                JavaType::Primitive(Primitive::Float)
508            );
509
510            assert_eq!(
511                100.0f64.j_value_type(),
512                JavaType::Primitive(Primitive::Double)
513            );
514
515            assert_eq!(true.j_value_type(), JavaType::Primitive(Primitive::Boolean));
516
517            assert_eq!('a'.j_value_type(), JavaType::Primitive(Primitive::Char));
518        }
519
520        #[test]
521        pub fn test_wrapper_types() {
522            assert_eq!(
523                JByte(100).j_value_type(),
524                JavaType::Object("java/lang/Byte".to_string())
525            );
526
527            assert_eq!(
528                JShort(100).j_value_type(),
529                JavaType::Object("java/lang/Short".to_string())
530            );
531
532            assert_eq!(
533                JInt(100).j_value_type(),
534                JavaType::Object("java/lang/Integer".to_string())
535            );
536
537            assert_eq!(
538                JLong(100).j_value_type(),
539                JavaType::Object("java/lang/Long".to_string())
540            );
541
542            assert_eq!(
543                JFloat(100.0).j_value_type(),
544                JavaType::Object("java/lang/Float".to_string())
545            );
546
547            assert_eq!(
548                JDouble(100.0).j_value_type(),
549                JavaType::Object("java/lang/Double".to_string())
550            );
551
552            assert_eq!(
553                JBoolean(true).j_value_type(),
554                JavaType::Object("java/lang/Boolean".to_string())
555            );
556
557            assert_eq!(
558                JChar('a').j_value_type(),
559                JavaType::Object("java/lang/Character".to_string())
560            );
561        }
562
563        #[test]
564        pub fn test_class_types() {
565            assert_eq!(
566                "string".to_string().j_value_type(),
567                JavaType::Object("java/lang/String".to_string())
568            );
569        }
570
571        #[test]
572        pub fn test_signature_builder() {
573            // builder
574            assert_eq!(
575                TypeSignature::from_str("(ILjava/lang/String;)F").unwrap(),
576                arg::<i32>().arg::<String>().ret::<f32>()
577            );
578
579            assert_eq!(
580                TypeSignature::from_str("(ILjava/lang/String;)F").unwrap(),
581                arg1(&10).arg1(&"test".to_string()).ret1(&10_f32)
582            );
583        }
584
585        #[test]
586        pub fn test_signature_macro_by_type() {
587            assert_eq!(
588                TypeSignature::from_str("(Ljava/lang/String;I)V").unwrap(),
589                signature_by_type!( String , i32 => )
590            );
591            assert_eq!(
592                TypeSignature::from_str("(Ljava/lang/String;[B)V").unwrap(),
593                signature_by_type!( String , Vec<u8> => JVoid )
594            );
595            assert_eq!(
596                TypeSignature::from_str("(Ljava/lang/String;[B)I").unwrap(),
597                signature_by_type!( Option<String> , Option<Vec<u8>> => Option<i32> )
598            );
599
600            println!("{}", signature_by_type!( => ));
601            println!("{}", signature_by_type!( => String));
602            println!("{}", signature_by_type!( => i32));
603            println!("{}", signature_by_type!( String  => i32));
604            println!("{}", signature_by_type!( String  => ));
605            println!("{}", signature_by_type!( String , i32 => i32));
606            println!("{}", signature_by_type!( String , i32 => i32));
607            println!("{}", signature_by_type!( String , i32 => ));
608            println!("{}", signature_by_type!( String , Vec<u8> => JVoid ));
609        }
610
611        #[test]
612        pub fn test_signature_macro_by_value() {
613            let string = "ok".to_string();
614            assert_eq!(
615                TypeSignature::from_str("(Ljava/lang/String;I)I").unwrap(),
616                signature_by_value!( string, 10_i32 => 10_i32)
617            );
618
619            println!("{}", signature_by_value!( => ));
620            println!("{}", signature_by_value!( => string));
621            println!("{}", signature_by_value!( => 10_i32));
622            println!("{}", signature_by_value!( string  => 10_i32));
623            println!("{}", signature_by_value!( string  => ));
624            println!("{}", signature_by_value!( string , 10_i32 => 10_i32));
625            println!("{}", signature_by_value!( string , 10_i32 => 10_i32));
626            println!("{}", signature_by_value!( string , 10_i32 => ));
627        }
628    }
629}
630
631// Java List<T> Support
632
633#[derive(Default)]
634pub struct JList<T>(pub Vec<T>);
635
636impl<T> JList<T> {
637    pub fn add(&mut self, element: T) {
638        self.0.push(element)
639    }
640
641    pub fn add_at(&mut self, index: usize, element: T) {
642        self.0.insert(index, element)
643    }
644
645    pub fn get(&self, index: usize) -> Option<&T> {
646        self.0.get(index)
647    }
648}
649
650impl<'local, T> JList<T>
651where
652    jni::objects::JObject<'local>: IntoRustType<'local, i32> + IntoRustType<'local, T>,
653{
654    fn from_j_object(
655        mut obj: jni::objects::JObject<'local>,
656        env: &mut jni::JNIEnv<'local>,
657    ) -> crate::JResult<Self> {
658        let mut items = vec![];
659
660        let size: i32 = obj.borrow_mut().call_getter("size", env)?;
661        for i in 0..size {
662            let index = i.into_j_value(env)?;
663            let e = env
664                .call_method(
665                    &mut obj,
666                    "get",
667                    "(I)Ljava/lang/Object;".to_string(),
668                    &[index.borrow()],
669                )
670                .j_catch_ini(env, &"List.get(int) failed".to_string())?;
671
672            let obj = e.l()?;
673            let item: T = obj.into_rust(env)?;
674            items.push(item)
675        }
676
677        Ok(JList(items))
678    }
679}
680
681impl<'local, T> JList<T>
682where
683    T: IntoJavaType<'local, jni::objects::JObject<'local>>,
684{
685    fn into_j_object(
686        self,
687        env: &mut jni::JNIEnv<'local>,
688    ) -> crate::JResult<jni::objects::JObject<'local>> {
689        let class = env
690            .find_class("java/util/ArrayList")
691            .j_catch_ini(env, "ArrayList class not found")?;
692        let mut array_list = env
693            .new_object(class, "()V", &[])
694            .j_catch_ini(env, "Failed to create ArrayList")?;
695
696        for item in self.0.into_iter() {
697            let obj = item.into_java(env)?;
698            let index = JValueOwned::Object(obj);
699            env.call_method(
700                &mut array_list,
701                "add",
702                "(Ljava/lang/Object;)Z".to_string(),
703                &[index.borrow()],
704            )
705                .j_catch_ini(env, &"ArrayList.add(T) failed".to_string())?;
706        }
707
708        Ok(array_list)
709    }
710}
711
712impl<'local, T> IntoRustType<'local, JList<T>> for jni::objects::JObject<'local>
713where
714    jni::objects::JObject<'local>: IntoRustType<'local, i32> + IntoRustType<'local, T>,
715{
716    fn into_rust(self, env: &mut jni::JNIEnv<'local>) -> crate::JResult<JList<T>> {
717        JList::from_j_object(self, env)
718    }
719}
720
721impl<'local, T> IntoJavaType<'local, jni::objects::JObject<'local>> for JList<T>
722where
723    T: IntoJavaType<'local, jni::objects::JObject<'local>>,
724{
725    fn into_java(
726        self,
727        env: &mut jni::JNIEnv<'local>,
728    ) -> crate::JResult<jni::objects::JObject<'local>> {
729        self.into_j_object(env)
730    }
731}
732
733impl<'local, T> IntoRustType<'local, JList<T>>
734for jni::objects::JValueGen<jni::objects::JObject<'local>>
735where
736    jni::objects::JObject<'local>: IntoRustType<'local, i32> + IntoRustType<'local, T>,
737{
738    fn into_rust(self, env: &mut jni::JNIEnv<'local>) -> crate::JResult<JList<T>> {
739        let obj = self.l()?;
740        JList::from_j_object(obj, env)
741    }
742}
743
744impl<'local, T> JTypeInfo<'local> for JList<T>
745where
746    T: IntoJavaType<'local, jni::objects::JObject<'local>>,
747{
748    fn j_return_type() -> jni::signature::ReturnType {
749        jni::signature::ReturnType::Object
750    }
751
752    fn j_type() -> jni::signature::JavaType {
753        jni::signature::JavaType::Object("java/util/List".to_string())
754    }
755
756    fn into_j_value(self, env: &mut jni::JNIEnv<'local>) -> crate::JResult<JValueOwned<'local>> {
757        let obj = self.into_j_object(env)?;
758        Ok(JValueOwned::Object(jni::objects::JObject::from(obj)))
759    }
760}