1use jni::objects::JObject;
2
3
4pub trait IntoJava<'j> {
6 type Ret;
8 fn into_java(self, _: &mut jni::JNIEnv<'j>) -> Result<Self::Ret, jni::errors::Error>;
10}
11
12macro_rules! auto_into_java {
13 ($t: ty, $j: ty) => {
14 impl<'j> IntoJava<'j> for $t {
15 type Ret = $j;
16
17 #[inline]
18 fn into_java(self, _: &mut jni::JNIEnv<'j>) -> Result<Self::Ret, jni::errors::Error> {
19 Ok(self)
20 }
21 }
22 };
23}
24
25auto_into_java!(i64, jni::sys::jlong);
28auto_into_java!(i32, jni::sys::jint);
29auto_into_java!(i16, jni::sys::jshort);
30auto_into_java!(i8, jni::sys::jbyte);
31auto_into_java!(f32, jni::sys::jfloat);
32auto_into_java!(f64, jni::sys::jdouble);
33auto_into_java!((), ());
34
35impl<'j> IntoJava<'j> for bool {
36 type Ret = jni::sys::jboolean;
37
38 #[inline]
39 fn into_java(self, _: &mut jni::JNIEnv) -> Result<Self::Ret, jni::errors::Error> {
40 Ok(if self { 1 } else { 0 })
41 }
42}
43
44impl<'j, X: IntoJavaObject<'j>> IntoJava<'j> for X {
45 type Ret = jni::sys::jobject;
46
47 #[inline]
48 fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result<Self::Ret, jni::errors::Error> {
49 Ok(self.into_java_object(env)?.as_raw())
50 }
51}
52
53pub trait IntoJavaObject<'j> {
55 const CLASS: &'static str;
57 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error>;
59}
60
61impl<'j> IntoJavaObject<'j> for JObject<'j> {
62 const CLASS: &'static str = "java/lang/Object";
63 #[inline]
64 fn into_java_object(self, _: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
65 Ok(self)
66 }
67}
68
69macro_rules! auto_into_java_object {
70 ($t:ty, $cls:literal) => {
71 impl<'j> IntoJavaObject<'j> for $t {
72 const CLASS: &'static str = $cls;
73 #[inline]
74 fn into_java_object(self, _: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
75 Ok(self.into())
76 }
77 }
78 };
79}
80
81auto_into_java_object!(jni::objects::JString<'j>, "java/lang/String");
82auto_into_java_object!(jni::objects::JObjectArray<'j>, "java/lang/Object[]");
83auto_into_java_object!(jni::objects::JIntArray<'j>, "java/lang/Integer[]");
84auto_into_java_object!(jni::objects::JLongArray<'j>, "java/lang/Long[]");
85auto_into_java_object!(jni::objects::JShortArray<'j>, "java/lang/Short[]");
86auto_into_java_object!(jni::objects::JByteArray<'j>, "java/lang/Byte[]");
87auto_into_java_object!(jni::objects::JCharArray<'j>, "java/lang/Char[]");
88auto_into_java_object!(jni::objects::JFloatArray<'j>, "java/lang/Float[]");
89auto_into_java_object!(jni::objects::JDoubleArray<'j>, "java/lang/Double[]");
90auto_into_java_object!(jni::objects::JBooleanArray<'j>, "java/lang/Boolean[]");
91
92
93impl<'j> IntoJavaObject<'j> for &str {
94 const CLASS: &'static str = "java/lang/String";
95 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
96 Ok(env.new_string(self)?.into())
97 }
98}
99
100impl<'j> IntoJavaObject<'j> for String {
101 const CLASS: &'static str = "java/lang/String";
102 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
103 self.as_str().into_java_object(env)
104 }
105}
106
107impl<'j, T: IntoJavaObject<'j>> IntoJavaObject<'j> for Vec<T> {
108 const CLASS: &'static str = T::CLASS; fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
110 let mut array = env.new_object_array(self.len() as i32, T::CLASS, JObject::null())?;
111 for (n, el) in self.into_iter().enumerate() {
112 let el = el.into_java_object(env)?;
113 env.set_object_array_element(&mut array, n as i32, &el)?;
114 }
115 Ok(array.into())
116 }
117}
118
119impl<'j, T: IntoJavaObject<'j>> IntoJavaObject<'j> for Option<T> {
120 const CLASS: &'static str = T::CLASS;
121 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
122 match self {
123 Some(x) => x.into_java_object(env),
124 None => Ok(JObject::null())
125 }
126 }
127}
128
129macro_rules! auto_into_java_object_primitive_array {
130 ($t:ty, $fn_new:ident, $fn_set:ident, $clazz:literal) => {
131 impl<'j> IntoJavaObject<'j> for Vec<$t> {
132 const CLASS: &'static str = $clazz;
133 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
134 let len = self.len()
135 .try_into()
136 .map_err(|_| jni::errors::Error::JniCall(jni::errors::JniError::InvalidArguments))?;
137 let mut array = env.$fn_new(len)?;
138 env.$fn_set(&mut array, 0, self.as_slice())?;
139 Ok(array.into())
140 }
141 }
142 };
143}
144
145auto_into_java_object_primitive_array!(i8, new_byte_array, set_byte_array_region, "java/lang/Byte[]");
146auto_into_java_object_primitive_array!(i16, new_short_array, set_short_array_region, "java/lang/Short[]");
147auto_into_java_object_primitive_array!(i32, new_int_array, set_int_array_region, "java/lang/Integer[]");
148auto_into_java_object_primitive_array!(i64, new_long_array, set_long_array_region, "java/lang/Long[]");
149auto_into_java_object_primitive_array!(f32, new_float_array, set_float_array_region, "java/lang/Float[]");
150auto_into_java_object_primitive_array!(f64, new_double_array, set_double_array_region, "java/lang/Double[]");
151
152impl<'j> IntoJavaObject<'j> for Vec<bool> {
153 const CLASS: &'static str = "java/lang/Boolean[]";
154
155 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
156 let len = self.len()
157 .try_into()
158 .map_err(|_| jni::errors::Error::JniCall(jni::errors::JniError::InvalidArguments))?;
159 let mut array = env.new_boolean_array(len)?;
160 let new_self : Vec<u8> = self.into_iter().map(|x| if x { 1 } else { 0 }).collect();
161 env.set_boolean_array_region(&mut array, 0, new_self.as_slice())?;
162 Ok(array.into())
163 }
164}
165
166impl<'j> IntoJavaObject<'j> for Vec<char> {
167 const CLASS: &'static str = "java/lang/Char[]";
168
169 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
170 let len = self.len()
171 .try_into()
172 .map_err(|_| jni::errors::Error::JniCall(jni::errors::JniError::InvalidArguments))?;
173 let mut array = env.new_char_array(len)?;
174 let mut new_self : Vec<u16> = Vec::new();
175 for c in self {
176 new_self.push(
177 c
178 .try_into()
179 .map_err(|_| jni::errors::Error::JniCall(jni::errors::JniError::InvalidArguments))?
180 );
181 }
182 env.set_char_array_region(&mut array, 0, new_self.as_slice())?;
183 Ok(array.into())
184 }
185}
186
187#[cfg(feature = "uuid")]
188impl<'j> IntoJavaObject<'j> for uuid::Uuid {
189 const CLASS: &'static str = "java/util/UUID";
190 fn into_java_object(self, env: &mut jni::JNIEnv<'j>) -> Result<JObject<'j>, jni::errors::Error> {
191 let class = env.find_class(Self::CLASS)?;
192 let (msb, lsb) = self.as_u64_pair();
193 let msb = i64::from_ne_bytes(msb.to_ne_bytes());
194 let lsb = i64::from_ne_bytes(lsb.to_ne_bytes());
195 env.new_object(&class, "(JJ)V", &[jni::objects::JValueGen::Long(msb), jni::objects::JValueGen::Long(lsb)])
196 }
197}