1use typed_jni_core::{Arg, JNIEnv, MethodID, StrongRef};
2
3use crate::{LocalObject, ObjectType, TypedRef, builtin::JavaThrowable};
4
5pub unsafe trait Target<'env>: Sized {
19 unsafe fn call<const STATIC: bool, const N_ARGS: usize, T: StrongRef>(
25 env: &'env JNIEnv,
26 this: &T,
27 method: MethodID<STATIC>,
28 args: [Arg<'_>; N_ARGS],
29 ) -> Result<Self, LocalObject<'env, JavaThrowable>>;
30
31 unsafe fn call_variadic<'a, const STATIC: bool, T: StrongRef, Args: IntoIterator<Item = Arg<'a>>>(
37 env: &'env JNIEnv,
38 this: &T,
39 method: MethodID<STATIC>,
40 args: Args,
41 ) -> Result<Self, LocalObject<'env, JavaThrowable>>;
42}
43
44macro_rules! impl_target_for_primitive {
45 ($ty:ty, $call:ident, $call_variadic:ident) => {
46 unsafe impl<'env> Target<'env> for $ty {
47 unsafe fn call<const STATIC: bool, const N_ARGS: usize, T: StrongRef>(
48 env: &'env JNIEnv,
49 this: &T,
50 method: MethodID<STATIC>,
51 args: [Arg<'_>; N_ARGS],
52 ) -> Result<Self, LocalObject<'env, JavaThrowable>> {
53 unsafe { env.$call(this, method, args).map_err(|err| LocalObject::from_ref(err)) }
54 }
55
56 unsafe fn call_variadic<'a, const STATIC: bool, T: StrongRef, Args: IntoIterator<Item = Arg<'a>>>(
57 env: &'env JNIEnv,
58 this: &T,
59 method: MethodID<STATIC>,
60 args: Args,
61 ) -> Result<Self, LocalObject<'env, JavaThrowable>> {
62 unsafe {
63 env.$call_variadic(this, method, args)
64 .map_err(|err| LocalObject::from_ref(err))
65 }
66 }
67 }
68 };
69}
70
71impl_target_for_primitive!((), call_void_method, call_void_method_variadic);
72impl_target_for_primitive!(bool, call_boolean_method, call_boolean_method_variadic);
73impl_target_for_primitive!(i8, call_byte_method, call_byte_method_variadic);
74impl_target_for_primitive!(u16, call_char_method, call_char_method_variadic);
75impl_target_for_primitive!(i16, call_short_method, call_short_method_variadic);
76impl_target_for_primitive!(i32, call_int_method, call_int_method_variadic);
77impl_target_for_primitive!(i64, call_long_method, call_long_method_variadic);
78impl_target_for_primitive!(f32, call_float_method, call_float_method_variadic);
79impl_target_for_primitive!(f64, call_double_method, call_double_method_variadic);
80
81macro_rules! impl_target_for_object {
82 ($ty:ty, $ret:ident, $transform:block) => {
83 unsafe impl<'env, Type: ObjectType> Target<'env> for $ty {
84 unsafe fn call<const STATIC: bool, const N_ARGS: usize, T: StrongRef>(
85 env: &'env JNIEnv,
86 this: &T,
87 method: MethodID<STATIC>,
88 args: [Arg<'_>; N_ARGS],
89 ) -> Result<Self, LocalObject<'env, JavaThrowable>> {
90 unsafe {
91 env.call_object_method(this, method, args)
92 .map(|$ret| $transform)
93 .map_err(|err| LocalObject::from_ref(err))
94 }
95 }
96
97 unsafe fn call_variadic<'a, const STATIC: bool, T: StrongRef, Args: IntoIterator<Item = Arg<'a>>>(
98 env: &'env JNIEnv,
99 this: &T,
100 method: MethodID<STATIC>,
101 args: Args,
102 ) -> Result<Self, LocalObject<'env, JavaThrowable>> {
103 unsafe {
104 env.call_object_method_variadic(this, method, args)
105 .map(|$ret| $transform)
106 .map_err(|err| LocalObject::from_ref(err))
107 }
108 }
109 }
110 };
111}
112
113impl_target_for_object!(Option<LocalObject<'env, Type>>, ret, {
114 ret.map(|v| LocalObject::from_ref(v))
115});
116impl_target_for_object!(LocalObject<'env, Type>, ret, {
117 LocalObject::from_ref(ret.expect("call returning null"))
118});
119
120pub struct NewObject<'env, T: ObjectType>(pub LocalObject<'env, T>);
121
122unsafe impl<'env, Type: ObjectType> Target<'env> for NewObject<'env, Type> {
123 unsafe fn call<const STATIC: bool, const N_ARGS: usize, T: StrongRef>(
124 env: &'env JNIEnv,
125 this: &T,
126 method: MethodID<STATIC>, args: [Arg<'_>; N_ARGS],
128 ) -> Result<Self, LocalObject<'env, JavaThrowable>> {
129 unsafe {
130 env.new_object(this, core::mem::transmute::<MethodID<STATIC>, MethodID<false>>(method), args)
131 .map(|v| Self(LocalObject::from_ref(v)))
132 .map_err(|err| LocalObject::from_ref(err))
133 }
134 }
135
136 unsafe fn call_variadic<'a, const STATIC: bool, T: StrongRef, Args: IntoIterator<Item = Arg<'a>>>(
137 env: &'env JNIEnv,
138 this: &T,
139 method: MethodID<STATIC>, args: Args,
141 ) -> Result<Self, LocalObject<'env, JavaThrowable>> {
142 unsafe {
143 env.new_object_variadic(this, core::mem::transmute::<MethodID<STATIC>, MethodID<false>>(method), args)
144 .map(|v| Self(LocalObject::from_ref(v)))
145 .map_err(|err| LocalObject::from_ref(err))
146 }
147 }
148}