1use std::any::Any;
16use std::convert::TryFrom;
17use std::ptr;
18
19use jni_sys::{jobject, JNIEnv};
20use serde::Serialize;
21
22use crate::api::instance::Instance;
23use crate::api::{JavaClass, Jvm, Null};
24use crate::{cache, errors, jni_utils, utils};
25
26#[derive(Serialize)]
28pub enum InvocationArg {
29 Java {
31 instance: Instance,
32 class_name: String,
33 serialized: bool,
34 },
35 Rust {
37 json: String,
38 class_name: String,
39 serialized: bool,
40 },
41 RustBasic {
45 instance: Instance,
46 class_name: String,
47 serialized: bool,
48 },
49}
50
51impl InvocationArg {
52
53 pub fn empty<'a>() -> &'a[InvocationArg;0] {
55 &[]
56 }
57
58 pub fn new<T>(arg: &T, class_name: &str) -> InvocationArg
61 where
62 T: Serialize + Any,
63 {
64 Self::new_2(
65 arg,
66 class_name,
67 cache::get_thread_local_env().expect("Could not find the jni_env in the local cache. Please make sure that you created a Jvm before using Jvm::new"))
68 .expect("Could not create the InvocationArg. Please see the logs/console for more details.")
69 }
70
71 pub fn new_2<T>(
72 arg: &T,
73 class_name: &str,
74 jni_env: *mut JNIEnv,
75 ) -> errors::Result<InvocationArg>
76 where
77 T: Serialize + Any,
78 {
79 let arg_any = arg as &dyn Any;
80 if let Some(a) = arg_any.downcast_ref::<String>() {
81 Ok(InvocationArg::RustBasic {
82 instance: Instance::new(
83 jni_utils::global_jobject_from_str(a, jni_env)?,
84 class_name,
85 )?,
86 class_name: class_name.to_string(),
87 serialized: false,
88 })
89 } else if let Some(a) = arg_any.downcast_ref::<i8>() {
90 Ok(InvocationArg::RustBasic {
91 instance: Instance::new(
92 jni_utils::global_jobject_from_i8(a, jni_env)?,
93 class_name,
94 )?,
95 class_name: class_name.to_string(),
96 serialized: false,
97 })
98 } else if let Some(a) = arg_any.downcast_ref::<i16>() {
99 Ok(InvocationArg::RustBasic {
100 instance: Instance::new(
101 jni_utils::global_jobject_from_i16(a, jni_env)?,
102 class_name,
103 )?,
104 class_name: class_name.to_string(),
105 serialized: false,
106 })
107 } else if let Some(a) = arg_any.downcast_ref::<u16>() {
108 Ok(InvocationArg::RustBasic {
109 instance: Instance::new(
110 jni_utils::global_jobject_from_u16(a, jni_env)?,
111 class_name,
112 )?,
113 class_name: class_name.to_string(),
114 serialized: false,
115 })
116 } else if let Some(a) = arg_any.downcast_ref::<i32>() {
117 Ok(InvocationArg::RustBasic {
118 instance: Instance::new(
119 jni_utils::global_jobject_from_i32(a, jni_env)?,
120 class_name,
121 )?,
122 class_name: class_name.to_string(),
123 serialized: false,
124 })
125 } else if let Some(a) = arg_any.downcast_ref::<i64>() {
126 Ok(InvocationArg::RustBasic {
127 instance: Instance::new(
128 jni_utils::global_jobject_from_i64(a, jni_env)?,
129 class_name,
130 )?,
131 class_name: class_name.to_string(),
132 serialized: false,
133 })
134 } else if let Some(a) = arg_any.downcast_ref::<f32>() {
135 Ok(InvocationArg::RustBasic {
136 instance: Instance::new(
137 jni_utils::global_jobject_from_f32(a, jni_env)?,
138 class_name,
139 )?,
140 class_name: class_name.to_string(),
141 serialized: false,
142 })
143 } else if let Some(a) = arg_any.downcast_ref::<f64>() {
144 Ok(InvocationArg::RustBasic {
145 instance: Instance::new(
146 jni_utils::global_jobject_from_f64(a, jni_env)?,
147 class_name,
148 )?,
149 class_name: class_name.to_string(),
150 serialized: false,
151 })
152 } else {
153 let json = serde_json::to_string(arg)?;
154 Ok(InvocationArg::Rust {
155 json,
156 class_name: class_name.to_string(),
157 serialized: true,
158 })
159 }
160 }
161
162 fn make_primitive(&mut self) -> errors::Result<()> {
163 match utils::primitive_of(self) {
164 Some(primitive_repr) => {
165 match *self {
166 InvocationArg::Java {
167 instance: _,
168 ref mut class_name,
169 serialized: _,
170 } => *class_name = primitive_repr,
171 InvocationArg::Rust {
172 json: _,
173 ref mut class_name,
174 serialized: _,
175 } => *class_name = primitive_repr,
176 InvocationArg::RustBasic {
177 instance: _,
178 ref mut class_name,
179 serialized: _,
180 } => *class_name = primitive_repr,
181 };
182 Ok(())
183 }
184 None => Err(errors::J4RsError::JavaError(format!(
185 "Cannot transform to primitive: {}",
186 utils::get_class_name(self)
187 ))),
188 }
189 }
190
191 pub fn into_primitive(self) -> errors::Result<InvocationArg> {
196 let mut ia = self;
197 ia.make_primitive()?;
198 Ok(ia)
199 }
200
201 pub fn as_java_ptr_with_global_ref(&self, jni_env: *mut JNIEnv) -> errors::Result<jobject> {
203 match self {
204 _s @ &InvocationArg::Java { .. } => {
205 jni_utils::invocation_arg_jobject_from_java(self, jni_env, true)
206 }
207 _s @ &InvocationArg::Rust { .. } => {
208 jni_utils::invocation_arg_jobject_from_rust_serialized(self, jni_env, true)
209 }
210 _s @ &InvocationArg::RustBasic { .. } => {
211 jni_utils::invocation_arg_jobject_from_rust_basic(self, jni_env, true)
212 }
213 }
214 }
215
216 pub fn as_java_ptr_with_local_ref(&self, jni_env: *mut JNIEnv) -> errors::Result<jobject> {
218 match self {
219 _s @ &InvocationArg::Java { .. } => {
220 jni_utils::invocation_arg_jobject_from_java(self, jni_env, false)
221 }
222 _s @ &InvocationArg::Rust { .. } => {
223 jni_utils::invocation_arg_jobject_from_rust_serialized(self, jni_env, false)
224 }
225 _s @ &InvocationArg::RustBasic { .. } => {
226 jni_utils::invocation_arg_jobject_from_rust_basic(self, jni_env, false)
227 }
228 }
229 }
230
231 pub fn instance(self) -> errors::Result<Instance> {
233 match self {
234 InvocationArg::Java { instance: i, .. } => Ok(i),
235 InvocationArg::RustBasic { .. } => Err(errors::J4RsError::RustError("Invalid operation: Cannot get the instance of an InvocationArg::RustBasic".to_string())),
236 InvocationArg::Rust { .. } => Err(errors::J4RsError::RustError("Cannot get the instance from an InvocationArg::Rust".to_string())),
237 }
238 }
239
240 pub fn class_name(&self) -> &str {
241 match self {
242 InvocationArg::Java {
243 instance: _,
244 class_name,
245 serialized: _,
246 } => class_name,
247 InvocationArg::Rust {
248 json: _,
249 class_name,
250 serialized: _,
251 } => class_name,
252 InvocationArg::RustBasic {
253 instance: _,
254 class_name,
255 serialized: _,
256 } => class_name,
257 }
258 }
259
260 pub fn create_null(null: Null) -> errors::Result<InvocationArg> {
262 let class_name: &str = match null {
263 Null::String => JavaClass::String,
264 Null::Boolean => JavaClass::Boolean,
265 Null::Byte => JavaClass::Byte,
266 Null::Character => JavaClass::Character,
267 Null::Short => JavaClass::Short,
268 Null::Integer => JavaClass::Integer,
269 Null::Long => JavaClass::Long,
270 Null::Float => JavaClass::Float,
271 Null::Double => JavaClass::Double,
272 Null::List => JavaClass::List,
273 Null::Of(class_name) => JavaClass::Of(class_name),
274 }
275 .into();
276 Ok(InvocationArg::RustBasic {
277 instance: Instance::new(ptr::null_mut(), class_name)?,
278 class_name: class_name.to_string(),
279 serialized: false,
280 })
281 }
282}
283
284impl From<Instance> for InvocationArg {
285 fn from(instance: Instance) -> InvocationArg {
286 let class_name = instance.class_name.to_owned();
287
288 InvocationArg::Java {
289 instance,
290 class_name,
291 serialized: false,
292 }
293 }
294}
295
296impl TryFrom<Result<Instance, errors::J4RsError>> for InvocationArg {
297 type Error = errors::J4RsError;
298
299 fn try_from(
300 instance_res: Result<Instance, errors::J4RsError>,
301 ) -> errors::Result<InvocationArg> {
302 Ok(InvocationArg::from(instance_res?))
303 }
304}
305
306impl<'a> TryFrom<Null<'a>> for InvocationArg {
307 type Error = errors::J4RsError;
308 fn try_from(null: Null) -> errors::Result<InvocationArg> {
309 InvocationArg::create_null(null)
310 }
311}
312
313impl TryFrom<String> for InvocationArg {
314 type Error = errors::J4RsError;
315 fn try_from(arg: String) -> errors::Result<InvocationArg> {
316 InvocationArg::new_2(
317 &arg,
318 JavaClass::String.into(),
319 cache::get_thread_local_env()?,
320 )
321 }
322}
323
324impl<'a> TryFrom<&'a [String]> for InvocationArg {
325 type Error = errors::J4RsError;
326 fn try_from(vec: &'a [String]) -> errors::Result<InvocationArg> {
327 let args: errors::Result<Vec<InvocationArg>> = vec
328 .iter()
329 .map(InvocationArg::try_from)
330 .collect();
331 let res =
332 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
333 Ok(InvocationArg::from(res?))
334 }
335}
336
337impl<'a> TryFrom<&'a str> for InvocationArg {
338 type Error = errors::J4RsError;
339 fn try_from(arg: &'a str) -> errors::Result<InvocationArg> {
340 InvocationArg::new_2(
341 &arg.to_string(),
342 JavaClass::String.into(),
343 cache::get_thread_local_env()?,
344 )
345 }
346}
347
348impl<'a> TryFrom<&'a [&'a str]> for InvocationArg {
349 type Error = errors::J4RsError;
350 fn try_from(vec: &'a [&'a str]) -> errors::Result<InvocationArg> {
351 let args: errors::Result<Vec<InvocationArg>> = vec
352 .iter()
353 .map(|&elem| InvocationArg::try_from(elem))
354 .collect();
355 let res =
356 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
357 Ok(InvocationArg::from(res?))
358 }
359}
360
361impl TryFrom<bool> for InvocationArg {
362 type Error = errors::J4RsError;
363 fn try_from(arg: bool) -> errors::Result<InvocationArg> {
364 InvocationArg::new_2(
365 &arg,
366 JavaClass::Boolean.into(),
367 cache::get_thread_local_env()?,
368 )
369 }
370}
371
372impl<'a> TryFrom<&'a [bool]> for InvocationArg {
373 type Error = errors::J4RsError;
374 fn try_from(vec: &'a [bool]) -> errors::Result<InvocationArg> {
375 let args: errors::Result<Vec<InvocationArg>> = vec
376 .iter()
377 .map(InvocationArg::try_from)
378 .collect();
379 let res =
380 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
381 Ok(InvocationArg::from(res?))
382 }
383}
384
385impl TryFrom<i8> for InvocationArg {
386 type Error = errors::J4RsError;
387 fn try_from(arg: i8) -> errors::Result<InvocationArg> {
388 InvocationArg::new_2(&arg, JavaClass::Byte.into(), cache::get_thread_local_env()?)
389 }
390}
391
392impl<'a> TryFrom<&'a [i8]> for InvocationArg {
393 type Error = errors::J4RsError;
394 fn try_from(vec: &'a [i8]) -> errors::Result<InvocationArg> {
395 let args: errors::Result<Vec<InvocationArg>> = vec
396 .iter()
397 .map(InvocationArg::try_from)
398 .collect();
399 let res =
400 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
401 Ok(InvocationArg::from(res?))
402 }
403}
404
405impl TryFrom<char> for InvocationArg {
406 type Error = errors::J4RsError;
407 fn try_from(arg: char) -> errors::Result<InvocationArg> {
408 InvocationArg::new_2(
409 &arg,
410 JavaClass::Character.into(),
411 cache::get_thread_local_env()?,
412 )
413 }
414}
415
416impl<'a> TryFrom<&'a [char]> for InvocationArg {
417 type Error = errors::J4RsError;
418 fn try_from(vec: &'a [char]) -> errors::Result<InvocationArg> {
419 let args: errors::Result<Vec<InvocationArg>> = vec
420 .iter()
421 .map(InvocationArg::try_from)
422 .collect();
423 let res =
424 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
425 Ok(InvocationArg::from(res?))
426 }
427}
428
429impl TryFrom<i16> for InvocationArg {
430 type Error = errors::J4RsError;
431 fn try_from(arg: i16) -> errors::Result<InvocationArg> {
432 InvocationArg::new_2(
433 &arg,
434 JavaClass::Short.into(),
435 cache::get_thread_local_env()?,
436 )
437 }
438}
439
440impl<'a> TryFrom<&'a [i16]> for InvocationArg {
441 type Error = errors::J4RsError;
442 fn try_from(vec: &'a [i16]) -> errors::Result<InvocationArg> {
443 let args: errors::Result<Vec<InvocationArg>> = vec
444 .iter()
445 .map(InvocationArg::try_from)
446 .collect();
447 let res =
448 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
449 Ok(InvocationArg::from(res?))
450 }
451}
452
453impl TryFrom<u16> for InvocationArg {
454 type Error = errors::J4RsError;
455 fn try_from(arg: u16) -> errors::Result<InvocationArg> {
456 InvocationArg::new_2(
457 &arg,
458 JavaClass::Character.into(),
459 cache::get_thread_local_env()?,
460 )
461 }
462}
463
464impl<'a> TryFrom<&'a [u16]> for InvocationArg {
465 type Error = errors::J4RsError;
466 fn try_from(vec: &'a [u16]) -> errors::Result<InvocationArg> {
467 let args: errors::Result<Vec<InvocationArg>> = vec
468 .iter()
469 .map(InvocationArg::try_from)
470 .collect();
471 let res =
472 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
473 Ok(InvocationArg::from(res?))
474 }
475}
476
477impl TryFrom<i32> for InvocationArg {
478 type Error = errors::J4RsError;
479 fn try_from(arg: i32) -> errors::Result<InvocationArg> {
480 InvocationArg::new_2(
481 &arg,
482 JavaClass::Integer.into(),
483 cache::get_thread_local_env()?,
484 )
485 }
486}
487
488impl<'a> TryFrom<&'a [i32]> for InvocationArg {
489 type Error = errors::J4RsError;
490 fn try_from(vec: &'a [i32]) -> errors::Result<InvocationArg> {
491 let args: errors::Result<Vec<InvocationArg>> = vec
492 .iter()
493 .map(InvocationArg::try_from)
494 .collect();
495 let res =
496 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
497 Ok(InvocationArg::from(res?))
498 }
499}
500
501impl TryFrom<i64> for InvocationArg {
502 type Error = errors::J4RsError;
503 fn try_from(arg: i64) -> errors::Result<InvocationArg> {
504 InvocationArg::new_2(&arg, JavaClass::Long.into(), cache::get_thread_local_env()?)
505 }
506}
507
508impl<'a> TryFrom<&'a [i64]> for InvocationArg {
509 type Error = errors::J4RsError;
510 fn try_from(vec: &'a [i64]) -> errors::Result<InvocationArg> {
511 let args: errors::Result<Vec<InvocationArg>> = vec
512 .iter()
513 .map(InvocationArg::try_from)
514 .collect();
515 let res =
516 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
517 Ok(InvocationArg::from(res?))
518 }
519}
520
521impl TryFrom<f32> for InvocationArg {
522 type Error = errors::J4RsError;
523 fn try_from(arg: f32) -> errors::Result<InvocationArg> {
524 InvocationArg::new_2(
525 &arg,
526 JavaClass::Float.into(),
527 cache::get_thread_local_env()?,
528 )
529 }
530}
531
532impl<'a> TryFrom<&'a [f32]> for InvocationArg {
533 type Error = errors::J4RsError;
534 fn try_from(vec: &'a [f32]) -> errors::Result<InvocationArg> {
535 let args: errors::Result<Vec<InvocationArg>> = vec
536 .iter()
537 .map(InvocationArg::try_from)
538 .collect();
539 let res =
540 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
541 Ok(InvocationArg::from(res?))
542 }
543}
544
545impl TryFrom<f64> for InvocationArg {
546 type Error = errors::J4RsError;
547 fn try_from(arg: f64) -> errors::Result<InvocationArg> {
548 InvocationArg::new_2(
549 &arg,
550 JavaClass::Double.into(),
551 cache::get_thread_local_env()?,
552 )
553 }
554}
555
556impl<'a> TryFrom<&'a [f64]> for InvocationArg {
557 type Error = errors::J4RsError;
558 fn try_from(vec: &'a [f64]) -> errors::Result<InvocationArg> {
559 let args: errors::Result<Vec<InvocationArg>> = vec
560 .iter()
561 .map(InvocationArg::try_from)
562 .collect();
563 let res =
564 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
565 Ok(InvocationArg::from(res?))
566 }
567}
568
569impl TryFrom<()> for InvocationArg {
570 type Error = errors::J4RsError;
571 fn try_from(arg: ()) -> errors::Result<InvocationArg> {
572 InvocationArg::new_2(&arg, JavaClass::Void.into(), cache::get_thread_local_env()?)
573 }
574}
575
576impl<'a> TryFrom<&'a String> for InvocationArg {
577 type Error = errors::J4RsError;
578 fn try_from(arg: &'a String) -> errors::Result<InvocationArg> {
579 InvocationArg::new_2(
580 arg,
581 JavaClass::String.into(),
582 cache::get_thread_local_env()?,
583 )
584 }
585}
586
587impl<'a> TryFrom<&'a bool> for InvocationArg {
588 type Error = errors::J4RsError;
589 fn try_from(arg: &'a bool) -> errors::Result<InvocationArg> {
590 InvocationArg::new_2(
591 arg,
592 JavaClass::Boolean.into(),
593 cache::get_thread_local_env()?,
594 )
595 }
596}
597
598impl<'a> TryFrom<&'a i8> for InvocationArg {
599 type Error = errors::J4RsError;
600 fn try_from(arg: &'a i8) -> errors::Result<InvocationArg> {
601 InvocationArg::new_2(arg, JavaClass::Byte.into(), cache::get_thread_local_env()?)
602 }
603}
604
605impl<'a> TryFrom<&'a char> for InvocationArg {
606 type Error = errors::J4RsError;
607 fn try_from(arg: &'a char) -> errors::Result<InvocationArg> {
608 InvocationArg::new_2(
609 arg,
610 JavaClass::Character.into(),
611 cache::get_thread_local_env()?,
612 )
613 }
614}
615
616impl<'a> TryFrom<&'a i16> for InvocationArg {
617 type Error = errors::J4RsError;
618 fn try_from(arg: &'a i16) -> errors::Result<InvocationArg> {
619 InvocationArg::new_2(arg, JavaClass::Short.into(), cache::get_thread_local_env()?)
620 }
621}
622
623impl<'a> TryFrom<&'a u16> for InvocationArg {
624 type Error = errors::J4RsError;
625 fn try_from(arg: &'a u16) -> errors::Result<InvocationArg> {
626 InvocationArg::new_2(arg, JavaClass::Character.into(), cache::get_thread_local_env()?)
627 }
628}
629
630impl<'a, 'b> TryFrom<&'a i32> for InvocationArg {
631 type Error = errors::J4RsError;
632 fn try_from(arg: &'a i32) -> errors::Result<InvocationArg> {
633 InvocationArg::new_2(
634 arg,
635 JavaClass::Integer.into(),
636 cache::get_thread_local_env()?,
637 )
638 }
639}
640
641impl<'a> TryFrom<&'a i64> for InvocationArg {
642 type Error = errors::J4RsError;
643 fn try_from(arg: &'a i64) -> errors::Result<InvocationArg> {
644 InvocationArg::new_2(arg, JavaClass::Long.into(), cache::get_thread_local_env()?)
645 }
646}
647
648impl<'a> TryFrom<&'a f32> for InvocationArg {
649 type Error = errors::J4RsError;
650 fn try_from(arg: &'a f32) -> errors::Result<InvocationArg> {
651 InvocationArg::new_2(arg, JavaClass::Float.into(), cache::get_thread_local_env()?)
652 }
653}
654
655impl<'a> TryFrom<&'a f64> for InvocationArg {
656 type Error = errors::J4RsError;
657 fn try_from(arg: &'a f64) -> errors::Result<InvocationArg> {
658 InvocationArg::new_2(
659 arg,
660 JavaClass::Double.into(),
661 cache::get_thread_local_env()?,
662 )
663 }
664}
665
666impl<'a, T: 'static> TryFrom<(&'a [T], &'a str)> for InvocationArg
667 where
668 T: Serialize,
669{
670 type Error = errors::J4RsError;
671 fn try_from(vec: (&'a [T], &'a str)) -> errors::Result<InvocationArg> {
672 let (vec, elements_class_name) = vec;
673 let jni_env = cache::get_thread_local_env()?;
674 let args: errors::Result<Vec<InvocationArg>> = vec
675 .iter()
676 .map(|elem| {
677 InvocationArg::new_2(elem, JavaClass::Of(elements_class_name).into(), jni_env)
678 })
679 .collect();
680 let res =
681 Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
682 Ok(InvocationArg::from(res?))
683 }
684}
685
686impl TryFrom<Result<InvocationArg, errors::J4RsError>> for InvocationArg {
687 type Error = errors::J4RsError;
688 fn try_from(arg: Result<InvocationArg, errors::J4RsError>) -> errors::Result<InvocationArg> {
689 arg
690 }
691}
692
693#[cfg(test)]
694mod inv_arg_unit_tests {
695 use serde::Deserialize;
696
697 use super::*;
698 use crate::lib_unit_tests::create_tests_jvm;
699 use crate::errors;
700
701 #[test]
702 fn new_invocation_arg() -> errors::Result<()> {
703 let _jvm = create_tests_jvm()?;
704 let _ = InvocationArg::new(&"something".to_string(), "somethingelse");
705
706 Ok(())
707 }
708
709 #[test]
710 fn invocation_arg_try_from_basic_types() -> errors::Result<()> {
711 let _jvm = create_tests_jvm()?;
712 validate_type(InvocationArg::try_from("str")?, "java.lang.String");
713 validate_type(
714 InvocationArg::try_from("str".to_string())?,
715 "java.lang.String",
716 );
717 validate_type(InvocationArg::try_from(true)?, "java.lang.Boolean");
718 validate_type(InvocationArg::try_from(1_i8)?, "java.lang.Byte");
719 validate_type(InvocationArg::try_from('c')?, "java.lang.Character");
720 validate_type(InvocationArg::try_from(1_i16)?, "java.lang.Short");
721 validate_type(InvocationArg::try_from(1_i64)?, "java.lang.Long");
722 validate_type(InvocationArg::try_from(0.1_f32)?, "java.lang.Float");
723 validate_type(
724 InvocationArg::try_from(0.1_f64)?,
725 "java.lang.Double",
726 );
727 validate_type(InvocationArg::try_from(())?, "void");
728
729 validate_type(
730 InvocationArg::try_from(&"str".to_string())?,
731 "java.lang.String",
732 );
733 validate_type(InvocationArg::try_from("str")?, "java.lang.String");
734 validate_type(InvocationArg::try_from(&true)?, "java.lang.Boolean");
735 validate_type(InvocationArg::try_from(&1_i8)?, "java.lang.Byte");
736 validate_type(
737 InvocationArg::try_from(&'c')?,
738 "java.lang.Character",
739 );
740 validate_type(InvocationArg::try_from(&1_i16)?, "java.lang.Short");
741 validate_type(InvocationArg::try_from(&1_i64)?, "java.lang.Long");
742 validate_type(
743 InvocationArg::try_from(&0.1_f32)?,
744 "java.lang.Float",
745 );
746 validate_type(
747 InvocationArg::try_from(&0.1_f64)?,
748 "java.lang.Double",
749 );
750
751 Ok(())
752 }
753
754 #[test]
755 fn invocation_into_primitive() -> errors::Result<()> {
756 let _jvm: Jvm = create_tests_jvm()?;
757 assert!(InvocationArg::try_from(false)?
758 .into_primitive()
759 .is_ok());
760 assert!(InvocationArg::try_from(1_i8)?
761 .into_primitive()
762 .is_ok());
763 assert!(InvocationArg::try_from(1_i16)?
764 .into_primitive()
765 .is_ok());
766 assert!(InvocationArg::try_from(1_i32)?
767 .into_primitive()
768 .is_ok());
769 assert!(InvocationArg::try_from(1_i64)?
770 .into_primitive()
771 .is_ok());
772 assert!(InvocationArg::try_from(0.1_f32)?
773 .into_primitive()
774 .is_ok());
775 assert!(InvocationArg::try_from(0.1_f64)?
776 .into_primitive()
777 .is_ok());
778 assert!(InvocationArg::try_from('c')?
779 .into_primitive()
780 .is_ok());
781 assert!(InvocationArg::try_from(())?
782 .into_primitive()
783 .is_ok());
784 assert!(InvocationArg::try_from("string")?
785 .into_primitive()
786 .is_err());
787
788 Ok(())
789 }
790
791 #[test]
792 fn invocation_arg_for_custom_types() -> errors::Result<()> {
793 let jvm = create_tests_jvm()?;
794
795 let my_bean = MyBean {
796 someString: "My String In A Bean".to_string(),
797 someInteger: 33,
798 };
799 let ia = InvocationArg::new(&my_bean, "org.astonbitecode.j4rs.tests.MyBean");
800
801 let test_instance = jvm.create_instance("org.astonbitecode.j4rs.tests.MyTest", InvocationArg::empty())?;
802 let string_instance = jvm.invoke(&test_instance, "getTheString", &[ia]).unwrap();
803
804 let rust_string: String = jvm.to_rust(string_instance).unwrap();
805
806 assert!(&rust_string == "My String In A Bean");
807
808 Ok(())
809 }
810
811 #[derive(Serialize, Deserialize, Debug)]
812 #[allow(non_snake_case)]
813 struct MyBean {
814 someString: String,
815 someInteger: isize,
816 }
817
818 fn validate_type(ia: InvocationArg, class: &str) {
819 let b = match ia {
820 _s @ InvocationArg::Java { .. } => false,
821 InvocationArg::Rust {
822 class_name,
823 json: _,
824 ..
825 } => class == class_name,
826 InvocationArg::RustBasic {
827 instance: _,
828 class_name,
829 serialized: _,
830 } => class == class_name,
831 };
832 assert!(b);
833 }
834}