1use java::{ResultExt, Type};
2use jni::objects::{GlobalRef,
3 JBooleanArray,
4 JByteArray,
5 JCharArray,
6 JDoubleArray,
7 JFloatArray,
8 JIntArray,
9 JLongArray,
10 JObject,
11 JObjectArray,
12 JShortArray,
13 JValue,
14 JValueOwned};
15use jni::sys::jobject;
16
17use crate::java;
18
19pub trait Object
25 where Self: java::Type
26{
27 fn upcast(e: &mut java::Env, jobj: java::lang::Object) -> Self;
29
30 fn downcast(self, e: &mut java::Env) -> java::lang::Object;
32
33 fn downcast_ref(&self, e: &mut java::Env) -> java::lang::Object;
35
36 fn upcast_value_ref<'e>(e: &mut java::Env<'e>, jv: JValue<'e, '_>) -> Self
38 where Self: Sized
39 {
40 java::lang::Object::upcast_value_ref(e, jv).upcast_to::<Self>(e)
41 }
42
43 fn upcast_value<'e>(e: &mut java::Env<'e>, jv: JValueOwned<'e>) -> Self
45 where Self: Sized
46 {
47 Self::upcast_value_ref(e, (&jv).into())
48 }
49
50 fn downcast_value<'e>(self, e: &mut java::Env<'e>) -> JValueOwned<'e>
52 where Self: Sized
53 {
54 self.downcast(e).downcast_value(e)
55 }
56
57 fn yield_to_java(&self, e: &mut java::Env) -> jobject {
61 self.downcast_ref(e).yield_to_java(e)
62 }
63}
64
65impl Object for GlobalRef {
66 fn upcast(_: &mut java::Env, jobj: java::lang::Object) -> Self {
67 jobj.into()
68 }
69
70 fn downcast(self, _: &mut java::Env) -> java::lang::Object {
71 self.into()
72 }
73
74 fn downcast_ref(&self, e: &mut java::Env) -> java::lang::Object {
75 e.new_global_ref(self).unwrap().into()
76 }
77}
78
79impl<T> Object for Vec<T> where T: java::Object
80{
81 fn upcast(e: &mut java::Env, jobj: java::lang::Object) -> Self {
82 let arr = <&JObjectArray>::from(jobj.as_local());
83 let len = e.get_array_length(arr).unwrap_java(e) as usize;
84
85 macro_rules! go {
86 ($arr:ty => $get_region:ident) => {{
87 let arr = <&$arr>::from(jobj.as_local());
88 let mut els = Vec::new();
89 els.resize(len, Default::default());
90 e.$get_region(&arr, 0, &mut els).unwrap_java(e);
91 els.into_iter()
92 .map(|b| {
93 let val = b.downcast_value(e);
94 T::upcast_value(e, val)
95 })
96 .collect()
97 }};
98 }
99
100 match T::SIG {
101 | i8::SIG => go!(JByteArray => get_byte_array_region),
102 | i16::SIG => go!(JShortArray => get_short_array_region),
103 | i32::SIG => go!(JIntArray => get_int_array_region),
104 | i64::SIG => go!(JLongArray => get_long_array_region),
105 | f32::SIG => go!(JFloatArray => get_float_array_region),
106 | f64::SIG => go!(JDoubleArray => get_double_array_region),
107 | u16::SIG => go!(JCharArray => get_char_array_region),
108 | bool::SIG => {
109 let arr = <&JBooleanArray>::from(jobj.as_local());
110 let mut els = Vec::new();
111 els.resize(len, 0u8);
112 e.get_boolean_array_region(arr, 0, &mut els).unwrap_java(e);
113 els.into_iter()
114 .map(|b| {
115 let val = (b == jni::sys::JNI_TRUE).downcast_value(e);
116 T::upcast_value(e, val)
117 })
118 .collect()
119 },
120 | _ if jobj.is_instance_of::<Vec<java::lang::Object>>(e) => {
121 let mut vec = Vec::new();
122
123 (0..len).for_each(|ix| {
124 let obj = e.get_object_array_element(arr, ix as i32).unwrap_java(e);
125 vec.push(java::lang::Object::from_local(e, obj).upcast_to::<T>(e));
126 });
127
128 vec
129 },
130 | _ => {
131 let cls = e.get_object_class(&jobj).unwrap_java(e);
132 panic!("unknown array type {}",
133 java::lang::Object::from_local(e, cls).to_string(e));
134 },
135 }
136 }
137
138 fn downcast(self, e: &mut java::Env) -> java::lang::Object {
139 self.downcast_ref(e)
140 }
141
142 fn downcast_ref(&self, e: &mut java::Env) -> java::lang::Object {
143 macro_rules! go {
144 ($new_array:ident, $set_region:ident) => {{
145 let slice = self.as_slice();
146
147 let slice = unsafe { core::mem::transmute::<_, &[_]>(slice) };
157
158 let arr = e.$new_array(self.len() as i32).unwrap_java(e);
159 e.$set_region(&arr, 0, slice).unwrap_java(e);
160 java::lang::Object::from_local(e, arr)
161 }};
162 }
163
164 match T::SIG {
165 | i8::SIG => go!(new_byte_array, set_byte_array_region),
166 | i16::SIG => go!(new_short_array, set_short_array_region),
167 | i32::SIG => go!(new_int_array, set_int_array_region),
168 | i64::SIG => go!(new_long_array, set_long_array_region),
169 | f32::SIG => go!(new_float_array, set_float_array_region),
170 | f64::SIG => go!(new_double_array, set_double_array_region),
171 | u16::SIG => go!(new_char_array, set_char_array_region),
172 | bool::SIG => go!(new_boolean_array, set_boolean_array_region),
173 | _ => {
174 let arr = e.new_object_array(self.len() as i32, java::lang::Object::SIG, JObject::null())
175 .unwrap_java(e);
176 let arr_ref = &arr;
177 self.iter().enumerate().for_each(|(ix, o)| {
178 let val = o.downcast_ref(e);
179 e.set_object_array_element(arr_ref, ix as i32, &val)
180 .unwrap_java(e);
181 });
182
183 java::lang::Object::from_local(e, arr)
184 },
185 }
186 }
187}
188
189impl<T> Object for T where T: java::Primitive
190{
191 fn upcast(e: &mut java::Env, jobj: java::lang::Object) -> Self {
192 let w = <T as java::Primitive>::PrimitiveWrapper::upcast(e, jobj);
193 T::from_primitive_wrapper(e, w)
194 }
195
196 fn downcast(self, e: &mut java::Env) -> java::lang::Object {
197 self.to_primitive_wrapper(e).downcast(e)
198 }
199
200 fn downcast_ref(&self, e: &mut java::Env) -> java::lang::Object {
201 self.to_primitive_wrapper(e).downcast(e)
202 }
203
204 fn upcast_value_ref<'e>(_: &mut java::Env<'e>, jv: JValue<'e, '_>) -> Self
205 where Self: Sized
206 {
207 T::from_jvalue_ref(jv)
208 }
209
210 fn upcast_value(_: &mut java::Env, jv: JValueOwned) -> Self
211 where Self: Sized
212 {
213 T::from_jvalue(jv)
214 }
215
216 fn downcast_value<'e>(self, _: &mut java::Env<'e>) -> JValueOwned<'e>
217 where Self: Sized
218 {
219 self.into_jvalue()
220 }
221}
222
223impl Object for () {
224 fn upcast(_: &mut java::Env, _: java::lang::Object) -> Self {
225 ()
226 }
227
228 fn downcast(self, e: &mut java::Env) -> java::lang::Object {
229 java::lang::Object::from_local(e, JObject::null())
230 }
231
232 fn downcast_ref(&self, e: &mut java::Env) -> java::lang::Object {
233 ().downcast(e)
234 }
235
236 fn upcast_value_ref<'e>(_: &mut java::Env<'e>, jv: JValue<'e, '_>) -> Self
237 where Self: Sized
238 {
239 jv.v().unwrap()
240 }
241
242 fn upcast_value<'e>(_: &mut java::Env<'e>, jv: JValueOwned<'e>) -> Self
243 where Self: Sized
244 {
245 jv.v().unwrap()
246 }
247
248 fn downcast_value<'e>(self, _: &mut java::Env<'e>) -> JValueOwned<'e>
249 where Self: Sized
250 {
251 JValueOwned::Void
252 }
253}